|
From: topmind on 12 Feb 2007 12:30 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 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 12 Feb 2007 14:05 > 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 12 Feb 2007 15:29 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 13 Feb 2007 10:58 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 20 Feb 2007 08:34
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 |