A "convenção sobre configuração" não está violando os princípios básicos de programação?

51

Eu estava olhando o framework Caliburn.Micro do WPF MVVM e li que muitas coisas padrão são baseadas em convenções de nomenclatura .

Por exemplo, ligação automática de propriedades no View para propriedades no ViewModel. Embora isso pareça conveniente (remove algum código padrão), minha primeira reação instintiva é que não é completamente óbvio para um novo programador que lerá esse código. Em outras palavras, a funcionalidade do aplicativo não é completamente explicada por seu próprio código, mas também pela documentação da estrutura.

EDITAR:

Portanto, essa abordagem é chamada de convenção sobre configuração. Como não consegui encontrar nenhuma pergunta sobre isso, alterei minha pergunta:

Minha pergunta é:

A convenção sobre configuração é uma maneira correta de simplificar as coisas ou está violando alguns princípios de programação (e, em caso afirmativo, quais)?

Geerten
fonte
8
A maioria das abordagens / princípios viola algumas outras abordagens / princípios até certo ponto. É principalmente uma questão de prioridades e trocas.
Joachim Sauer
11
É verdade, mas acho a diferença declarada na minha pergunta um pouco estranha e, portanto, estou interessado nas compensações específicas e possivelmente nos princípios violados ao usar a convenção sobre a configuração.
Geerten
O conceito de rastreabilidade de software é relevante aqui. Os programadores contam com ferramentas como grep, mas precisam de ferramentas melhores para rastrear os usos do código gerado. Por exemplo, as ferramentas devem tornar mais explícito que a classe css "user-id" está relacionada ao método gerado getUserId () e à coluna da tabela user_id.
Macneil

Respostas:

49

Não considero "um aplicativo deve ser totalmente explicado por seu próprio código" como um princípio fundamental de programação. Há muitas coisas que não são explicadas apenas olhando o código de um aplicativo. Além de conhecer as coisas básicas da própria linguagem de programação (sintaxe e semântica), você precisa conhecer as convenções. Se um identificador em Java começa com uma letra maiúscula, é um tipo. Existem muitas dessas convenções que você precisa conhecer.

A convenção sobre configuração consiste em reduzir a quantidade de decisões que o programador precisa tomar sobre as coisas. Para algumas coisas, isso é óbvio - ninguém consideraria ter um idioma em que a capitalização de tipos é algo que você precisa declarar no topo do seu programa - mas, para outras coisas, não é tão óbvio.

Equilibrar convenções e configurações é uma tarefa difícil. Muitas convenções podem tornar o código confuso (veja as variáveis ​​implícitas do Perl, por exemplo). Muita liberdade do lado do programador pode dificultar a compreensão dos sistemas, pois o conhecimento adquirido em um sistema raramente é útil quando se estuda outro.

Um bom exemplo de onde a convenção ajuda o programador é ao escrever plugins do Eclipse. Ao olhar para um plugin que eu nunca vi, eu imediatamente sei muitas coisas sobre ele. A lista de dependências está em MANIFEST.MF, os pontos de extensão estão em plugin.xml, o código-fonte está em "src" e assim por diante. Se essas coisas dependessem do programador definir, cada plug-in Eclipse seria diferente e a navegação de código seria muito mais difícil.

JesperE
fonte
4
+1: o desenvolvimento de software já é bastante complicado. Se você puder evitar a complexidade nas coisas que tem controle, faça-o. Salve a complexidade dos locais que você absolutamente precisa.
scrwtp 24/09/12
11
Obrigado pela explicação clara sobre a diferença e o equilíbrio.
Geerten
3
"Se um identificador em Java começa com uma letra maiúscula, é um tipo." - se um tipo depende do contexto da sintaxe e não do padrão de nomenclatura, as convenções de nomenclatura Java não afetam a 'configuração de compilação'. Tem certeza de que é um exemplo válido? O último exemplo também não está correto - trata-se de "convenções de configuração" e não "convenção sobre configuração". Você está dizendo as coisas certas, mas elas têm pouco a ver com o princípio subj.
Den
4
Não analise demais os exemplos, eles são apenas exemplos. O primeiro é apenas um exemplo de uma convenção, o último é um exemplo em que convenção é uma coisa boa. O exemplo Perl é um exemplo em que convenções demais (implícitas) são uma coisa ruim (IMO, devo acrescentar).
JesperE
11
O que eu odeio é que quando convenção sobre configuração se torna convenção sem configuração ... neste último caso, você tende a ficar preso em uma base de código, pode ser difícil integrar com outras ferramentas.
217 Andy
77

Deu +1 ao @JesperE e gostaria de adicionar algo:

é violar alguns princípios de programação

Sim, "convenção sobre configuração" viola o princípio "explícito é melhor que implícito" (veja, por exemplo, "Zen-Of-Python" ).

Por outro lado, a "configuração sobre convenção" oposta tende a violar "Simples é melhor que complexo" e, pior, viola o princípio DRY de maneira sutil, já que você precisa repetir nomes usados ​​no seu código também na sua configuração .

Doc Brown
fonte
4
Essa é a resposta mais direta à pergunta!
Joachim Sauer
Esta é a resposta correta real entre os dois mais votados.
Den
+1 para "explícito é melhor do que implícito"
Justin Ohms
12
Minha parte favorita sobre essa resposta é que ela destaca implicitamente a realidade, pois os princípios do bom desenvolvimento de software geralmente ficam tensos um com o outro. Engenharia é equilibrar essas tensões adequadamente para o seu contexto e aplicação específicos.
Chris Krycho
Boa resposta. Para expandir o comentário de @Chris Krycho, o bom dos padrões ou princípios de software é que você tem muitos por onde escolher. :-)
user949300
9

Algumas das "convenções sobre configuração" se resumem a padrões sensíveis. Você só precisa configurar algo para usá-lo para fins não padronizados. Eu tenho que comparar Struts com Rails aqui. No Rails, você precisa colocar suas "ações / telas" em uma pasta e elas simplesmente funcionam. No Struts, você ainda precisa colocá-los em uma pasta, mas também precisa criar um nome de ação E um arquivo JSP E um nome de formulário E um bean de formulário E especificar como essas três coisas funcionam juntas no Struts-config. xml AND especifique que o formulário pertence à solicitação (RESTful). Se isso não for suficiente, o mapeamento form / form-bean possui sua própria seção no Struts-config, que é mapeada independentemente para a seção de ação no mesmo arquivo e tudo depende de cadeias de caracteres manuscritas no arquivo JSP para funcionar. devidamente. Para cada tela, são pelo menos seis coisas que você não precisa fazer e tantas oportunidades para cometer um erro. Eu acho que você pode definir a maioria ou todas essas coisas manualmente no Rails, se necessário, mas 2/3 do tempo de desenvolvimento do Struts é gasto na construção e manutenção de camadas desnecessárias de complexidade.

Com toda a justiça, o Struts 1 foi projetado quando as pessoas estavam transportando aplicativos entre a área de trabalho e a web. A flexibilidade que o Struts adotou o torna adequado para tudo o que o Rails faz, além de tudo o que um aplicativo de desktop precisaria. Infelizmente, a montanha de configurações que permite essa flexibilidade é uma grande força para quem precisa escrever um aplicativo da Web ou apenas um aplicativo de desktop.

Eu trabalhei em algum lugar em que eles deram o próximo passo e argumentaram: "Configuração sobre código ", mas tendo visto isso levado ao extremo lógico, o resultado é que a configuração se torna uma nova linguagem de codificação. Era um jogo de shell em que a complexidade era contornada sem ser domada de maneira significativa. E isso me agradeceu por todas as redes de verificação de tipo e outras redes de segurança que uma linguagem de programação bem projetada possui. Algum formato de arquivo de configuração incompleto que explode sem nenhuma mensagem de erro se você adicionar um espaço ou um apóstrofo NÃO é uma melhoria em relação a uma linguagem de programação de qualidade que possui conjuntos de ferramentas de edição e um compilador de qualidade criado para ele.

Não posso imaginar que ter padrões sensíveis viole quaisquer princípios teóricos sobre extensibilidade e modularidade. Um programador de Ruby / Rails mais cedo espetaria um pôquer quente nos olhos do que mudaria para um framework como o Struts 1, onde todas as configurações são feitas explicitamente em vários arquivos XML. Não estou discutindo Rails vs. Struts EM GERAL, mas essa convenção pode ser uma enorme vitória na produtividade. Essas duas tecnologias são a comparação mais extrema do mundo real que eu já vi.

Se você trabalha com Java, consulte Joshua Bloch, "Effective Java", Item 2: "Considere um construtor quando confrontado com muitos parâmetros de construtor", pp. 11-16. Para a maioria dos propósitos, alguns parâmetros (configuração) são necessários e outros são opcionais. A idéia básica é exigir apenas a configuração necessária e fazer com que o usuário (que poderia ser outro programa) especifique opções adicionais, conforme necessário. Limpei um monte de código com esse padrão há um mês e ele brilha positivamente.

GlenPeterson
fonte
7

Em outras palavras, a funcionalidade do aplicativo não é completamente explicada por seu próprio código, mas também pela documentação da estrutura.

A funcionalidade de um aplicativo que usa uma estrutura sempre depende da estrutura; a convenção sobre a configuração não faz diferença nesse sentido.

Na minha experiência, a convenção sobre configuração não apenas torna o código mais legível, mas também reduz a possibilidade de introduzir bugs sutis (especialmente copiar-colar-bugs).

Por exemplo, vamos assumir que, em alguma estrutura A, o evento FooBardispara uma chamada para handleFooBar. Em outra estrutura B, essa correlação é configurada em algum lugar de um arquivo XML.

Então, em A, é simplesmente

handleFooBar() {
   ...
}

e, a menos que você tenha digitado incorretamente o FooBar, ele será chamado sempre que o FooBar acontecer.

Em B, é novamente

handleFooBar() {
   ...
}

mas também

<eventconfiguration>
  <event>
    <type>FooBar</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

Com centenas de coisas para configurar dessa maneira, é muito fácil criar acidentalmente um bug sutil como

<eventconfiguration>
  <event>
    <type>BarFoo</type>
    <handler>handleFooBar</handler>
  </event>
</eventconfiguration>

porque depois de copiar e colar, apenas mudamos, <type>mas esquecemos de mudar <handler>.

Como esses arquivos de configuração são grandes e monótonos, é menos provável que alguém encontre o bug revisando do que encontraria um bug semelhante no código real do programa.

user281377
fonte
11
+1: evitar configurações repetitivas, chatas de escrever, difíceis de ler e quase sempre óbvias é a principal vantagem da convenção sobre a configuração.
Joachim Sauer
-1

Pode estar violando poucos princípios, mas ao mesmo tempo obedece a um dos princípios mais fundamentais de design, o SRP (princípio de responsabilidade única).

rai.skumar
fonte
2
O uso de convenções não tem nada a ver com responsabilidade única. Eu poderia estar usando uma convenção e fazendo 100 coisas nela.
Suamere