Java constructor with large arguments or Java bean getter/setter approach

后端 未结 18 2077
清歌不尽
清歌不尽 2020-12-12 21:29

I can\'t decide which approach is better for creating objects with a large number of fields (10+) (all mandatory) the constructor approach of the getter/setter. Constructor

相关标签:
18条回答
  • 2020-12-12 22:13

    The better approach (imho) is to use some kind of builder:

    MyClass a = new MyClassBuilder().blah("blah").foo("foo").doStuff().toMyClass();
    

    where MyClass is still immutable but has a far more readable creation than a constructor with 10 arguments.

    This is also called a fluent interface. Josh Bloch refers to this in Effective Java.

    0 讨论(0)
  • 2020-12-12 22:16

    It is a design question no doubt. You have to weigh readability with ease. A ten arg constructor is easier, but may or may not be more readable/maintainable. It also has less method calls to put on and off the call stack. Setting ten distinct values through setters is a bit more readable and explicit. It is not necessarily "easier" (although you could argue both ways), and adds more method calls to put on and off the call stack.

    But here are some more points to think about. Even with a ten argument constructor, you could have a programmer choose to pass in a null, a blank, a false, or a zero (depending on object or primitive), which may or may not be what you intended. Your only way to control this would be to potentially throw an exception in the constructor. Is this what you really want to do? Is this the behavior you expect?

    Granted, setting each variable separately through setters, you may not be able to know when you are or are not done constructing the object. This is where the Builder pattern discussed above would help. Have it create the object, set the values, and then validate that all are set. If something is missing, because a programmer decided not to pass something in, then you are protected. Your class doesn't have to do more than it is supposed to. (After all, it is important to think about who might be using your class some day. They may not understand your intent, despite all the great Javadoc in the world.)

    Lastly, I'd ask if there is anything that you need to default? Because if certain things can default then you can either set them to default values at the class level, or set them to default in the constructor (depending on your programming ideals and which you feel is more specific and assists with the behavior of your object). Then you could potentially "preset" certain fields and only need to override them through setters manually or through setters through a Builder.

    Again, you have to decide these things yourself. But probably most important out of all this is the consideration for readability over efficiency to make the code more maintainable, and creating API's and behaviors that programmers that come after you won't be able to abuse. Anticipate abuse protection in your design, whatever you use.

    0 讨论(0)
  • 2020-12-12 22:17

    IMO the constructors don't form a good API while creating objects, especially when the number of arguments are large and they are of the same type.

    new Person(String, String, String, String); // what the?? this is what may 
                                                // show up in IDEs
    

    where it actually means Person(firstname, lastname, screenname, password, (just for example's sake)

    As cletus mentions, the Builder pattern with chaining is good. Another advantage with a builder is that, if the objects are immutable, the builder can return the same object (in this case you can have a package private constructor with 15 args that only the builder knows about). Builders can also return any subtype of the objects that they build

    Another approach you could take is consider using an internal DSL. But this makes sense only if you are building objects like configurations, queries, etc. See if having an internal DSL makes sense in your case.

    We had a similar problem in our project. We had to fetch certain values from a home gateway (our product). It supported a request-response, query based XML protocol over http. But creating of Request object for sending in the UI was tedious, with setting up Request obejcts with appropriate parameters and filters, etc.

    Initially our request object looked like this:

    Request r = new Request("SET");
    r.setAction("add"); // modify, add, delete
    r.setModuleName("NPWIFI"):
    r.addParameter(new Param("wifiAclMac", "aa:bb:cc:dd:ee:ff"));
    r.addParameter(new Param("wifiCommit", "commit"));
    r.setActionParam("wifiAclRowStatus")
    r.addFilter(new Filter(Type.EQUALS, "wifiInterface", "wl0"));
    r.addFilter(new Filter(Type.EQUALS, "wifiAclMac", "yourgateway"));
    
    Resonse r = gwSession.sendRequest(r);
    

    So we changed it into an internal DSL that had an SQL like feel but only programmatic

    Query q = DQL.add("wifiAclMac", "wifiCommit").into("NPWIFI").values
                ("aa:bb:cc:dd:ee:ff", "commit").withAp("wifiAclRowStatus")
                .where("wifiInterface").is("wl0")
                .and("wifiAclMac").is("aa:bb:cc:dd:ee:ff").end();
    

    The DQL "query builder" object did all the building with validation and also proved to be a lot convenient to use.

    Builders and DSLs are a elegant and powerful means of creating and building up objects, but see what makes sense in your case.

    0 讨论(0)
  • 2020-12-12 22:21

    In his book Code Complete, Steve McConnell argues that no procedure should ever have more than a maximum of 6, maybe 7 arguments. Most of these statements are not just his opinion but backed by studies, e.g. of error rates related to code structure.

    Clean Code by Robert Martin goes even further: He recommends 1 or 2 arguments, while 3 is already considered a "code smell". Personally, I think Clean Code is a bit extreme in places, but on the whole it makes some good arguments.

    "A whole bunch of parameters" (however many that may be) bespeaks a "kitchen sink" design with lots of afterthoughts and little structure. It also makes maintenance more difficult and error prone; at the very least, it makes code hard to read.

    All this makes for good reasons to think about cutting down on the number of parameters. Other answers have offered some practical suggestions.

    0 讨论(0)
  • 2020-12-12 22:21

    I would avoid constructors with large numbers of arguments. Classes with lots of arguments in constructors can be unwieldy. Imagine if you have an inheritance heirarchy with subclassses, each with many arguments in their constructors. How much work would if be if need to change the arguments of somes of the top level classes.

    I would passing an interface to your contructor which you could change without breaking code, or use the Javabeans approach and have a no arg constructor.

    0 讨论(0)
  • 2020-12-12 22:22

    Really depends on the specific class. Should it be immutable? Is it a simple value object without any behavior? Are you going to map this value object to web service parameters, or to a relational database? Are you going to serialize it? (Some of that stuff need a default constructor). Can you tell a little bit more about the object?

    0 讨论(0)
提交回复
热议问题