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.
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.
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.
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?
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 shouldnever 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.
- 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.
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.
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
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.
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.
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.
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?
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.
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).
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?
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?
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.
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?
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?
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.
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?
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?
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 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 by:autobot
What a stench! Central nervous system shutting down. Save yourself tiny ad!
a bit of art, as a gift, that will fit in a stocking