Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How much should be done in a constructor

Tags:

java

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.

like image 968
Andy Avatar asked Jan 19 '23 19:01

Andy


2 Answers

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.

like image 173
Mike Samuel Avatar answered Jan 25 '23 23:01

Mike Samuel


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)

like image 20
Yann Ramin Avatar answered Jan 26 '23 00:01

Yann Ramin