Is it bad practice to do a lot of things inside a builder? Why?

Asked

Viewed 192 times

3

Is carrying out heavy processing, such as queries to a database or consuming an API, within class constructors considered a bad practice? Why?

public class Classe
{
    private String dados;

    public Classe()
    {
        // ...
        dados = Database.GetDados();
        // ...
    }
}

It would be better to do this way or similar, taking out the processing from the builder?

public class Classe
{
    private String dados;

    public Classe()
    {
        // ...
    }

    public void Inicializar()
    {
        dados = Database.GetDados();
    }
}

And to "build":

public void Call()
{
    Classe x = new Classe();
    x.Inicializar();
}

I have heard from some higher education teachers that it is bad practice, but I see no reason. The object should not be built and its dependencies at the same time?

1 answer

2


"It’s bad to do a lot of things inside builders?"

If too much is fast, no, define quick as a requirement of your application and the response time that is satisfactory for the object in question.

"Carrying out heavy processing, such as BD queries, within builders is considered a bad practice? Why?"

Yes. Because instantiating an object is commonplace and should be fast, we usually avoid operations that we know are heavy and most of the time are being done in the constructor because the programmer tries to make sure things are there afterwards, And he usually doesn’t need them on the builder. In your example, you just load the property, do not use it in the constructor flow, so you could leave this action for the moment when the property is actually used.

If you really need to perform this operation on during the construction of objects, you should consider the scenarios where this object will be used, because, as you do something great in the constructor, certain operations with objects that are commonplace have direct impact on the application, follow some examples.

1 - Object listing for grids/tables: it is common to create screens where the system lists (including with paging) objects for a user to operate on them. As you necessarily have to instantiate the object to display the data, even if it is just the name and ID, you will have a ridiculously slow grid, consuming memory, database and application unnecessarily.

Alternatives that can improve your life: Lazy Load.

2 - Strong coupling: Usually an object that has a slow constructor is a complex object, which may need to access various data sources and instantiate several other objects, so its implementation should be careful with coupling the concrete classes. This can also cause your layers (if this is your architecture) to be confused.

Alternatives that can improve your life: Dependency Injection

3 - Calls to build other complex objects that have constructors as complex as what you are building. The.o (this phrase is cool): You can engage an object that needs to be built by calling a second complex constructor, but that will only be used in certain situations (it looks like a case for Lazy load :)) and sometimes you may not even need it.

Alternatives that can improve your life: proxy Object.

To tell you the truth, in some scenarios you rarely escape the fact that you have to build heavy objects, but most frameworks solve this for you and already have these design standards implemented.

If you use Entity Framework, for example, Lazy load is already there for you almost natively. You just need to ask to use. Many modern object-oriented applications use Orms and this facilitates the implementation of these techniques because it happens a lot with objects that need to be stored in databases and programmers end up knowing the design patterns as a feature of the ORM, not as a generic solution that he himself can implement.

But, this is a lack of knowledge and not a constraint of the pattern, you could use the pattern to slow the load of a texture of a file that comes from the disk, not necessarily from the bank.

It is important to note that I responded using the context of . NET, but much of what I wrote here is a general solution on most POO platforms, Java is a great example.

Bringing some of this all to your code example:

public class Classe
{
    private String dados;

    public Classe()
    {
        // ...
        dados = Database.GetDados();
        // ...
    }
}

Your class needs to know the concrete implementation of the Database class (strong coupling, even if it is only the interface.

Your class necessarily goes to the database to load the data attribute, even if you don’t use it. Imagine another name attribute that you use in the grid but which is returned in the constructor, something like:

public class Classe
{
    private String dados;
    private String nome;    

    public Classe()
    {
        // ...
        dados = Database.GetDados();
        nome = Database.GetNome();
        // ...
    }
}

In this case, in addition to coupling, you would be going to the bank twice, even if you only need to show the name on the grid/table/screen. Classic waste of resources and performance. An Object/Lazy load proxy would leave this load for later, causing the object to be instantiated much faster and you would only pass through the bank for what you really need.

"It would be better to do this way or similar, taking out the processing from the builder?"

No. Because the implement of a class is often not your user, so you don’t guarantee that the users of your class will call this method, which ends up inserting a point of failure in the application. Another important and also conceptual factor is that you are only slowing the constructor actions down to a secondary method, but, there is no golden rule, it depends on what you are doing.

If possible, avoid distortions of already consolidated design patterns, they are there because much better people than us have faced this.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.