An example might be wrapping Collection<Subscriber> in a Subscribers type, rather than passing around the collection. I usually find that these wrapper objects start to attract related behaviour, rather than having actions on the collection scattered around the code. One clue is when I get to three levels of angle bracket :)
S.
As a side point, I wouldn't recommend mocking an ArrayList either. It's simpler just to use a real one and it doesn't help to discover domain collaborations.
S.
Steve Freeman
Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com
+44 797 179 4105
Twitter: @sf105
Higher Order Logic Limited
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 7522677
S.
On Sat, Apr 21, 2012 at 11:06 PM, Chuck Krutsinger
<chuck.kr...@gmail.com> wrote:
>
> "Encapsulate Collections - We've developed a habit of packaging up
> common types, such as Collections, in our own classes, even though
> Java generics avoid the need to cast objects…"
I use a couple of rules to help steer me in the right direction:
1. Never pass a collection as a method parameter or return value
2. Any class that has a collection as an instance variable must have
no other instance variables.
These aren't hard guidelines, but they do push me towards wrapping
most collections in a class. That class will only have methods that
correspond to the ways it is actually used, and will generally not
expose the collection at all.
Cheers,
Kevin
--
http://www.kevinrutherford.co.uk
http://myonepage.com/kevinrutherford
+44 (0) 797 356 3521
Jimmy Nilsson in his "Applying Domain Driven Design and Patterns" suggests another way of encapsulating collections (original code was in C#, but I translated it to Java):
public class Person {
private List<Person> children = new ArrayList<Person>();
// ...
public Collection<Person> getChildren (){
return Collections.unmodifableList (children);
}
public void addChild(Person child){
children.add(child);
}
// ...
}
I like this because it its very simple. It is default solution for me.
When (after a while) I spot a lot of collection handling code in Person. I refactor by applying "extract class" People.
For an example like this, it'll be interesting to see how far you can get without providing some kind access to the collection.
S.
It also reduces opportunities for mistakes such as having the wrong person remove a book from the library.
S.
--
Best regards
Piotr Przybylak
W dniu 22 kwietnia 2012 16:24 użytkownik Michał Piotrkowski
<mpi.michal....@gmail.com> napisał:
It depends. It depends if you can attach behavior to a Children class that is specific to a collection of children but is not for a collection of people. Example of such behavior in this case could be children.favoriteToys().
Otherwise, you end up with classes like Parents, Neighbors, Coworkers... All of them could be generalized to "a group of people".
I like to use variable name vs variable type analogy:
String name or Name name?
Lets look at an example:
public class Person {
private String name;
private Integer age;
private Integer salary;
// ...
Or
ublic class Person {
private Name name;
private Age age;
private Salary salary;
// ...
Which one is better???
I can't imagine any reasonable behavior that could be attached to Name. It is just a sequence of characters. However Age has some validation rules: age cannot be negative. You could also provide a creational method Age.fromBirthDate(Date birthDate).
When to use Integer age and when Age age?
Eric Evans in "Domain Driven Design" introduces concepts of a "core domain" and a "supporting domain". For example, if I am creating an application that calculates and visualizes currencies exchange rates I can let myself to store address data as String addressLine1, String addressLine2, but I should create a separate class for Currency, Money, ExchangeRate, ...
Many things that you couldn't imagine could possibly have behaviour, do in fact have lots, depending on the particular context, so best not to over generalise.
I'm just imagining a scenario, but what about people who are yet to be born, like little johnny's mum signing him up for a school, yet his birthday is both in the future and also probably only accurate to month and year, yet you would still want to perform logic like ' age at start of school year'
James
You might find that using a static helper method increases readability there.
Rather than new Age(10) etc, see what you think about Age.of(10) Name.of("bob")
James
I wrote a blog about this a while ago, as I seemed to do the same thing on every project....
http://www.time4tea.net/wiki/x/AwA0
James
--Nat
2012/4/24 James Richardson <ja...@time4tea.net>:
Person chuck = person().withName("Chuck
Krutsinger").withAge(51).withSalary(100000).build();
I can have multiple occurrences of the method name for different data
types, e.g.
class PersonBuilder {
public PersonBuilder withName(final String name) {
return withName(new Name(name));
}
public PersonBuilder withName(final Name name) {
[...]
}
[...]
}
The disadvantage of this is it is harder to distinguish mandatory
parameters from optional ones, if such a distinction is relevant.
> Actually it all depends ;). Names can have interesting behaviour, whether
> the family name comes before the personal name varies by language. In
> Iceland, i believe, the family name depends on gender. Anything involving
> people will be weird and complicated.
Yes. The Wikipedia pages on naming conventions in various countries
provides interesting reading.
In Iceland, traditional names -- still the majority -- are
patronymics. I would be Josef Jónsson, literally "Joseph, son of
John". My wife would be "Sara Rónsdóttir", or "Sarah, daughter of
Ron". And, of course, not everyone in Iceland does this, just most.
Some have family names as we understand them.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Author, JUnit Recipes
Free Your Mind to Do Great Work :: http://www.freeyourmind-dogreatwork.com
Find out what others have to say about me at http://nta.gs/jbrains