• Post Reply Bookmark Topic Watch Topic
  • New Topic

Designing an address book in Java  RSS feed

 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am designing an address book. I have come up with the following design:

Address Book:
Attributes : Entry
Methods: add(), delete(), search()

Entry:
Attributes : Name, Address, Phone Number
Methods: addName(),editName(),deleteName(),addPhone(),editPhone(),deletePhone(),addAddress(),editAddress(),deleteAddress()

Name:
Attributes: firstName, lastName

PhoneNumber:
Attributes:areaCode, phoneNumber

Address:
Attributes:streetNumber,streetName,city,zip.

Please review and comment on the design.



 
Stephan van Hulst
Saloon Keeper
Posts: 7973
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In your Entry class, I would probably just use setters and getters. Deleting an attribute is then equivalent to setAttribute(null). For the rest it looks decent.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks. So my methods would be getName(), setName(Name n), getPhone(), setPhone(PhoneNumber num), getAddress(), setAddress(Address addr)

So, instead of a valid name, the user has to pass null to the setName() method to delete the name? Is passing null to a method acceptable?
 
Stephan van Hulst
Saloon Keeper
Posts: 7973
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Absolutely. Even though null means as much as "no value", you can still assign a meaning to it. In your method's contract, explain to the user what it means to pass null into a method. In this case, it means to delete the name/phone number/address.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, thank you
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you are designing the address book the wrong way. You are going on about the details of what to enter, but you have not apparently designed the general structure of the address book.
Then you can add things like phone number, street and postal code/zip to the entry; You can even alter the entry later: for example you can have friends in different countries so you can add country code to the phone number.
Design the general strcuture of the address book first, then add those details later.

I do not like nulls, but there are some places where they are unavoidable, so you have to allow for them in your design, as Stephan said. As an alternative to making the address null, you can use a data structure which has a method like remove(), and use that in your delete() method.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Campbell. Do you mean I should think about how I will store my entries? Think about what data structure I'll be using? Or, are there other things that I'm missing in an address book?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:I do not like nulls...

Me neither, but I suspect it's because I'm an ornery old database guy, and they violate third normal form (and very often a few lower ones too); but I understand that they are sometimes a necessary evil (or kludge ) in designing program structures.

@Saikrishnan: One of the things to think about is: What causes an address entry to be created?

That will hopefully point you as to what its key should be; and keys should always be required. Off the top of my head, I'd say that it should probably be the name, so you should never be able to delete that, no matter how you implement "deletion", without deleting the entire entry from the address book. Keys should also generally not be changed, so if you find yourself needing to do that, you should think about a delete→add operation.

HIH (and there's a lot to know about this stuff )

Winston
 
Mohamed Sanaulla
Bartender
Posts: 3185
34
Google App Engine Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
- An AdressBook will have a collection of different entries so you might want to update the design of AddressBook class.
- Try to follow JavaBean naming convention.
- If you see that the attribute can be updated/modified then provide a setter method for the attribute otherwise if you find that the attribute is initialized with a value once in the constructor and never modified there after then you need not provide the setter method for the attribute.

 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Saikrishnan Srivatsan wrote:Thanks Campbell. Do you mean I should think about how I will store my entries? Think about what data structure I'll be using? Or, are there other things that I'm missing in an address book?
You're welcome

Yes, how are you going to store the entries and what sort of data structure?
Remember, you can amend the Address class very easily if necessary.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought I'd store my entries like this:

HashMap<Name,Entry> entries = new HashMap<Name, Entry>();
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Saikrishnan Srivatsan wrote:I thought I'd store my entries like this:
HashMap<Name,Entry> entries = new HashMap<Name, Entry>();

Seems reasonable, but then the question begs: Should Name be part of an Entry? Maybe, but it's worth thinking about.

Winston
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Saikrishnan Srivatsan wrote:I thought I'd store my entries like this:
That's good, but it should be:-

Map<Name,Entry> entries = new HashMap<Name, Entry>();

Make sure the Name class is immutable. Entry is a bad name because a Map already has a nested interface called Entry.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:it should be:-
Map<Name,Entry> entries = new HashMap<Name, Entry>();

I understand the concept of dynamic look-up that Java does but haven't come across a real life example to understand why I really need to declare things the one above as the super type. Is this something that someone can explain or maybe point me to other threads where this has been discussed? I can't understand here whyis bad
 
Michael Gomez
Greenhorn
Posts: 27
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Saikrishnan Srivatsan wrote:
Campbell Ritchie wrote:it should be:-
Map<Name,Entry> entries = new HashMap<Name, Entry>();

I understand the concept of dynamic look-up that Java does but haven't come across a real life example to understand why I really need to declare things the one above as the super type. Is this something that someone can explain or maybe point me to other threads where this has been discussed? I can't understand here whyis bad


its a good idea to code to interfaces instead of implementations, this allows more flexibility in your code since you can swap out the HashMap for a different subclass without major refactoring.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Michael. I still don't understand this Why will I not be able to change if I have the implementing type instead of the interface type?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you change the implementation rather than the interface your changes are very slight:-… can be changed to LinkedList or Vector by changing one word and everything else will work.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Saikrishnan Srivatsan wrote:Why will I not be able to change if I have the implementing type instead of the interface type?

You will be able to change it - you can re-write an entire program (or indeed, application) if you want to - but the change is likely to be much more extensive (and therefore error-prone) because you will have to change every place that relies on that implementation.

If you use an interface - eg, List, as in the examples you've been shown - everywhere except the place that you actually initialize, then you can change the implementation for the entire program by simply choosing another class that implements List.

HIH

Winston
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have come up with the following list of classes, attributes and methods after making minor modifications.

My idea is, when a user wants to add a new contact, the address book creates an empty contact object and returns it. The user has to use this object to set the Name and Phone number using setName() and the setPhoneNumber() methods in Contact rather than using the getters and setters in Name, directly. Is this acceptable?

AddressBook
Attributes - Map<Name, Contact>contacts, int size
Methods - Contact createContact(), void saveContact(Contact), void removeContact(Contact), int getSize(), void displayContacts(),
Contact searchByName(), Contact searchByPhoneNumber()

Contact
Attributes - Name name, String phoneNumber
Methods - Name getName(), String getPhoneNumber(), void setName(String firstName, String lastName), void setPhoneNumber(String phoneNumber)

Name
Attributes - String firstName, String lastName
Methods - String getFirstName(), String getLastName(), void setFirstName(String firstName), setLastName(String lastName)

 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How does search by phone number work? That looks interesting.

I would prefer to have a name in every Entry; avoid nulls like the plague. So I would set up the name and as many other fields as possible in the constructor.
You will have to decide what to do with nulls because everynow and then you will find people who lack a certain detail (e.g. phone number) or where you don't know it, so you may find nulls are unavoidable.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Even though I return an empty Contact object to the user at first, I plan to check for null once he updates the contact object and requests that it be added to the address book by calling saveContact(Contact).
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell, I don't understand why you say it will propagate nulls. Is using the constructor to get the first and last names, then constructing a Name object better than doing it via a method in the Address book class?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I didn't say it would propagate nulls; I said that nulls would be unavoidable and you would have to work out how to handle them.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you. If I check for nulls before adding to my hashmap, is my design right? Are there things in my design that are flawed or are there things that I've missed?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't know; I haven't read the whole thread carefully.
Yes, you are right to check for nulls before letting anything into the Map. But the way I see it, that implies that non‑nullity (for some fields) is an invariant of the Entry class, so the Entry class or the Address class should monitor their own fields (or some of them) for nullity.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you. My Contact class has a Name field.

Name has firstName and lastName as attributes.

Should I expose the Name class to the user, let him create a name object, then pass it to the Contact constructor or have the Contact constructor take 2 strings for first name and last name and then make a name object from there?
 
Paul Clapham
Sheriff
Posts: 22828
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's a good question. One response to it is "Well, why do you need a Name class anyway? Why not just let the Contact object contain the first and last names?" And then one response to that is "Because I might want to have more than one Contact for a Name."

I don't know whether either of those responses are valid in your case, but it does highlight the fact that your data design is not quite complete. Is the relationship between Contact and Name to be one-to-one, or one-to-many, or even many-to-many?
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Paul. I actually didn't even think about the relationship between Contact and Name when I wrote the Name class, but I think that I will permit more than one contact for a name. I have a few questions now:

1) If I want to store only one contact against a name, can I just have first and last name fields as strings in the Contact class and then have the user pass them to the constructor? I thought having Strings here was bad.

2)
Paul Clapham wrote:"Well, why do you need a Name class anyway? Why not just let the Contact object contain the first and last names?" And then one response to that is "Because I might want to have more than one Contact for a Name."
If I have a Name class, how can I allow multiple contacts to be stored against a name? I am not able to override my hashcode() and equals() appropriately to make this work.

 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can have a List<XXX> as the “V” of a Map.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:You can have a List<XXX> as the “V” of a Map.
Thank you, Campbell. I still don't need a Name class to do this, correct?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not certain, but I think you probably will need a Name class. You can have a name field in the address book entry.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought I could have first name and last name fields, and then pass as key to the Map.
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So what happens when you have saikrishnan srivatsan and saikrish nansrivatsan both in the same address book?
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, I meant Will this work without the need for a Name class?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you allow for all combinations of middle name, etc., it should work, yes.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you. Now, suppose I have the following entry in my address book:

Andrew Smith - 00000
Andrew Smith - 11111

The above entry would be stored with "Andrew Smith" as key and the value would be a "list" containing the 2 items above.

Suppose the user wants to change the phone number "00000" to "22222"; how do I manage that edit operation? Can I return a Contact object in the searchByName() method, then have him change that Contact object directly by having a public setPhoneNumber() method in the Contact class?
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've coded the Name and Contact classes. I am not happy with the way I've coded the Contact constructor, but I am not able to think of any other way to do it Can someone kindly review the design?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why do you have public classes with package‑private constructors?
If you have a Name class, why are you not using it in Contact? In that case the validation should be done in Contact Name.
I like the way you are validating names, but surely you would throw an IllegalArgumentException?
Don't you have a PhoneNumber class?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry. made a mistake and had to change Contact to Name.
 
Saikrishnan Srivatsan
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for your response, Campbell.
Campbell Ritchie wrote:Why do you have public classes with package‑private constructors?
I'll make the constructors public as well.
Campbell Ritchie wrote:If you have a Name class, why are you not using it in Contact? In that case the validation should be done in Contact Name.
OK, here's where I was a bit confused. So, is it OK to expose the Name class to the user? If I had a PhoneNumber class, then I'd expose that too? Basically, the user would first use all my "attribute" classes to construct the "attribute" objects and then call the Contact constructor to pass Name, PhoneNumber etc.?
Campbell Ritchie wrote:I like the way you are validating names, but surely you would throw an IllegalArgumentException?
I thought I should be creating my own custom exceptions here. In what cases should I be creating custom exceptions then?
Campbell Ritchie wrote:Don't you have a PhoneNumber class?
I am planning to have one, but I wanted to confirm that I was on the right track before doing too much code.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!