开发者

How much should be done in a constructor

This is a theory question I guess that I am using to find the standard procedure for this.

If I have a Constructor method that does a whole lot of setup op开发者_StackOverflow中文版erations gathering data and such, should I keep "all things construction" in the constructor, or should I try to call other methods from inside the constructor (for code looks basically), or should I just initialize everything I have to and leave other things to be dealt with later if they are actually needed?

Here is an example.

I am creating an object that is a collection manager basically. It needs to read in data from a file and it stores it inside of an array.

Do I use the constructor to just create an object with base properties and read data later, or should I read in all the info and set up the array inside the constructor which saves time later but takes up extra time here, or should I do something along the lines of

 public myConstructor(String filename) {
data = readDataIn(filename);
} 

This is not actual code, just an example of outsourcing to different methods to "pretty up the code" instead of a super long constructor method I can have say 5-6 short and good looking methods that can only be accessed by the constructor.


The constructor should do just enough work to get the instance into a state that satisfies its contract. Each method should then do just enough work to fulfill the method's contract and leave the instance in a state that satisfies its contract.

Very rarely should a constructor call cause side-effects or modify its inputs. These are just not often required to satisfy a contract. For example, a connection class shouldn't touch the network on construction. Since it has to be closeable, the closed state must be part of its contract, and so the "just enough work" standard dictates that the constructor puts it in a ready, but not yet open state.

Your particular example couples your class to the file system. You would probably get a more testable, more general class by using Guava Files to do the reading and taking a string with the content instead. You can get the convenience of a constructor coupled to the file system by writing a convenient static MyClass fromFile(String path) factory function that does new MyClass. That moves the portion of your code that is coupled to the filesystem outside the portion that interacts with instance variables reducing the number of possible interactions to test. As others have noted, dependency injection is another good way to achieve decoupling.


Really depends on your API style. Note that you may wish to have multiple constructors, such as:

public MyThing(String filename) { }
public MyThing(FileInputStream filestream) {}
public MyThing(File file) { }
public MyThing(byte[] rawdata) { }

at which its judicious to consolidate the file loading operation into a method or two (file open and file parse)


In this case, I would use dependency injection, so that your constructor requires data that has already been computed, and defers the computation to whatever invokes the constructor. I might provide an additional static factory function that does all this complicated setup so that it is convenient to construct this object (e.g. in tests), but at least it would be possible for the user of this class to come up with a more clever (possibly parallelized or lazily-initialized) way of creating this class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜