From: topmind on

andrewmcdonagh wrote:
> On Feb 11, 5:55 pm, "howa" <howac...(a)gmail.com> wrote:
> > for example, a Person class, I need to create a person using, e.g.
> >
> > Person peter = new Person('Peter', '....)
> >
> > the object creation might involved over 30 parameters, the advantage
> > is this call is atomic, rather than something like, e.g.
> >
> > Person peter = new Person();
> > peter.setName('Peter');
> > peter.setBirthPlace('....
> > ...
> >
> > Are there any platterns, suggestion or anti-plattern related to this
> > problem?
> >
> > thanks.
>
> I find, that when I need to pass more than 6 parameters, the code base
> is shouting to me 'Your design sucks'. It sucks because I've negated
> to see that there are relationships between two or more of the
> parameters, that should be described using a dedicated class, and
> therefore a single instance of that class as a parameter. As for an
> anti-pattern, I'd say 'primitive obsession' is probably one of the
> biggest culprits.
>
> So using your example....
>
> peter = new Person("Peter", 35, 123, "Sycamore Road", "Sometown",
> "Some county", "a postcode/zip code", "0044123
> 991199", ..............)
>
> Here, because we have 'primitive obsession' (i.e. using primitive
> types: String & ints) we are forced to send everything through as
> individual objects.
>
> Now, if we look for relationships between those parameters, the
> obvious one we see is the parameters that make up Peter's address.
> Oh hang on, that even gives us the missing classes name 'Address'. So
> by moving those 5 address related parameters into their own class, we
> can insubstantially reduce the parameter passing needed AND we have
> increased the quality and safety of our design.
>
> Address petersAddress = new Address(123, "Sycamore Road", "Sometown",
> "Some county", "a postcode/zip code");
>
> peter = new Person("Peter", 35, petersAddress, "0044123
> 991199", ..............);
>
>
> So why did I say 'safety' of design?
>
> Looking at the original constructor:
>
> Person(String name, int age, int housenumber, String firstLine, String
> secondLine, String thirdline, .....)
>
> Its unsafe from a compile time checking point of view, as there is
> nothing to catch errors.... We could safety do..
>
> peter = new Person("a postcode/zip code", 123, 35, "Sycamore Road",
> "Sometown", "Some county", "Peter", "0044123 991199", ..............);
>
> This would compile, but then the values would be wrong as 'Peter'
> would actaully be called 'a postcode/zip code' and he would be 123
> years old instead of 35 and his post/zip code would be 'peter'.
>
> Now we don't need to go overboard with turning every thing into its
> own class, like the Address one, but the technique is useful and worth
> using when you see large parameter lists.

That is a good suggestion. Larger databases tend to have some form of
a Contact table that stores typical address info, which is common for
vendors, customers, employees, etc. However, there can easily be more
than 7 attributes for a Contact record such that we are still back to
the original problem. Example:

Table: Contact
------------
contactID
title // (Mr. Dr. Etc.)
firstName
lastName
middleName
aliasName
homePhone
workPhone
messagePhone
pagerNumber
email
otherContact // (for I.M., fax and whatever new tech comes alone)
addressLine1
addressLine2 // (some postal systems require no line longer than 30
chars, so we split)
city
zipCode
country

There are ways to simplify some of this, but still the potential for
more than 7 items is still great.

>
> hth
>
> Andrew

-T-

From: Johan Stuyts on
> Rather than create a whole new class just for parameters, perhaps
> attributes can be set and then have a "validate" or "submit" method:
>
> Person peter = new Person();
> peter.setName('Peter');
> peter.setBirthPlace('....');
> peter.setMoreAttributesEtc(...);
> peter.save();

This alternative was already given by howa in his question, so I don't see
the need to repeat it.

Creating a separate class for something simple is not a problem. I create
dozens of tiny classes with one specific, simple function each week.
Usually I also introduce an interface along with it. In the case of howa's
question it would become:
interface PersonCreationParameters {...}
class PersonCreationParametersBean implements PersonCreationParameters
{...}

I find that this pattern increases cohesion and decreases coupling. The
cohesion is increased because Person loses a responsibility: managing the
creation parameters. The coupling is decreased because Person does not
have to know how the creation parameters were obtained. Granted, if you
use a constructor it does not know either, but I see a lot of code that
actively tries to get its configuration. The problem is that I always want
the configuration to come from somewhere else. Using an interface enables
me to decouple the object from how its parameters were obtained.

Another good solution is the map/associate array you propose in another
post to this thread. But this has the disadvantage that you loose strong
typing.

Johan
From: andrewmcdonagh on
On Feb 12, 5:15 pm, "topmind" <topm...(a)technologist.com> wrote:
> howa wrote:
> > > It is an anti-pattern (using a set of setters as a substitute for
> > > constructor parameters).
>
> > > --http://conceptoriented.com
>
> > i agree with you. it is anti-pattern. but consider 30 parametes
> > constructor, it is also easy to make mistake....
>
> Each has their advantages and disadvantages. My rule of thumb is that
> more than 6 or 7 positional parameters is a yellow alert to explore
> different approches, such as set/get's or an associative array (map).
>
> -T-

I'd never use an array/map bucket for holding parameters (unless a 3rd
party api forced me) as its no better than just passing them directly,
except that I could pass 31 parameters....

yuck

YMMV

Andrew

From: Diego on
On Feb 12, 6:29 pm, "andrewmcdonagh" <andrewmcdon...(a)gmail.com> wrote:
> On Feb 12, 5:15 pm, "topmind" <topm...(a)technologist.com> wrote:
>
> > howa wrote:
> > > > It is an anti-pattern (using a set of setters as a substitute for
> > > > constructor parameters).
>
> > > > --http://conceptoriented.com
>
> > > i agree with you. it is anti-pattern. but consider 30 parametes
> > > constructor, it is also easy to make mistake....
>
> > Each has their advantages and disadvantages. My rule of thumb is that
> > more than 6 or 7 positional parameters is a yellow alert to explore
> > different approches, such as set/get's or an associative array (map).
>
> > -T-
>
> I'd never use an array/map bucket for holding parameters (unless a 3rd
> party api forced me) as its no better than just passing them directly,
> except that I could pass 31 parameters....
>
> yuck
>
> YMMV
>
> Andrew

a hash table may be a great solution when the number of parameters is
unknown

but I agree with YMMV

From: Michael Feathers on
Jerry Coffin wrote:
> In article <1171216519.131931.144410(a)v33g2000cwv.googlegroups.com>,
> howachen(a)gmail.com says...
>
>>for example, a Person class, I need to create a person using, e.g.
>>
>>Person peter = new Person('Peter', '....)
>>
>>the object creation might involved over 30 parameters, the advantage
>>is this call is atomic, rather than something like, e.g.
>>
>>Person peter = new Person();
>>peter.setName('Peter');
>>peter.setBirthPlace('....
>>...
>>
>>Are there any platterns, suggestion or anti-plattern related to this
>>problem?
>
>
> 30 parameters is almost certainly excessive -- I'd suggest some sub-
> objects to encapsulate some of the coherent pieces. An obvious one would
> be "address" or something on that order.

That's a good way to go. The other thing to notice is that the pain of
a constructor with a large parameter list is proportional to its use.
If you can create a factory for the class and are able to ask for new
objects without having the client supply all of the parameters all of
the time, things are much nicer. This is pretty much the lesson of the
Dependency Injection Pattern.

Another handy pattern for this situation is the Essence pattern.
Essence lets you deal with optional parameters gracefully:

hillside.net/plop/plop98/final_submissions/P10.pdf