Os argumentos nomeados substituem o padrão do construtor?


20

Ao usar uma linguagem que suporta argumentos nomeados e opcionais, o padrão do construtor não tem mais um uso prático?

Construtor:

new Builder(requiredA, requiredB).setOptionalA("optional").Build();

Argumentos opcionais / nomeados:

new Object(requiredA, requiredB, optionalA: "optional");

3
Como você lida com 20 argumentos opcionais? Não há um problema que o Construtor precise resolver até que fique grande. No ponto que você descreveu aqui, você tem dois construtores (e eu não construiria um construtor para esse pequeno problema).

1
Mesmo com argumentos opcionais - se o construtor tiver mais de 2 argumentos, sou a favor de usar um objeto de valor para encapsular a configuração. O mesmo vale para inerfaces fluidos e construtor: qualquer coisa maior que 3 seria substituída por um objeto de valor.
Thomas Junk

Respostas:


21

Os construtores são mais úteis quando seu objeto precisa de muitos argumentos / dependências para ser útil, ou você deseja permitir várias maneiras diferentes de construir o objeto.

Em cima da minha cabeça, eu posso imaginar que alguém possa querer "construir" objetos em um jogo 3D como este:

// Just ignore the fact that this hypothetical god class is coupled to everything ever
new ObjectBuilder(x, y, z).importBlenderMesh("./meshes/foo")
                          .syncWithOtherPlayers(serverIP)
                          .compileShaders("./shaders/foo.vert", "./shaders/foo.frag")
                          .makeDestructibleRigidBody(health, weight)
                          ...

Eu diria que este exemplo é mais legível com os métodos construtores que criei agora do que com parâmetros opcionais:

new Object(x, y, z, meshType: MESH.BLENDER,
                    meshPath: "./meshes/foo",
                    serverToSyncWith: serverIP,
                    vertexShader: "./shaders/foo.vert",
                    physicsType: PHYSICS_ENGINE.RIGID_DESTRUCTIBLE,
                    health: health,
                    weight: weight)
                    ...

Em particular, as informações implícitas nos nomes dos métodos do construtor precisam ser substituídas por mais parâmetros, e é muito mais fácil esquecer um parâmetro em um grupo de parâmetros intimamente relacionados. De fato, o shader de fragmento está ausente, mas você não notaria isso a menos que soubesse procurá-lo.


Obviamente, se o seu objeto precisar de um a cinco argumentos para construir, não há necessidade de envolver o padrão do construtor, independentemente de você ter nomeado / não parâmetros opcionais.


Eu não compro seus argumentos. Se os nomes dos métodos do construtor forem tão maravilhosos, você poderá usá-los também para os nomes dos parâmetros. Se os parâmetros estiverem intimamente relacionados, coloque-os em um pequeno construtor de objetos.
user949300

@ user949300 Acho que você perdeu a parte importante do argumento, que é o de que os métodos do construtor aqui descrevem as relações entre os parâmetros que se perdem se você tiver apenas alguns parâmetros opcionais. No exemplo do construtor do Ixrec, "saúde" e "peso" são claramente parte lógica das configurações destrutíveis do corpo, mas esse relacionamento é perdido na versão opcional do argumento.
Jules

1
Não se um dos parâmetros opcionais é (corpo: nova DestructibleRigidBody (saúde, peso), ...)
Weyland Yutani

@Jules. O que Weyland disse - faça um construtor bem nomeado para peso e altura.
user949300

8

Além do que o Ixrec disse, os construtores ou o método nomeado parâmetros não permitirão que você tenha seu objeto em um estado a ser construído, no qual ele ainda pode ser modificado antes de construí-lo. Esta é a beleza do Construtor, onde você pode delegar partes de sua construção para diferentes métodos ou classes:

var myThingBuilder = new ThingBuilder("table");
myThingBuilder.setAttribute(Attributes.Legs, 4);

inventoryManager.setPrices(myThingBuilder);

// inventory manager
var availableCheapestMaterial = getMaterial();
myThingBuilder.setMaterial(availableCheapestMaterial);

Basicamente, você também pode lançar seu construtor em torno de seu sistema até que esteja pronto para construir o objeto final, permitindo diminuir a quantidade de conhecimento que seu construtor-consumidor precisa ter.


Eu não entendo o seu último parágrafo. Se você "lançar seu construtor em torno do sistema até que esteja pronto", ele terá muito conhecimento do sistema. Seu ThingBuilder conhece Atributos, é misteriosamente modificado pelo InventoryManager e conhece Materiais. Não veja como isso está diminuindo o conhecimento.
user949300

@ user949300 Pense em como seria sem o construtor viajando por todo o sistema. Você seria forçado a ter uma aula com um enorme fator de fan-out, e isso é apenas necessário para criar a Coisa. (Obviamente, supondo que sua classe não concentre todo o conhecimento, é isso que queríamos evitar em primeiro lugar.) Agora, se essa classe tiver outra responsabilidade, você estará criando uma classe enorme, quebrando S no SOLID . Se essa é a única responsabilidade, você está se tornando um ThingBuilder.
Alpha

1

Depende do que você está fazendo com o construtor.

Se você estiver usando o construtor apenas para definir (e variar) propriedades do objeto e (adiar) a criação do objeto, ele poderá ser substituído por parâmetros nomeados.

Substituindo o construtor, você pode ter a troca de legibilidade / uso mencionada pelo @Ixrec (ou pode não o ter, depende do que você está fazendo com o construtor).

No entanto, se o construtor fizer mais do que apenas manter as propriedades e cada etapa da construção envolver lógica, ela não poderá ser substituída.

O MockBuilder é um exemplo em que não pode ser substituído por parâmetros nomeados. Na página:

A lógica nas etapas de criação não pode ser substituída por parâmetros nomeados


-5

O padrão do construtor é essencial ao trabalhar com objetos imutáveis. Existem muitos benefícios ao trabalhar com objetos imutáveis, especialmente para tornar seu programa mais robusto na execução em um ambiente simultâneo (ou seja, threads)


3
Sim, os Construtores são ótimos para trabalhar com objetos imutáveis ​​complexos (ou mesmo mutáveis ​​- você precisa garantir que o objeto esteja em um estado consistente antes de poder ser usado). Dito isto, new Integer(42), new BigDecimal("42.000")e new String("foobar")são todos os construtores para imutáveis que ... bem, um construtor seria desnecessariamente complexo para esses casos. Portanto, um construtor não é essencial para trabalhar com imutáveis ​​quando os construtores também podem funcionar.

Sim, um construtor pode ser usado com objetos imutáveis, que não estão sendo negados. Mas a pergunta original era se o padrão Builder tem algum uso prático além dos argumentos opcionais e minha resposta foi esclarecer isso.
Codigoabbler

2
A pergunta original não diz nada sobre objetos imutáveis. Ele está perguntando sobre parâmetros nomeados e o relacionamento com eles com os Construtores. Sua resposta é sobre o construtor e sua relação com objetos imutáveis. É difícil ver como sua resposta responde à pergunta.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.