Best practices for too many parameters
Hi,
I have an object with 10 fields. Let's say, for example, a Person class, with 10 attributes (name, age, height...). If I want to set the attributes from a database method that's in another class, but "show" the Person object from within the Person class, I'd rather not have a big constructor with 10 parameters, and I've been reading that 'set' methods are not the best style (e.g. Holub). And I'm quite sure that making the attributes public is very bad style. So what's the best practice for an object with many attributes?
Thanks!
[565 byte] By [
Cranky1a] at [2007-11-26 12:19:33]

# 1
There is nothing wrong with a 10 variable constructor. In this case I would recommend it.
# 2
Dan,
For this senario, I would create a data type (class) to hold whatever the information is for Person class. The constructor for the Person class would take one object as a parameter. See below:
public final class Person {
private PersonData pd;
private String name = null;
public Person(Object obj) {
// instanceOf check on obj
...
pd = (PersonData) obj
this.name = pd.getName();
....
}
}
public final class PersonData implements Serializable {
private String name = null;
public String getName() {
return this.name;
}
...
}
This way instead of sending 10+ objects/raw primitives, we only send one object. A constructor with more than three parameters is not a good object-oriented design, in my opinion.
Ghost/>
# 3
> Hi,
> I have an object with 10 fields. Let's say, for
> example, a Person class, with 10 attributes (name,
> age, height...). If I want to set the attributes
> from a database method that's in another class, but
> "show" the Person object from within the Person
> class, I'd rather not have a big constructor with 10
> parameters, and I've been reading that 'set' methods
> are not the best style (e.g. Holub). And I'm quite
> sure that making the attributes public is very bad
> style. So what's the best practice for an object
> with many attributes?
Data Transfer Object pattern also called Transfter Object pattern.
Search the java blue prints patten catalog for it.
You might want to look at the other associated pattern particularly the Data Access Object (DAO) pattern.
# 4
I would have to disagree. What is the point of taking in an object if you cast it to a PersonData. Either take a PersonData in the constructor or create an interface that you accept instead.
How are you going to create a new instance of PersonData class, you still have the same problem of 10 variables. Except now you have two classes.
> A constructor
> with more than three parameters is not a good
> object-oriented design, in my opinion.
Why draw the line at three?
If it makes enough sense for your object to have 4 primatives as variables, then I think it is best to have a constructor with 4 parameters.
# 5
> Dan,
>
> For this senario, I would create a data type (class)
> to hold whatever the information is for Person class.
> The constructor for the Person class would take one
> object as a parameter. See below:
>
> public final class Person {
>
>private PersonData pd;
> private String name = null;
>
>public Person(Object obj) {
>
>// instanceOf check on obj
>...
>pd = (PersonData) obj
>this.name = pd.getName();
>....
> }
>
> }
>
> [code]public final class PersonData implements
> Serializable {
>private String name = null;
> public String getName() {
> return this.name;
>
>...
> e]
>
> This way instead of sending 10+ objects/raw
> primitives, we only send one object. A constructor
> with more than three parameters is not a good
> object-oriented design, in my opinion.
>
> Ghost/>
But then you are just pushing the OP's question from the Person class to the PersonData class. How will you set the 10 fields in the PersonData instance - a constructor with 10 parameters, 10 set methods, etc.?
Also, why did you make the parameter to the Person constructor of type Object instead of PersonData type (causing the need for the instanceof check)?
# 6
> I would have to disagree. What is the point of
> taking in an object if you cast it to a PersonData.
> Either take a PersonData in the constructor or
> create an interface that you accept instead.
PersonData could be an interface, I only provided an example to help guide. The example was only an example of another way to go about. Programming to interfaces is best.
> How are you going to create a new instance of
> PersonData class, you still have the same problem of
> 10 variables. Except now you have two classes.
The 10 variables/fields is not a "problem". Having two classes is not a "problem" either. One class/object is for encapsulating and sending data back and forth, and the other is for encapsulating business logic.
> > A constructor
> > with more than three parameters is not a good
> > object-oriented design, in my opinion.
>
> Why draw the line at three?
This is a design decision. Other programmers may feel differently. If there is more than three, then I feel it deserves a special type, encapsulated in an object and implementing a generic interface suited and designed for the application.
> If it makes enough sense for your object to have 4
> primatives as variables, then I think it is best to
> have a constructor with 4 parameters.
Constructor with 4 parameters is how you would program. That is fine and you can do it any way you want. Four parameters are too much and not condusive to adaptability. For example, if you used the constructor with four parameters, and then had to change to five or six, you would have to rewrite and recompile and retest and regression test the application. For small appilcations, this may not take long. However, depending upon how many classes useing and constructing the Person object, you may end up having to rewrite and recompile many, many classes for a simple thing. If you only sent one object as the parameter, you would probably only have to rewrite two/maybe three classes if you need to add more fields to the Person class.
# 7
>public Person(Object obj) { // Why did you declare the parameter as an object?
> This way instead of sending 10+ objects/raw
> primitives, we only send one object.
But then you will need to construct your "PersonData" object., which leads back to the OP's question. This sounds like you advocate creating arbitrary holder classes just to limit the number of parameters (even if the arbitrary class contains unrelated fields).
> A constructor
> with more than three parameters is not a good
> object-oriented design, in my opinion.
Why not? Please elaborate. What if you you declared > 3 fields as final?
# 8
> > How are you going to create a new instance of
> > PersonData class, you still have the same problem
> of
> > 10 variables. Except now you have two classes.
>
> The 10 variables/fields is not a "problem".
But that is what the OP asked. How to handle creating an object with 10 variables/fields. Now instead of Person class, there is a new class the PersonData class which has the same responsibility and therefore the same question.
> Having two classes is not a "problem" either.
It is, if the the second class was created to fix a problem in the first and still doesn't address the problem.
> This is a design decision. Other programmers may feel
> differently. If there is more than three, then I feel
> it deserves a special type, encapsulated in an object
> and implementing a generic interface suited and
> designed for the application.
I understand the logic here.
> Constructor with 4 parameters is how you would
> program. That is fine and you can do it any way you
> want. Four parameters are too much and not condusive
> to adaptability. For example, if you used the
> constructor with four parameters, and then had to
> change to five or six, you would have to rewrite and
> recompile and retest and regression test the
> application.
You have the same problem if you have a constructor with 3 fields and then you need 4 or 5.
My point was why draw the line at three.
> However, depending upon how many classes
> useing and constructing the Person object, you may
> end up having to rewrite and recompile many, many
> classes for a simple thing. If you only sent one
> object as the parameter, you would probably only have
> to rewrite two/maybe three classes if you need to add
> more fields to the Person class.
The number of changes will be the same. In one case you will be changing classes that construct Person objects, in the other case you will be changing classes that construct PersonData objects.
# 9
> But then you are just pushing the OP's question from
> the Person class to the PersonData class. How will
> you set the 10 fields in the PersonData instance - a
> constructor with 10 parameters, 10 set methods,
> etc.?
Not really, the PersonData class would not have a constructor with 10+ parameters. This would be a data transfer object and would most likely utilze get/set methods and maybe the BeanUtils class from the JavaBeans package.
> Also, why did you make the parameter to the Person
> constructor of type Object instead of PersonData type
> (causing the need for the instanceof check)?
Design decision. Didn't really see point of thinking about it too much, it is a simple example for a forum post. I am also drinking coffee and listening to the news while I'm writing these posts. Taking the stance of an object purist there is no difference between a PersonData and a Object class. Everything is an Object, if it is not a primitive. Whether one codes the type check in the constructor's method signature or in the constructor's body, it is the same thing. Again, a simple design choice. I like method signature using Object. Only Objects! The code in the class will determine/discover what type of Object it is. No shortcuts!
# 10
> Object, if it is not a primitive. Whether one codes
> the type check in the constructor's method signature
> or in the constructor's body, it is the same thing.
> Again, a simple design choice. I like method
> signature using Object. Only Objects! The code in the
> class will determine/discover what type of Object it
> is. No shortcuts!
One can be checked at compile time; the other cannot be checked until runtime - big difference.
# 11
> I like method signature using Object. Only Objects! Yick. (<-- Design decision):o)~
# 12
> > If it makes enough sense for your object to have 4
> > primatives as variables, then I think it is best
> to
> > have a constructor with 4 parameters.
>
> Constructor with 4 parameters is how you would
> program. That is fine and you can do it any way you
> want. Four parameters are too much and not condusive
> to adaptability.
How exactly do 4 parameters limit adaptability, but 3 don't?
> For example, if you used the
> constructor with four parameters, and then had to
> change to five or six, you would have to rewrite and
> recompile and retest and regression test the
> application.
If you have a constructor with 3 parameters and had to change it to 6, you'd still have to recompile and retest and regression test. If you had 20 parameters and went down to 3, you'd have to do the same thing. The number of parameters doesn't affect the amount of recompiling you have to do.
> For small appilcations, this may not
> take long. However, depending upon how many classes
> useing and constructing the Person object, you may
> end up having to rewrite and recompile many, many
> classes for a simple thing. If you only sent one
> object as the parameter, you would probably only have
> to rewrite two/maybe three classes if you need to add
> more fields to the Person class.
But that one object would still have the problem of having many parameters, so any class that dealt with that container would have to be changed. Any class that would deal with the Person parameters would instead be dealing with that object's parameters. You don't save any work by shifting the responsibility to a different class.
If only 2 or 3 classes needed to be recompiled to make changes to the container, then only 2 or 3 classes would need to be recompiled to make changes to the Person class with many parameters.
Besides, the amount of time it takes to compile your code should not be a factor in design decisions. Good design is intended to make it easier for humans to work with the code, not to make it easier for the compiler to work with the code.
# 13
> Not really, the PersonData class would not
> have a constructor with 10+ parameters. This would be
> a data transfer object and would most likely utilze
> get/set methods and maybe the BeanUtils class
> from the JavaBeans package.
Then why don't you just implement the Person class that way without having to create an additional PersonData class? However, this still doesn't address fields that are declared as final which can't be modified via get/set methods.
> The code in the
> class will determine/discover what type of Object it
> is.
Then you'll have to decide what to do if the Object passed in is of the wrong type. Do you then throw an IllegalArgumentException or IllegalStateException? This makes a compile time problem into runtime which is not good IMO.
# 14
> > I like method signature using Object. Only
> Objects!
>
>
> Yick. (<-- Design decision)
>
>
> :o)
>
> ~
I'm just foolin Yawny :o) I'm getting old and still remember the old academic arguments/persepectives.
Of course we know Java improved on these and programming to interfaces rule!
# 15
In terms of that this just "moves" the problem....
First if the ONLY method that needs this collection is a single constructor then that is true. However there are very likely other methods, even constructors that might need the same collection. And some of the methods quite possibly will be nothing but pass throughs (doing nothing but passing the collection to another method.)
Second, sometimes not all of the parameters are needed. I doubt that is true for this case (due to the mention of the database) but for initialization parameters often many are defaulted.If the entire list is used then either a large number of constructors are needed (10! I would guess for 10 params) or one just creates DTO with the defaults set and modifies, via getter/setters or directly only those values that need something besides the default.
# 16
> Of course we know Java improved on these and> programming to interfaces rule!Not to mention [url= http://forum.java.sun.com/thread.jspa?threadID=5114720]JDBC and RMI[/url]... ;o)~
# 17
> get/set methods and maybe the BeanUtils class
> from the JavaBeans package.
>
> I like method
> signature using Object. Only Objects! The code in the
> class will determine/discover what type of Object it
> is. No shortcuts!
That is a shortcut and I don't like it.
If you are going to do that you might as well use a real collection like a hash for all of the parameters.
One shouldn't code simply to avoid typing.
# 18
> How exactly do 4 parameters limit adaptability, but 3
> don't?
The goal is to properly decide when to create a class to encapsulate data. For more than 3 parameters, a class chould be created to encapsulate the information. And the number of parameters should be reduced to one. Again, this is a design decision, others may program differently. Having one object passed as the parameter is a clearner design than a constructor with more than three parameters, in my opinion.
> Besides, the amount of time it takes to compile your
> code should not be a factor in design decisions.
I disagree. How much rework, analysis, and recompiling should be an important factor in object-oriented design.
If your design cannot adapt and you have to recompile 100 classes to accomodate a new data field, that is poor design.
If my design can adapt and was designed properly, I might only have to recompile and analyze only three classes to accomodate a new data field. This is good design.
You choose how you want to design. The point is that this issue is very important to effective object-oriented design.
# 19
> If you are going to do that you might as well use a> real collection like a hash for all of the> parameters.> Great idea. The Collections framework is a good resource, (e.g. PersonData implements Set).
# 20
> > If you are going to do that you might as well use a
> > real collection like a hash for all of the
> > parameters.
> >
>
> Great idea. The Collections framework is a good
> resource, (e.g. PersonData implements Set).
Not sure now if you are serious or not.
That isn't a great idea. It is simply better than doing it the other way.
As already noted the collection as well as the other suggestion relegate type checking to runtime rather than compile time. And that isn't an ideal situation.
# 21
> The goal is to properly decide when to create a class
> to encapsulate data. For more than 3 parameters, a
> class chould be created to encapsulate the
> information.
I can understand seeing having several parameters in a constructor as a bad smell. But cutting it off a 3 seems to have no logic behind it.
Why not 4, why not 2? Why not only allow a max of one for every constructor?
You said it would be so much rework if the signature had to be changed.
Might as well just make all method take in an Object based on that logic.
> I disagree. How much rework, analysis, and
> recompiling should be an important factor in
> object-oriented design.
If your focus is to have adaptable code then one of the best ways to do that is using Xtreme Programming, which says:
1. do it the easiest way
2. don't ever look ahead (this would include the # of parameters in constructors changing)
3. Refactor, refactor, refactor
# 22
> > I like method
> > signature using Object. Only Objects! The code in
> the
> > class will determine/discover what type of Object
> it
> > is. No shortcuts!
>
> That is a shortcut and I don't like it.
I still don't see how this is a shortcut. Won't it require more code if programming defensively?
@jschell: I took your suggestion. I had to think twice before quoting this time ;-)
# 23
> > > I like method
> > > signature using Object. Only Objects! The code in
> > the
> > > class will determine/discover what type of Object
> > it
> > > is. No shortcuts!
> >
> > That is a shortcut and I don't like it.
>
> I still don't see how this is a shortcut. Won't it
> require more code if programming defensively?
>
There are only two cases where I have seen that done.
One they actually needed that and provided the required code to, defensively, support it.
Two, and many more cases, they didn't do the checks at all but simply assumed that it was always right. The 'decision' was made to do it that way because they got tired of changing all of the classes everytime something changed. (And the rest of the design was poor as well.) Thus it is a short cut.
# 24
> I can understand seeing having several parameters in
> a constructor as a bad smell. But cutting it off a 3
> seems to have no logic behind it.
> Why not 4, why not 2? Why not only allow a max of
> one for every constructor?
> You said it would be so much rework if the signature
> had to be changed.
> Might as well just make all method take in an Object
> based on that logic.
When designing, there has to be some guidelines that you must establish for yourself and those working under you. Three pieces of information might be good and not require a special class, it depends on the information that is being sent as well as the source of the information. It is a design decision to say, if, for this class, more than three bits of information of "this" sort, should be encapsulated in a special class. It is a design decision. Others may design in a different way, this is fine. Having all constructors only taking Object may be the best design for a particular application.
Three is the max for me and those under me. It works fine.
> If your focus is to have adaptable code then one of
> the best ways to do that is using Xtreme Programming,
> which says:
Xtreme programming may work and may not be the best. It depends. Proper analysis and business requirements process is the best practive. Proper UML design is also best practive.
To jump into programming right away may work for very snall Java programs.
To jump into programming right away is poor practice when working on enterprise applications, in my opinion.
Using the UML properly is the best way to go about creating an object-oriented design. Others may disagree, but the UML is the best way. Again, this is a design decision.
A combination of the Waterfall and Unified Process is a best practice, in my opinion. Use Waterfall in beginning and switch over to Iterative style of UP in the middle.
# 25
> If my design can adapt and was designed properly, I
> might only have to recompile and analyze only three
> classes to accomodate a new data field. This is good
> design.
A problem with using get/set accessor methods is that you may forget to initialize a necessary field. Your compiler won't warn you that you didn't call the set method for a particular field. On the other hand, if the signature of a constructor doesn't match, the compiler will tell you.
I don't think an arbitrary cutoff is appropriate. What about a 4D point? I don't like many arguments but if I can't come up with a better logical design, I leave it that way. Personally, I don't even like my method signatures longer than 80 characters (including indentation) but that's another question.
# 26
> I can understand seeing having several parameters in
> a constructor as a bad smell. But cutting it off a 3
> seems to have no logic behind it.
> Why not 4, why not 2? Why not only allow a max of
> one for every constructor?
> You said it would be so much rework if the signature
> had to be changed.
> Might as well just make all method take in an Object
> based on that logic.
>
Effective C++ (or maybe another book like that) rationalized that, based on a memorization study, that humans can grasp between 3-7 entites.
Thus class should never have more than 3-7 attributes.
I suspect most people would agree that 200 attributes and certainly 200 parameters in a method are too many. But then is 199 ok? At some point there is a reasonable number.
# 27
> A problem with using get/set accessor methods is that
> you may forget to initialize a necessary field. Your
> compiler won't warn you that you didn't call the set
> method for a particular field. On the other hand, if
> the signature of a constructor doesn't match, the
> compiler will tell you.
That isn't a problem with my code. Appropriate default values are set.
>
> I don't think an arbitrary cutoff is appropriate.
> What about a 4D point? I don't like many arguments
> but if I can't come up with a better logical design,
> I leave it that way. Personally, I don't even like
> my method signatures longer than 80 characters
> (including indentation) but that's another question.
So rather than passing java.awt.Point around you would rather pass two values to every method where Point is currently used?
# 28
Create a Person interface. Create a factory that returns an instance of the Person interface. Write the implementation (PersonJDBC) able to talk to the DB directly to populate itself. This way a DTO knows how to store itself but that implementation detail is NOT exposed to the rest of the program.
In reality the interfaces produced by the factory would perform operations.
interface PeopleStore {
/**
* Find person by name
*/
Person findByName(String name);
/**
* Find the person by id
*/
Person findById(long id);
void update(Person p);
....etc
}
And a factory
public abstract class PeopleStoreFactory {
public static PeopleStoreFactory getInstance() {
// in here you would do something a bit more complex
// than this to determine which factory instance to return
// (i.e. JDBC, JDO, JPA, File based etc)
return new PeopleStoreFactoyImpl();
}
public abstract PeopleStore getPeopleStore();
}
matfud
# 29
> > A problem with using get/set accessor methods is
> that
> > you may forget to initialize a necessary field.
> Your
> compiler won't warn you that you didn't call the
> set
> method for a particular field. On the other hand,
> if
> the signature of a constructor doesn't match, the
> compiler will tell you.
>
> That isn't a problem with my code. Appropriate
> default values are set.
There cannot be a default value which could accurately cover the behaviour in all cases.
# 30
Hi everyone,
So far, I'm hearing the following answers:
1) Contructor with many parameters - good because it forces the parameters to match at compile-time, but bad because there are many parameters to track.
2) Separate class - good because the constructor only needs one parameter, but bad because it seems the problem is simply transferred to another class that may need lots of setter methods or a large constructor itself.
3) Hashmap / map - good because it's a single object that can be passed. I personally don't like it because I have a few simple types that need to be converted (e.g. int and boolean), and it's somewhat of a proxy for answer #2.
4) Passing the ResultSet as a parameter to the constructor... not mentioned yet - I can see a few reasons why not to do this one, like assuming that the data will always come from a database, and the try/catch situation.
5) Have everything in the Person class - I don't think anyone has mentioned this one, but maybe just have the database calls and the 'show' methods all in the one class. Does anyone else do that?
I don't get a sense that there's a solution yet that everyone can agree with, but everyone's input is definitely helpful.
Dan
# 31
> > A problem with using get/set accessor methods is
> that
> > you may forget to initialize a necessary field.
> Your
> compiler won't warn you that you didn't call the
> set
> method for a particular field. On the other hand,
> if
> the signature of a constructor doesn't match, the
> compiler will tell you.
>
> That isn't a problem with my code. Appropriate
> default values are set.
I'm talking more about situations in which default values aren't appropriate.
> > I don't think an arbitrary cutoff is appropriate.
> > What about a 4D point? I don't like many
> arguments
> > but if I can't come up with a better logical
> design,
> > I leave it that way. Personally, I don't even
> like
> > my method signatures longer than 80 characters
> > (including indentation) but that's another
> question.
>
> So rather than passing java.awt.Point around you
> would rather pass two values to every method where
> Point is currently used?
I'm not sure I understand you here or if you understood me. I'm saying if you have an arbitrary cutoff of 3 parameters per constructor, then you can't easily create a class like Point4D which makes sense to have 4 parameters in the constructor.
//Just an example
public class Point4D {
public Point4D(int x, int y, int z, int time){...}// 4 parameters
public Point4D(Point3D coordinates, int time) {...}
}
# 32
> 5) Have everything in the Person class - I don't
> think anyone has mentioned this one, but maybe just
> have the database calls and the 'show' methods all in
> the one class. Does anyone else do that?
Not good IMO. I prefer using a DAO for interaction with the database. I don't think you should mix it with the presentation.
> I don't get a sense that there's a solution yet that
> everyone can agree with
That is unlikely to happen.
# 33
> When designing, there has to be some guidelines that
> you must establish for yourself and those working
> under you.
Broad design decisions are poo. IMHO.
The design decisions should be specific to each app.
I think it is ok to have coding standards for a group of developers. But this is not a coding standard issue.
> A combination of the Waterfall and Unified Process is
> a best practice, in my opinion. Use Waterfall in
> beginning and switch over to Iterative style of UP in
> the middle.
Well, we have a difference of opinion. In general I find Waterfall to be the worst method.
# 34
> Hi everyone,
>
> So far, I'm hearing the following answers:
>
> 1) Contructor with many parameters - good because it
> forces the parameters to match at compile-time, but
> bad because there are many parameters to track.
>
> 2) Separate class - good because the constructor only
> needs one parameter, but bad because it seems the
> problem is simply transferred to another class that
> may need lots of setter methods or a large
> constructor itself.
>
> 3) Hashmap / map - good because it's a single object
> that can be passed. I personally don't like it
> because I have a few simple types that need to be
> converted (e.g. int and boolean), and it's somewhat
> of a proxy for answer #2.
>
> 4) Passing the ResultSet as a parameter to the
> constructor... not mentioned yet - I can see a few
> reasons why not to do this one, like assuming that
> the data will always come from a database, and the
> try/catch situation.
>
> 5) Have everything in the Person class - I don't
> think anyone has mentioned this one, but maybe just
> have the database calls and the 'show' methods all in
> the one class. Does anyone else do that?
>
> I don't get a sense that there's a solution yet that
> everyone can agree with, but everyone's input is
> definitely helpful.
>
> Dan
My prevoius comment was a combination of 5 and 2. Hide it behind interfaces and provide a factory to produce it. Then the implementation can change without client code needing to be aware of it and without exposing constructors to people using your api (even if its only you using your api :)
Although, as I said earlier, its generally more productive to provide an interface that performs OPERATIONS on the data objects rather then just producing the data objects.
matfud
# 35
How about concatenating all attributes into one string separated by tabs and passing it to the Person c'tor. In the c'tor split() the string and use the resulting array to set fields in the class. This way the number of attributes can increase or decrease. You would still need to know what variable each element in the resulting array corresponds to but that effort is no different from when c'tor arguments change.
# 36
> How about concatenating all attributes into one
> string separated by tabs and passing it to the Person
> c'tor. In the c'tor split() the string and use the
> resulting array to set fields in the class. This way
> the number of attributes can increase or decrease.
> You would still need to know what variable each
> element in the resulting array corresponds to but
> that effort is no different from when c'tor
> arguments change.
*yuck*
# 37
> How about concatenating all attributes into one
> string separated by tabs and passing it to the Person
> c'tor. In the c'tor split() the string and use the
> resulting array to set fields in the class. This way
> the number of attributes can increase or decrease.
> You would still need to know what variable each
> element in the resulting array corresponds to but
> that effort is no different from when c'tor
> arguments change.
1) Too much unnecessary overhead
2) High chance of hidden errors
3) Casting
...
# 38
> *yuck* (<-- 'nother design decision)~
# 39
> > *yuck* (<-- 'nother design decision)> > ~*shrug* I was designed that way - yuck or no yuck. ;)
# 40
> *shrug* I was designed that way - yuck or no yuck. ;)Reply #11, if you haven't already seen it... :o)~
# 41
There are always trade offs. I personally would simply deal with however many arguments are needed provided they are truly needed. It may be the case that the Person class is trying to "do too much" as evidenced by the great number of arguments required. Splitting up Person into other objects that encapsulate only the necessary behaviour and properties needed might be possible if the arguments are not all dependent on each other to achieve the needed behaviour/properties.
# 42
> > *shrug* I was designed that way - yuck or no> yuck. ;)> > Reply #11, if you haven't already seen it... :o)> > ~Missed that. <enlightenment/>
# 43
> 3) Hashmap / map - good because it's a single object
> that can be passed. I personally don't like it
> because I have a few simple types that need to be
> converted (e.g. int and boolean)
Yuck, because it is hell to debug when all you know is you have a map of Object keys and Object values (even with Generics, you need to know exactly what keys/values to expect). When you can mistakenly type the String key incorrectly, and that gives you a null pointer (or the wrong value, if two have similar keys), it's horrible to debug.
An Object[ ] (an Object array) is no better. You have to know exactly what is expected at each index.
It makes flexible code. But, it offers very little compile-time safety. And making sure to test all the possibilities at runtime is difficult.
Don't do it!
# 44
> How about concatenating all attributes into one
> string separated by tabs and passing it to the Person
> c'tor. In the c'tor split() the string and use the
> resulting array to set fields in the class. This way
> the number of attributes can increase or decrease.
> You would still need to know what variable each
> element in the resulting array corresponds to but
> that effort is no different from when c'tor
> arguments change.
Or hey, how about you convert the string to Unicode values, find the length of the longest field, prepend the converted string with that number, pad each field with -1's to be the right length, then stick it all together and make a BigInteger out of it! Then on the other side you just reverse the process.
*yuck*
Message was edited by:
tsith
# 45
> >
> > That isn't a problem with my code. Appropriate
> > default values are set.
>
> There cannot be a default value which could
> accurately cover the behaviour in all cases.
Could be.
But as I said for all the code that I have written there were default values appropriate for instantiation.
Note that the values were not valid for all possible actions that might occur with those instances. But that is handle by validation for the action.
# 46
>
> 3) Hashmap / map - good because it's a single object
> that can be passed. I personally don't like it
> because I have a few simple types that need to be
> converted (e.g. int and boolean), and it's somewhat
> of a proxy for answer #2.
>
Bad because validation occurs at runtime rather than compile time.
# 47
> >
> > That isn't a problem with my code. Appropriate
> > default values are set.
>
> I'm talking more about situations in which default
> values aren't appropriate.
>
I suppose that is possible but I haven't encountered it so far.
Noting (as with the other response) that a valid default value might not be appropriate for all actions. But validation for the action deals with that.
> >
> > So rather than passing java.awt.Point around you
> > would rather pass two values to every method where
> > Point is currently used?
>
> I'm not sure I understand you here or if you
> understood me.
I suspect I didn't understand your point.
# 48
>
> Or hey, how about you convert the string to Unicode
> values, find the length of the longest field, prepend
> the converted string with that number, pad each field
> with -1's to be the right length, then stick it all
> together and make a BigInteger out of it! Then on
> the other side you just reverse the process.
Pick me! Pick me!.....
Every object should keep all of it attributes as xml. Each object should have its own XSD of course. To extract any attribute provide the appropriate xpath.
# 49
> Every object should keep all of it attributes as xml.
> Each object should have its own XSD of course. To
> extract any attribute provide the appropriate xpath.
That sounds like a holistic, extensible, robust paradigm that completely fits within our forward-looking service-oriented framework and trend-based agile process methodology.
Thanks for identifying that win-win solution.
</phb>
# 50
> > When designing, there has to be some guidelines
> > that you must establish for yourself and those working
> > under you.
> Broad design decisions are poo. IMHO.
You are entitled to your opinions, and guidelines and decisions are two different things. No one is going to shoot someone if they design in a different way. What matters most is that the business requirements are met, that is all. Whether you have 3 parameters, 10 parameters, or an Object, this is a trivial decision. What matters is that the business requirements are met in a good fashion. Trivial arguments over trivial things are for the birds that don't know :o)
>
> The design decisions should be specific to each app.
>
This is a great design guideline, that some may make a decision to recommendsuggest.
>
> A combination of the Waterfall and Unified Process
> is a best practice, in my opinion. Use Waterfall in
> beginning and switch over to Iterative style of UP
> in the middle.
> Well, we have a difference of opinion. In general I
> find Waterfall to be the worst method.
It sounds like it never worked well for your environment. I am sorry.
The Waterfall software development structure/theory/guideline works fine for my environement when combined with the Unified Process and it's Iterative style of development after the initial business requirements are properly discovered/gathered/derived.
# 51
I would use a Hashmap. http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html
# 52
> I would use a Hashmap. > > http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.htmlBad idea, as already mentioned at least twice (Reply #43 and #46).
# 53
> Could be.
>
> But as I said for all the code that I have written
> there were default values appropriate for
> instantiation.
>
> Note that the values were not valid for all possible
> actions that might occur with those instances. But
> that is handle by validation for the action.
I suspect the point was it provides some basic compile-time checking that the developer remembered all necessary parameters. Take the constructors in java.awt.GradientPaint as an example, wouldn't it be silly for them to require a GradientConstraints? It'd be far easier to "forget" to set one of the points or colors and the mistake would show up at runtime rather than at compile-time.
# 54
It really depends on the context. You can't just say that Hashmaps in general are bad for condensing many attributes.
# 55
> It really depends on the context. You can't just say> that Hashmaps in general are bad for condensing many> attributes.To pass to a constructor? I most certainly can say that for reasons already given in reply #43.
# 56
> It really depends on the context. You can't just say
> that Hashmaps in general are bad for condensing many
> attributes.
I can.....
In terms of this discussion, in general, it is bad idea.
There can be specific cases where it might be required by the business requirements of the system. For most applications the business requirements will never require that.
It most definitely is a bad idea if this is a design decision that is driven solely because the developer doesn't want to type as much. Even if a developer thinks that the schedule doesn't allow time to do all the work, the time spent in debugging will more that exceed that, so it will never be a win situation.
# 57
> > It really depends on the context. You can't just
> say
> > that Hashmaps in general are bad for condensing
> many
> > attributes.
>
> I can.....
>
> In terms of this discussion, in general, it is bad
> idea.
>
> There can be specific cases where it might be
> required by the business requirements of the system.
> For most applications the business requirements will
> never require that.
>
> It most definitely is a bad idea if this is a design
> decision that is driven solely because the developer
> doesn't want to type as much. Even if a developer
> thinks that the schedule doesn't allow time to do all
> the work, the time spent in debugging will more that
> exceed that, so it will never be a win situation.
interesting. i never had a bug dealing with a hashmap before so i dont know how hard it is to debug it, but i'll take your advice.
Thanks :)
# 58
import java.util.*;
public class WhyMapIsABadIdea {
public static void main(String[] args) {
Map m = new HashMap();
m.put("foo", Long.MIN_VALUE);
new MyObject(m); // <-- crunch
}
}
class MyObject {
private String foo;
public MyObject(Map m) {
this.foo = (String) m.get("foo");
}
}
Yes, this problem can be mitigated by jumping through a bunch of hoops at runtime, but that seems to me to eliminate any perceived benefit of using a Map in the first place.
~
# 59
> Trivial> arguments over trivial things are for the birds that> don't know :o)Welcome back, Daffy. You still passing references by name?
# 60
> interesting. i never had a bug dealing with a
> hashmap before so i dont know how hard it is to debug
> it, but i'll take your advice.
Consider this....where is the bug in the following?
// Only appears in server code
hash.add("Link.Table15.Request.Only01", "15");
// Only appears in client code
hash.add("Link.TableI5.Request.Only01", "15");