Does a lot of constructors do poorly?

Creating all final fields as a whole is a good idea, but sometimes I find that I am doing everything in the constructor. I recently ended up with a class that does virtually everything in the constructor, including reading the properties file and accessing the database.

On the one hand, this is the purpose of the class, it encapsulates the read data and I like to completely initialize the objects. The constructor is not complicated at all, as it delegates most of the work, so it looks good.

This, on the other hand, is a little strange. Moreover, in this conversation at about 5:58 p.m. there are good reasons not to do a lot of work in the constructor. I think I can fix the problem by passing the appropriate dummies as constructor arguments.

The question remains: does much work (or even all the work) in the designers?

+45
java constructor
Aug 13 '11 at 4:11
source share
5 answers

I think that "Doing the work in the constructor" is fine ...

... until you violate the Single Responsibility Principle (SRP) and adhere to Injection Dependency (DI) .

I asked myself this question too late. And the motivation against doing the work in the constructor that I found is either:

  • Hard to check
    • All the examples I saw were where DI was not used. In fact, the constructor that does the actual work is not to blame.
  • Perhaps you do not need all the results that your constructor computes, losing processing time, and it is difficult to test in isolation.
    • This is basically an SRP violation, not a constructor error that does the work for the response.
  • Older compilers have / had problems with exceptions thrown into constructors, so you should not do anything other than assigning fields to constructors.
    • I do not think that it is a good idea to write new code that takes into account the shortcomings of the statistical compiler. We could also end C ++ 11 and all that is good together if we do this.

My opinion is that ...

... if your constructor needs to work to stick to Resource Initialization (RAII) , and the class does not violate SRP and DI is used correctly; Then do the work in the A-Okay constructor! You can even throw an exception if you want to prevent the use of an object of a class whose initialization failed, rather than relying on the user to check the return value.

+25
Sep 27 '13 at 13:36 on
source share

This is a very open question, so my answer will be as general as possible ...

Performing work in designers is not as "bad" as before, when exception handling was not as common and developed as it is today. You will notice that in a conversation with Google Tech, designers are mainly considered in terms of testing. It was very difficult for the designers to debug the story, so it’s saying correctly that it’s better to do as little as possible in the designer.

With that said, you will notice that it also affects the implementation dependency / vendor pattern, which is notorious for complex constructors. In this case, it is preferable to leave ONLY the provider / DI code in the constructor. Again, the answer depends on what patterns you use and how your code "fits" together.

The whole purpose of using the constructor is to create a neat object that can be used immediately; those. new Student("David Titarenco", "Senior", 3.5) . There is no need to do david.initialize() , as that would be completely stupid.

Here are some of my production code, for example:

  Config Conf = new Config(); Log.info("Loading server.conf"); Conf.doConfig(); 

In the above case, I decided not to do anything with the constructor (it is empty), but it has a doConfig() method that runs the entire i / o disk; I often thought that the doConfig() method is simply pointless, and I have to do everything in the constructor. (I will only check the configuration file once, after all.)

I think that it completely depends on your code, and you should not think that putting "stuff" in your constructor is bad. What are the designers for! Sometimes we get getThis OOP ( getThis , setThat , doBark ), when the whole class really needs to do this, load the configuration file. In such cases, just put everything in the constructor and name it day!

+12
Aug 13 2018-11-11T00:
source share

Usually, if your object has a complex creation algorithm, you could probably simplify it with Builder or Factory. Specifically, if there are prerequisites for verification to create an object.

As soon as you start using Builders and Factories to create your objects, they will be able to check the pre and post conditions and make sure that your code clients can access a fully initialized object, and not half-work one, you can even use modern smooth mod interfaces to create your object and make it cool, D

 new EmailMessage() .from("demo@guilhermechapiewski.com") .to("destination@address.com") .withSubject("Fluent Mail API") .withBody("Demo message") .send(); 

Obviously, this is not your case, since it does not use Builder, but it is very similar to what you could create to make your constructor work less and make your code simpler.

+10
Aug 13 '11 at 4:18
source share

I had the following problems when I added too much code to the constructor:

  • It was difficult to write unit tests for the other methods of this class, because he wanted to do a lot of things in the constructor, so I had to set a lot of real things, or at least mocks (DB, file, whatever) for the simplest unit tests .
  • It was hard to write unit tests for the constructor itself. One way or another, putting a lot of code with diverse responsibilities in one block is even a bad idea. (A simple principle of responsibility.)
  • For previous reasons, it was difficult to use this class. For example, this completely prevented me from implementing some pending init methods, because it needs everything at the time the constructor is called. Ok, I could write a lazy init method in the constructor, good one.
  • Sooner or later, I realized that it makes sense to reuse some parts of the code that fit into the constructor. Well, when I first wrote the constructor, I also thought that these parts of the code would only be used there forever.
  • When I wanted to extend this class and insert some logic before or into the logic of the super constructor, it simply did not work, because the first thing to do in the constructor of the extended class is to call the super one.

So yes, doing a lot in the constructor is a bad idea, in my opinion.

Usually I just insert the field initialization into the constructor and run the init method when everyone is on board.

+7
Nov 23 '11 at 9:25 a.m.
source share

Having constructors and destructors, in my opinion, is good, but not doing too much work in them. This is especially true for access to files and databases, unless it is very class specific. You want your constructors / destructors to glow so that your program feels bold. Sometimes, as already, you come to the case when the designer does almost all the work. There is a way to make things easier. The concept / paradigm is called lazy assessment. The idea is to accept input and do nothing (for example, in the constructor), but use the inputs when you need the requested calculation.

Example: Suppose you have a class that reads a file, parses it, and tells you information as the sum of all the numbers in the file. You can do it all in the constructor. Using a lazy rating, you simply open the file and get getTotalSum () function. When it is called, it will perform a parsing and give you the result. That way you can also get getBestFit () to get the best match line. Sometimes you don’t want everything to be in order, and for some of the materials you make. Thus, the user will not wait until the constructor performs the calculations before the user decides what to do.

another example: let's say you have a view that loads 20 images. But only 5 is shown, and the constructor displays an array of images. You can load them all in the constructor, but from the point of view of users it will be very slow from the very beginning. Or you can upload 1 “upload” image and upload 1 image at a time. And as the user scrolls, loads more images in accordance with the shown / necessary base.

Of course, the problem is that you find errors, such as invalid images later on the road, and not the constructor. You can always perform simple checks to pre-confirm the input to some extent (for example, check the correct password).

+3
Aug 13 2018-11-11T00:
source share



All Articles