What is the advantage of hiding the class constructor in favor of a static method (no .NET)?

Asked

Viewed 2,252 times

14

My leader uses this pattern in ALL his classes (I’ll give the examples in C#, but it goes for any . NET language):

public class MeuTipo
{
    private MeuTipo() { } // esconder o construtor

    public static MeuTipo CriarMeuTipo()
    {
        MeuTipo meuTipo = new MeuTipo();
        return meuTipo;
    }
}

I really don’t understand why this is happening. Its classes are not even immutable (although I also do not think that there would be an advantage even if the class were immutable), so, besides this seems to me a pattern without much utility, it also prevents us from using constructors with properties, as for example... (I will use a supposed class Pessoa)

new Pessoa { Nome = "João", Sobrenome = "Doe", (...) } // não é possível nesse padrão

Therefore, we are obliged to imagine all the scenarios in which a constructor would be possible. For example, supposing that on one occasion the Pessoa can start without any data, or only with the first name, or with both names, we are obliged to do the class like this:

public class Pessoa {
    private string _nome;
    public string nome {
        get { return this._nome; }
        set { this._nome = value; }
    }

    private string _sobrenome;
    public string sobrenome {
        get { return this._sobrenome; }
        set { this._sobrenome = value; }
    }

    private Pessoa() { }
    public static Pessoa CriarPessoa() {
        return CriarPessoa(null);
    }
    public static Pessoa CriarPessoa(string nome) {
        return CriarPessoa(null, null);
    }
    public static Pessoa CriarPessoa(string nome, string sobrenome) {
        Pessoa pessoa = new Pessoa();
        pessoa.nome = nome;
        pessoa.sobrenome = nome;
        return pessoa;
    }
}

While we could do so:

public class Pessoa {
    public string Nome { get; set; }
    public string Sobrenome { get; set; }
}

I really can’t understand why I go to so much trouble to lose a language resource, so I can’t help but think that there might be a reason for it. If there is a reason, be it Design Patterns or some kind of reason for legacy code, can anyone enlighten me?

Note: I NAY I want opinions here, because this is not a review site. I asked this question because I believe that some programmer longer than me, or who has worked with Object Orientation outside the . Give me an answer to why that would be an advantage.

By the way, my leader used Java in the past. So I think there is an answer certain to that question.

  • 2

    I was going to comment exactly on your last line. I saw this Pattern in Java programmers, but I don’t see the advantage in . net

4 answers

13


This pattern is useful in rare cases.

One is to implement the Singleton standard, in which the constructor is hidden, and a static method is used to create a new Singleton or return the existing one. Simply:

public class MySingleton{    
    private static MySingleton _singleton = null;

    private MySingleton() { }

    public static MySingleton GetInstance() {
        if(_singleton == null)
            _singleton = new MySingleton();
        return _singleton;
    }
}

(Note: the above example could be improved with double-checked Locking for example to ensure thread Safety)

However, in most cases they all Private constructors are nothing but trouble. Prevents unit tests in isolation, cannot mock dependencies, cannot inject dependencies, etc.

With all due respect, your leader should go back to college...

  • +1 for the answer certain as I asked. And I wanted to give +10 by the comment at the end. xD (Note: It nay uses the Singleton standard -- nor does unit testing or mocking)

  • 1

    @Andréleria asks your leader what are the advantages of using this approach in all classes. I would be surprised if he could give it to you one pertinent advantage...

  • I question him every time I feel like I can ask him without risking being burned in front of my boss. But I can no longer count on his answers, because as in this question, I have already shown that much of what he says is good practice is useless (just as he has already told me that good practice is bad practice...)

  • 1

    @Andréleria Whenever you suspect the tips of your leader, ask here in the O.R.;) There are no leaders! If the answer is correct and substantiated, upvote - otherwise, downvote! Democracy for all :D

  • 1

    Just to complement, this pattern is also useful when there is a need to control the use of resources (that is, control the instantiation of class objects). Classic example in games: a missile launched by a ship, which when "leaving" the screen can be reused without the need to instantiate a new object. In addition to the problems cited by @dcastro, this pattern may also hinder or prevent the use of reflection (http://pt.wikipedia.org/wiki/Reflex%C3%A3o_(program%C3%A7%C3%A3o)) in some languages, since the class constructor is private.

  • 1

    Note also that since there is only one constructor and it is private, the constructor cannot be used in subclasses (see this OS thread for details: http://stackoverflow.com/questions/16661595/why-can-you-not-inherit-froma-class-whose-constructor-is-private). So, if the default is necessary, it might be better to declare the constructor as protected rather than private.

Show 1 more comment

10

There are two standards (which I remember now) that benefit from builders that are not public:

  • Factory

  • Singleton

Neither of these two patterns benefits from a static construction method... Singleton has a static method (or property), but it is not a construction method but a obtaining the instance, which may or may not build the object.

There is, however, a purpose for static construction methods:

  • construction with inference of argument types

  • construction with semantics (very important for maintainability)

Standard Factory

The pattern Factory determines that an object is built by a objects. This object factory implements an interface so that one can use inversion control (Ioc) of building objects, ie externalize the construction of objects, being that the object factory becomes a dependency of all who need to build the object.

public interface IFabricaMeuObjeto
{
    MeuObjeto Criar(int exemploParametro);
}

In this pattern the object builder is not public, so programmers are not induced to create the object using a constructor, rather than using the factory of objects. In this case it would not be private but yes internal.

public class MeuObjeto
{
    internal MeuObjeto()
    {
    }

    public int Inteiro { get; set; }
}

Utilities of the Factory standard

This is a very useful pattern as it allows in mocking the construction of new objects, in addition to enabling aspect-oriented programming, for example, if you want to log every time an object is created, you can implement the object factory interface, getting the original factory and implement the LOG thus:

public class FabricaMeuObjeto : IFabricaMeuObjeto
{
    public MeuObjeto Criar(int exemploParametro)
    {
        return new MeuObjeto { Inteiro = exemploParametro };
    }
}

public class FabricaMeuObjetoLog : IFabricaMeuObjeto
{
    IFabricaMeuObjeto original;

    public FabricaMeuObjetoLog(IFabricaMeuObjeto original)
    {
        this.original = original;
    }

    public MeuObjeto Criar(int exemploParametro)
    {
        return this.original.Criar(exemploParametro);
        Log.CriarLog("MeuObjeto foi criado.");
    }
}

On system startup, using some dependency injection framework:

container.Register<IFabricaMeuObjeto, FabricaMeuObjetoLog>();

I used the Simpleinjector in this example.

Singleton standard

The Singleton pattern is very useful for objects that only need one the entire execution time of the program. Thus, the constructor of the object should not be public, so as not to induce programmers who use object to error.

The Singleton is obtained from a static call, however I see no problems in make this Singleton be obtained from an injection framework of dependencies. Simpleinjector (which is what I use) supports a form of injection in which is always injected the same object, when it is needed... for me is a good way to integrate two very useful patterns, providing the single instance through a service interface:

public interface ISingletonService
{
    MeuObjeto PegarInstancia();
}

public interface SingletonService
{
    public MeuObjeto PegarInstancia()
    {
        return MeuObjeto.Instancia;
    }
}

public class MeuObjeto
{
    internal static MeuObjeto Instancia { get; private set; }

    static MeuObjeto()
    {
        Instancia = new MeuObjeto();
    }

    private MeuObjeto()
    {
    }
}

At system startup, using some dependency injection framework, which in this case is the Simpleinjector:

container.Register<ISingletonService, SingletonService>(Lifestyle.Singleton);

Construction with inference of generic types

One utility I see for static building methods is to make inference of types of a constructor of an object that has generic parameters, once that C# does not accept to infer types when using the operator new. That doesn’t work on C#:

public class MeuObjeto<T>
{
    public T Valor { get; set; }

    public MeuObjeto(T valor)
    {
        this.Valor = valor;
    }
}

...

var obj = new MeuObjeto( 1 ); // o C# não vai inferir o construtor a ser usado

The following build error will occur:

Using the Generic type 'Meuobjeto' requires 1 type Arguments

For this can be created a static method, in another class, so that can take advantage of type inference to create the object:

public static class MeuObjeto
{
    public static MeuObjeto<T> Criar<T>(T valor)
    {
        return new MeuObjeto<T>(valor);
    }
}

...

var objInt = MeuObjeto.Criar( 1 ); // isso funciona
var objStr = MeuObjeto.Criar( "string" ); // isso também funciona

Object construction with semantics

When a constructor has a specific meaning, it would be better expressed through a method with a specific name, I prefer to use construction methods than the operator new. A good example in the framework . Net is the TimeSpan, that has several static construction methods, which could not be expressed using builders:

  • TimeSpan.FromDays

  • TimeSpan.FromSeconds

  • TimeSpan.FromTicks

When there is semantics in the construction, probably the name of the method will not be only Criar... because "create" does not present any better semantics than the own new.

  • Great explanation. Too bad my leader doesn’t use any of these...

1

This way of working with the builder is widely used in the Singleton design pattern. To answer the question, it is not good practice to treat all classes in this way. Try to talk to your leader and understand why you do it this way.

1

Immutable Objects.

The default setting for immutable objects is usually the definition of a private/protected constructor, the absence of sets, and the definition of constructors for the correct completion of the instance.

The code gets more "strange", but for those who want to work with parallel programming (and immutable objects are essential in this programming model), there is no other way.

This also applies to hybrid languages, for example Scala (functional and object-oriented).

If the intention is not to work with immutable objects and there is no need for a parallelism solution, I see no point in using this pattern. Immutable objects tend to decrease the bugs of side effects, but requires good architectural planning.

See a definition in Value Object

  • 3

    What do you mean "there is no other way"? It is perfectly possible to use a constructor with immutable objects.

  • It is not advisable because you must provide set methods, which breaks the "default" definition of immutable objects. This "default" forces the developer to ALWAYS create a new instance instead of updating it.

  • 1

    Both in the . NET as on other platforms, this easily resolves by defining private setters (in the case of auto-properties) or simply by not defining setters (in the case of encapsulation). I still don’t see why it’s not advisable, or why there would be no other way.

  • 1

    @That doesn’t make any sense. If I want to create an immutable class, I create the necessary constructors, with the necessary arguments. Privatize constructors and create methods Factory statics does not help in the immutability of the class.

  • Think you want to force the developer to always create a new instance. How would you do that? You cannot allow him to use set s. And each time you change some value in the object, be forced to create a new instance. The only way is to make the constructor private/protected, remove all set s and provide new constructors where the developer is required to provide the values. Factory methods are not part of this standard. Remember, I’m only talking about the default constructor, no parameters.

  • @Marcelohaßlocher For this there are constructors with more parameters. I don’t see how a static method can be more efficient than a constructor for immutable classes. Example

  • 1

    @Marcelohaßlocher 1) The question is not to hide "only from the default constructor, no parameters". It is about "hiding the constructor from the class in favor of a static method". 2) The standard constructor, without parameters, can be useful for immutable objects - it can initialize the object with standard values. Immutability has nothing to do with hiding builders - much less with statistical methods. Scala, for example, promotes the use of immutable objects and - Shocker! - technically there are even no statistical methods.

  • 1

    To make a class immutable, just delete all the setters (public or not) and make the Fields private readonly.

  • Static methods are not part of the "pattern" I quoted. They really cannot be used as constructor substitutes. The fact is that in C#, for the little I know, there is no way to hide the default constructor (except for some scams). In Java, you can do this and the compiler complains if you try to instantiate with the default constructor, which makes creating immutable objects easier. In Scala, the fact that we have how to declare anything like val helps a lot in the use of immutability. The point is that I believe the leader tried to bring an idea, but set it wrong.

  • @Marcelohaßlocher In C# you hide the default constructor just like in Java.

Show 5 more comments

Browser other questions tagged

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