Como divulgar a programação genérica entre os membros da equipe?


20

Estou hospedado em um ambiente em que as pessoas acreditam:

  1. Os genéricos Java são o recurso usado exclusivamente para a gravação de bibliotecas e não para a codificação real.
  2. C ++ é uma linguagem de programação OO; templateé um recurso opcional e evitável

No entanto, essas pessoas dependem muito das bibliotecas criadas usando programação genérica (por exemplo, STL, contêineres Java). Se eu escrever um código usando templates ou generics, o revisor de código provavelmente o rejeitará e fará um comentário para escrevê-lo de maneira "adequada / compreensível / elegante" .

Essa mentalidade é aplicável do programador normal ao gerente mais sênior. Não há saída, porque 90% do tempo, essas pessoas fazem lobby.

Qual é a melhor maneira ( sem ser cortada ) de explicá-las, a abordagem prática de escrever código que constitui OO e programação genérica, ao mesmo tempo?


11
Desejo-lhe a melhor sorte, mas você provavelmente vai ter de sair se você quiser que o seu caminho ..
The Muffin Man

3
@TheMuffinMan, você está certo. Saí daquele local de trabalho e agora tenho minha própria empresa. Aqui eu tenho controle completo sobre a codificação!
Iammilind 6/03

Respostas:


14

Ainda existem pessoas no mundo que não usam genéricos jave na "codificação comum". Eu posso acreditar com modelos C ++, mas genéricos? Eles nem são difíceis de aprender / usar. Sério, os melhores recursos do Java e C ++ são respectivamente genéricos e modelos.

A melhor maneira de convencer as pessoas das coisas é argumentar convincentemente, não ameaçar e estar certo.

Desde que você não esteja usando algo como modelos como sua linguagem de programação, o polimorfismo paramétrico (genéricos / modelos) é quase certamente bom.

1. Evita duplicação de código.

Isso é óbvio, mas o código polimórfico é o código geral. É por isso que é chamado de genérico.

2. Suporta melhor verificação estática.

Sem o polimorfismo paramétrico, você acaba escrevendo coisas como public Object clone()ou public boolean equals(object b)que não são apenas abominações, eles têm tipos que não fornecem informações sobre o que fazem e invariavelmente acabam lançando exceções em todo o lugar. A alternativa ao polimorfismo paramétrico está em todo o lado

3. Polimorfismo não paramétrico O código OOP é basicamente incapaz de lidar com "métodos binários" de maneira correta.

Você usa isso frequentemente.

4. É uma boa prática

Em Java, o uso de genéricos é considerado uma prática recomendada (consulte Java eficaz por Josh Bloch). Os principais pensadores de C ++, como Sutter e Alexandrescu, também incentivam o uso de modelos para resolver uma variedade de problemas.

5. Ele se encaixa no paradigma OO.

As pessoas geralmente não percebem isso, mas a combinação de subtipagem e genéricos produz um sistema MUITO mais poderoso, expressivo e orientado a objetos do que qualquer sistema com apenas um deles.

Considere os mixins de Scala. Esse é um ótimo recurso que permite reunir seus objetos a partir de peças componentes. Genéricos e modelos podem simular alguns desses benefícios. Por exemplo, digamos que um de seus objetos use um banco de dados. Um bom design faria você abstrair o acesso ao banco de dados em uma classe separada. Se bem feito, isso não apenas permite que você zombe do armazenamento de dados (chave para a testabilidade), mas também significa que você pode adicionar implementações alternativas, como o novo banco de dados no-sql. Aqui, porém, você pode ter um problema, independentemente da implementação usada, obterá diferentes recursos do seu objeto de negócios.

Genéricos para o resgate!

   public class Business<S extends Datastore>{
      private S store; ...
   }

Agora você pode começar a diferenciar estaticamente seus Businessobjetos com base na capacidade de usar recursos específicos do banco de dados. Você ainda precisa de algumas verificações e conversão do tempo de execução, mas pode começar a criar MUITO melhor código.

e

6. Código normal não existe.

Existem apenas três coisas no universo da programação:

  1. bibliotecas,
  2. configurações e
  3. código incorreto.

Se você não pensa no seu código como se fosse uma biblioteca, estará com sérios problemas quando os requisitos do seu projeto mudarem. Arquitetura é (sem dúvida) a arte de projetar boas APIs.

Acho essa atitude impressionante. Depois que você se acostuma a programar com tipos parametrizados, não usá-los apenas torna tudo um problema. E Java e C ++ têm vários pontos difíceis que ajudam a remediar.


7
Eu gosto da idéia de que normal codenão existe e que existem apenas três tipos: libraries, configurationse bad code. É um raciocínio idealista, embora você ainda precise explicar aos colegas, que podem não ser tão idealistas quanto você. Concordo, porém, que o uso de tipos parametrizados é simplesmente incrível quando você pega o jeito.
Spoike

3
Caramba, mesmo os modelos C ++ não são tão difíceis de usar se você não os usar para fins de metaprogramação de modelos. :-)
In silico

-1 por sugerir que todo mundo que decide não usar genéricos faz isso apenas porque não sabe como o recurso funciona.
tp1 31/12/11

dado o potencial de uso indevido, eu diria que restringir / não usar genéricos / modelos pode ser uma decisão muito melhor pela qual você deve dar crédito.
Ryathal 9/01/12

As pessoas que se recusarem a usar genéricos / modelos para engenharia de software em larga escala criarão acidentalmente e inevitavelmente uma "segunda linguagem" - um intérprete executado em Java, que implementa qualquer "linguagem comercial" que eles tenham em mente. en.wikipedia.org/wiki/Inner-platform_effect
rwong 29/07

16

Esta é uma forma especializada da pergunta mais geral "como convencer seus superiores a começar a usar uma tecnologia / maneira mais nova e melhor de fazer as coisas?"

Infelizmente, acho que não, e não tenho certeza. É por definição a escolha deles, já que eles estão lhe pagando para fazer as coisas de uma certa maneira que eles escolheram, não da maneira que você quiser. O melhor que você pode fazer é sugerir que essa tecnologia está disponível, muitas pessoas a estão usando e parece ser o caminho do futuro. Você pode até mencionar o fato que eles já devem saber: é melhor que as pessoas não deixem suas habilidades estagnadas. Mas é isso: se eles não compram, não há nada que você possa fazer.

Eles podem ter outras considerações que você não tem, porque você não está pensando no nível deles. Você está pensando como engenheiro, eles podem estar pensando mais em termos de negócios ou mesmo em termos de recursos humanos.

  • Os genéricos (ou o que for) melhorarão o valor de seu produto? Provavelmente não.

  • Os genéricos (ou o que for) dificultam para as pessoas que eles já contrataram para realizar seu trabalho? Sim.

  • Os genéricos melhorarão o tempo de colocação no mercado? Se o único engenheiro fosse você, talvez. Mas se um monte de engenheiros precisa ser treinado em genéricos antes que outra linha de código seja escrita em casa, não.

Portanto, você pode considerar apenas mudar de emprego. No meu último trabalho, fui o primeiro a usar genéricos com Java e, felizmente, eles não tiveram problemas; eles expressaram a preocupação de que os genéricos tornem o código "mais difícil de ler", mas eles me deixaram do meu jeito. Encontre um emprego como esse.


9

Eu transmitia o mérito dos genéricos ao revisor de código e a outros colegas antes de qualquer revisão:

1) Ao permitir que você especifique tipos que são acionados por uma classe ou método genérico, o recurso genérico transfere o ônus da segurança de tipo de você para o compilador. Não há necessidade de escrever código para testar o tipo de dados correto, porque ele é imposto em tempo de compilação. A necessidade de conversão de tipo e a possibilidade de erros em tempo de execução são reduzidas.

2) Os genéricos fornecem segurança de tipo sem a sobrecarga de várias implementações.

Portanto, [1] e [2] reduzem o risco de erro no código. Isso economiza tempo do desenvolvedor e, portanto, o dinheiro da empresa.

Se a legibilidade for um problema, o constrangimento de usar tipos genéricos pode ser comprometido. Esse é um dos motivos pelos quais você pode estender as diretrizes de codificação. Isso pode ser feito em um contexto de jornada de trabalho e não apenas para estender bibliotecas (no entanto, é uma idéia refatorar à medida que avança e marcar possíveis métodos candidatos para bibliotecas no código para facilitar o reconhecimento posteriormente). Portanto, não haveria razão para não usá-los em um contexto de trabalho diário.

Eu acrescentaria algumas declarações sobre como outros programadores não têm problemas com genéricos: os genéricos são amplamente usados ​​em Java e em muitas outras linguagens como C #. Qualquer programador sério acharia a vida difícil sem esse tipo de componente seguro.

No entanto, você pode considerar que alguns dos desenvolvedores podem não estar preparados para o risco. A gerência poderia ter tomado uma decisão consciente de proteger projetos no passado, mantendo-os fora de áreas perigosas. Aqui, tanto os inocentes quanto os culpados costumam receber a culpa, pois raramente são realizadas análises ou microgerenciamento suficientes.

Se você apresentar um bom argumento e não receber uma resposta fundamentada em troca, secretamente comece a procurar outra empresa que leve a sério a programação.


7

A menos que você seja o arquiteto / líder técnico, será difícil exigir que você use genéricos / modelos. Você realmente deve propor a solução genérica / modelo muito antes da revisão do código, de preferência antes de começar a implementá-la.

O que você pode fazer é demonstrar por que você deve usar um genérico em alguns casos. Se você puder demonstrar os benefícios, seus colegas poderão concordar. Os possíveis motivos pelos quais você deve usar genéricos / modelos devem ser os seguintes:

  • Deve permitir que você escreva menos código para tarefas repetitivas
  • Facilita o trabalho dos programadores
  • Impõe um padrão definido pelo arquiteto da solução
  • Ele encapsula recursos comuns, que forçariam os programadores a não copiar e colar código (ou seja, evitar o problema de manutenção dupla)
  • Provavelmente o seu futuro comprova seu código (embora essa avenida seja difícil de raciocinar)

Em um projeto Java recente, adicionei com êxito alguma classe abstrata genérica porque ela satisfazia algumas coisas básicas: facilitou as coisas para os outros membros da equipe, reforçou o padrão que o arquiteto já havia proposto e tinha um código comum que os programadores não precisavam. copiar e colar. Foi um padrão simples que o arquiteto escreveu sobre que pessoas razoavelmente competentes ainda se enganavam (devido à complexidade do sistema real em jogo), mas os genéricos marcam qual classe vai aonde.

Obviamente, não posso mostrar o exemplo real sem violar o contrato de não divulgação. Mas como um exemplo do que eu fiz, seria fazer o padrão de estratégia e aplicá-lo com genéricos. Portanto, este é o padrão de estratégia:

insira a descrição da imagem aqui

E para que os programadores imponham esse padrão, você pode adicionar o tipo genérico, Contextque deve usar algo que tenha um Strategytipo. Em termos de código, seria algo parecido com isto em Java:

// declare the generic Context class that has a type "S" 
// that is an upper bound class of Strategy
public class Context <S extends Strategy> {
    S strategy;

    // Constructor with an initial strategy
    public Context(S initialStrategy) {
        this.strategy = initialStrategy;
    }

    public void doSomething() {
      strategy.execute(); // assumes that Strategy has an execute() method.
    }

    public void setStrategy(S strategy) {
        this.strategy = strategy;
    }
}

Você pode fazer isso praticamente com qualquer padrão, até onde eu saiba. Certifique-se de poder testar seu design genérico / modelo com testes de unidade para verificar se ele funciona, para ter confiança no design do código.

Se seus colegas não gostarem da ideia, não a levem para o lado pessoal, talvez não tenha sido a solução mais fácil para eles lidar com o que você pensava. É por isso que você deve propor uma solução genérica / modelo antes de começar a implementá-la. Você ainda precisa trabalhar junto com seus colegas para resolver o problema real de uma maneira diferente.


Ame o diagrama! Qual ferramenta você usou?
yannis

@YannisRizos Usei o yuml.me que cria diagramas a partir da entrada de texto. No entanto, o serviço beta é um pouco problemático no momento (no entanto, você pode fazer upload da imagem gerada para sua postagem usando o link gerado).
Spoike

marcado, obrigado por compartilhar. embora eu realmente não queira aprender outra sintaxe, por mais simplista que pareça, é legal e vou tentar em algum momento.
precisa

@YannisRizos Ah, eu sempre esqueço a sintaxe. É por isso que existe uma página de amostras útil . Achei mais rápido escrever diagramas de classe simples no yuml do que usar o Visio.
Spoike

@YannisRizos yUml é uma ferramenta legal. Aqui estão alguns outros exemplos do que você pode fazer com ele: carnotaurus.philipcarney.com/tagged/yUML
CarneyCode

4

Sempre existem várias maneiras de fazer a mesma coisa. Se o uso de modelos for um uso indevido de modelos, a revisão de código deve falhar.

No entanto, se o seu código falhar na revisão, porque eles não entendem os modelos, o problema é de outro tipo. Nesse caso, aconselhe-os (de uma maneira agradável) a aprender modelos.


4

O que você está lidando aqui é uma coleção de preconceitos. As pessoas preferem o status quo, um pensamento de grupo se desenvolveu, e o argumento foi travado algumas vezes para que as pessoas fiquem arraigadas em suas crenças.

Uma das estratégias mais eficazes aqui é se concentrar em uma pequena vitória. Li o seguinte exemplo em um livro : o autor era um usuário não-Apple fiel. Ela não gostava deles, e não queria nada com eles. Ela teve muitas discussões com pessoas com uma postura pró-Apple, e cada uma delas empurrou os calcanhares mais fundo no chão. Então alguém comprou um iPod shuffle para ela e, assim, seus preconceitos desapareceram. Isso não a fez querer comprar apenas produtos da Apple, mas a postura rígida e anti-Apple havia sido substituída por um ponto de vista mais equilibrado. Havia espaço para compromisso, e ela acabou se convertendo lentamente na Apple.

Portanto, não tente convencer todos de uma vez: isso terá o efeito oposto. Concentre-se em uma coisinha e o resto acontecerá por si só. Apenas se livre da natureza bilateral do argumento para que as pessoas possam atravessar pouco a pouco, em vez de todas de uma vez.

O ponto específico a ser focado depende da sua situação, mas aqui está uma idéia: A divisão que você esboça entre bibliotecas e 'código real' parece muito antinatural. Na minha opinião, um programador que cria um aplicativo deve gastar 80% de seu tempo em uma biblioteca para o tipo de aplicativo que ele está criando e 20% usando essa biblioteca para criar o aplicativo. Todo código que vale a pena manter deve ser considerado uma biblioteca. Eu sugeriria aos seus superiores que você generalizasse parte do seu código em uma biblioteca interna (se ainda não o fez). Por sua própria lógica, eles devem usar genéricos para isso e, pela estimativa acima, 80% do seu código pode acabar dentro da biblioteca. Quando você conseguir que todos usem genéricos do outro lado, eles devem se acostumar com isso, e os preconceitos devem desaparecer.


Obrigado Peter, foi uma resposta muito perspicaz. Seus pensamentos se aplicam não apenas à minha pergunta, mas também à filosofia geral do nosso dia-a-dia.
Iammilind 3/10

2

Nota "compreensível". Se o revisor de código não vê o benefício dos genéricos, todo o <<<>>>material-é apenas um ruído incompreensível que é desnecessário.

Eu sugeriria dar uma olhada em quantos bugs atuais (abertos ou corrigidos recentemente) que o banco de dados de bugs contém que poderiam ter sido evitados usando genéricos. Procure ClassCastExceptions.

Observe também que, se você não possui nenhum erro que poderia ter sido evitado com o uso de genéricos, seus colegas argumentam que você não precisa deles.


2

Eu seria fácil nisso. Mudei do Java 1.4 para 1.6 há alguns anos e os genéricos têm sido uma verdadeira sacudida. É simples e muito útil se você estiver tentando conciliar algumas coleções, mapas e outras estruturas. No entanto, escrever classes que tomam dados genéricos como parâmetros, manipulam e passam para outras classes rapidamente se torna monumentalmente confuso. Fico muito satisfeito ao fazer tudo funcionar, mas me pergunto se o tempo e o esforço despendidos valeram a pena. Também temo que um bom número de programadores Java possa nunca realmente entender o que está acontecendo.

Mais alguns pensamentos aleatórios da minha jornada genérica até agora:

  • ClassCastExceptions ocorrem no tempo de execução, mas geralmente aparecem nas primeiras execuções e são fáceis de corrigir.
  • Todos os artigos que li sobre genéricos afirmam que, às vezes, eles simplesmente não funcionam e você precisa usá-los @SuppressWarnings(value="unchecked")ocasionalmente. Como você sabe se está além dos limites dos genéricos, ou se está sendo burro e precisa pensar mais?
  • Pode ser difícil aplicar @SuppressWarnings(value="unchecked")a apenas uma linha.
  • Adicionei alguns genéricos sofisticados a uma de minhas aulas. Eu conheci vários programadores que poderiam ter aprimorado a classe antes que eu a gerasse, que nunca poderia tocá-la e obter uma compilação limpa posteriormente.

A Generics limpou meu código e me alertou sobre problemas muitas vezes para rejeitá-lo, mas também vejo aumento do tempo de desenvolvimento, tempo extra gasto em treinamento e programadores Java obrigados a trabalhar em C #, C e Visual Basic. ..ou Java 1.4. Eu me concentraria em escrever código que seus colegas de trabalho possam entender. Se você pode usar alguns genéricos compreensíveis, ótimo. Eu vejo os genéricos Java como uma oportunidade / problema que ainda não foi descoberto.

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.