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 operations 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With