Class relationships are really important and noone wants a "complicated" one. Now although grammar does help sometimes it is still hard to decide which class should relate to which thus you end up not thinking too much about it and dump them on a need to have basis.
One way to think of classes is in terms of the object state they enforce. So in essence you have classes of two kinds. Muttable (the value of its fields can change) and immutable (you can tell from their final fields [Disclaimer]). It's good practice not to mix the two since mixing a mutable with an immutable will give you a mutable one at the end :(.
The reason you should strive to design immutable classes is that are easier to maintain, (no state to worry about!) encourage reusability (objects are effectively constants!) and last but not least are thread safe. (woohoo, no concurrency bugs!)
Let's take a look at the survival kit to identify classes that qualify for immutable. The text talks about 2 distinct shipping methods. USCANADA and INTERNATIONAL. See a pattern here? With ShippingMethod as your class, you can have 2 objects, one for USCANADA and second one for INTERNATIONAL. Yes constants (use CAPITAL to get your point across). In Java you can use an Enum for defining constants.
- Start with private final fields.
- Don't have (possible) immutable classes with mutable properties.
- Make constants out of your immutable classes and reuse them.
There is still a long way to go before we start sending survival kits out, so leave your feedback below on how you would specify any further class relationships, now that you have acquired that extra knowledge.
Also, Misko Hevery gives you another clue as to how to think about your class relatiosnhips when it comes to dependency injection
Disclaimer: Not strictly true. final is about not changing the reference of an object while the object itself might still change. Take an array for example, though you might not be able to assign a different one, you can still change its contents. Kudoz: Misko Hevery