Eu sempre tento seguir o princípio DRY estritamente no trabalho; toda vez que repito o código por preguiça, ele volta mais tarde quando preciso manter esse código em dois lugares.
Mas muitas vezes escrevo métodos pequenos (talvez 10 a 15 linhas de código) que precisam ser reutilizados em dois projetos que não podem se referir um ao outro. O método pode ter algo a ver com networking / strings / MVVM, etc. e é geralmente um método útil, não específico ao projeto em que ele se encontra originalmente.
A maneira padrão de reutilizar esse código seria criar um projeto independente para o código reutilizável e referenciar esse projeto quando você precisar. O problema é que acabamos em um dos dois cenários abaixo do ideal:
- Acabamos com dezenas / centenas de pequenos projetos - cada um para abrigar as pequenas classes / métodos que precisávamos reutilizar. Vale a pena criar um novo totalmente
.DLL
só para um pouquinho de código? - Terminamos com um único projeto que contém uma coleção crescente de métodos e classes não relacionados. Essa abordagem é para o que uma empresa na qual eu costumava trabalhar; eles tinham um projeto nomeado
base.common
que tinha pastas para coisas como eu mencionei acima: rede, manipulação de strings, MVVM etc.
Então, minha pergunta é:
Como uma equipe de software melhor reutiliza pequenos pedaços de código entre projetos?
Estou particularmente interessado se alguém trabalhou em uma empresa que possui políticas nessa área ou que se deparou com esse dilema pessoalmente como eu.
note: Meu uso das palavras "Projeto", "Solução" e "Referência" é proveniente de experiência em desenvolvimento .NET no Visual Studio. Mas tenho certeza de que esse problema é independente de idioma e plataforma.
fonte
Respostas:
Se eles realmente são métodos / classes reutilizáveis, você pode escrevê-los em um pequeno número de bibliotecas 'Swiss Army Knife'. Fazemos isso com bastante frequência na minha empresa; nós os chamamos de bibliotecas de estrutura:
Framework.Data
- Utilitários para trabalhar com consultas de banco de dados.Framework.ESB
- Métodos padrão para interagir com nosso barramento de serviço corporativoFramework.Logging
- Sistema de registro unificadoFramework.Services
- Utilitários para interagir com serviços da webFramework.Strings
- Utilitários para manipulação avançada de strings / pesquisa de strings difusos etc.Ao todo, existem cerca de uma dúzia de bibliotecas. Você pode realmente distribuir o código da maneira que achar melhor, para não precisar acabar com centenas ou despejar tudo em um conjunto gigante. Acho que essa abordagem se encaixa porque apenas alguns de nossos projetos precisarão
Framework.Data
e apenas alguns precisarãoFramework.Strings
, para que os consumidores possam selecionar apenas as partes da estrutura que são relevantes para seu projeto em particular.Se eles são realmente apenas trechos, e não métodos / classes reais que podem ser facilmente reutilizados, tente distribuí-los como trechos de código no IDE (por exemplo, trechos de código do Visual Studio ). As equipes com as quais trabalhei anteriormente tinham uma biblioteca de trechos em comum que tornava mais fácil para todos seguir nossas práticas de codificação padrão com código interno também.
fonte
IPAddressToString
é provável que os consumidores que lidam com protocolos de rede tenham que usá-lo, mas os consumidores que brincam muito com cadeias de caracteres podem não se importar com endereços IP. Provavelmente isso acabaria em um pacote de redeFramework.Strings
.Framework.Logging.Gibraltar
é um complemento específico para o sistema de registro.Discordo da resposta aceita por vários motivos.
Na minha experiência, quando vejo bibliotecas "diversas" como a resposta aceita, elas são uma desculpa para reinventar a roda (ou não inventada aqui (NIH) ) - um pecado muito maior do que violar o Dont Repeat Yourself (DRY) .
Às vezes, violar o DRY pode ser um compromisso razoável, é melhor do que introduzir um acoplamento rígido. A reutilização é uma preocupação secundária em comparação com um bom design orientado a objetos. Um pouco (quero dizer, pequena quantidade, aplique a Regra dos Três ) de duplicação é mais fácil de entender do que uma base de código de espaguete.
A abordagem de várias bibliotecas de uso geral é um mau exemplo. Isso leva a uma granularidade fina da montagem e muitas montagens são ruins. Recentemente, reduzi uma empresa internamente de 24 bibliotecas para 6 bibliotecas. Melhorou o tempo de compilação de vários minutos para ~ 20 segundos. O Visual Studio também é mais lento para carregar e menos responsivo com mais montagens. Ter muitas bibliotecas também leva a confusão sobre onde o código deve residir; prefira menos regras mais simples.
Por que as coisas no .Net Framework não são boas o suficiente? A estrutura é bem grande; muitas vezes eu vi código que reimplementa coisas que já existem lá. Certifique-se realmente de que suas estruturas estejam preenchendo lacunas na estrutura .Net e não existam apenas por razões estéticas (por exemplo, "Eu não gosto da estrutura .Net aqui" ou talvez alguma otimização prematura )
A introdução de outra camada em sua arquitetura tem um custo de complexidade significativo. Por que a camada existe? Eu vi uma reutilização falsa, com isso quero dizer que, o código é construído sobre uma estrutura interna. Teria sido muito mais eficiente implementá-lo diretamente sobre as bibliotecas padrão.
O uso de tecnologias padronizadas (como a estrutura .Net e as populares bibliotecas de terceiros / código aberto) tem benefícios que geralmente superam os ganhos tecnológicos comparativos de sua criação. É mais fácil encontrar talentos que conheçam essas tecnologias e seus desenvolvedores existentes investirão mais em aprendê-las.
Minhas recomendações:
fonte
Para pequenos pedaços de código - digamos, uma única classe sem dependências -, tendemos a copiar e colar o código nos projetos. Isso soa como uma violação do DRY, e eu admito que às vezes. Mas, a longo prazo, tem sido muito melhor do que ter algum tipo de projeto maciço e de várias cabeças por alguns motivos.
Primeiro, é mais simples ter o código à mão, especialmente ao criar e depurar coisas.
Segundo, invariavelmente você desejará fazer alguns ajustes no código comum desse projeto. Se você tem uma cópia local da fonte, basta fazer o ajuste e chamar um dia. Se houver uma biblioteca compartilhada, você poderá ajustar essa biblioteca e garantir que não interrompa todos os outros aplicativos ou criar um pesadelo de versão.
Portanto, se não for robusto o suficiente para o seu próprio espaço para nome, tenderemos a colocá-lo nos bits apropriados do projeto e chamá-lo por dia.
fonte
A segunda solução que você descreve não é tão ruim assim. No .NET, você também faz referência a um assembly do GAC, mesmo que apenas use uma única classe dele. "Arrastar código irrelevante" não é um problema que você possa imaginar. Nesse caso, é vital manter pelo menos métodos e classes relacionados organizados de maneira limpa em diferentes espaços para nome. Além disso, boas práticas para o design da API devem ser aplicadas para evitar que essa solução se torne uma bagunça.
Se se trata de bits muito pequenos de código, acho que a seguinte abordagem é um bom complemento para um projeto comum: permita que eles sejam duplicados em diferentes soluções. Lide com eles como práticas recomendadas: documente e comunique-os à equipe.
fonte
Eu só trabalhei em ambientes "corporativos", onde esse tipo de coisa tem sido um problema e cada vez que é a segunda opção adotada. Na maioria das vezes, funcionou bem, porque não houve nenhuma restrição na área de cobertura do aplicativo.
No entanto, tendo passado a última semana com uma start-up que está executando seu próprio servidor Nuget, estou inclinado a sugerir isso como uma alternativa viável. É claro que os problemas que espero surgir serão em torno da capacidade de descoberta.
Se os projetos são adequadamente granulares e os namespaces são sensatos, posso ver isso se tornando uma abordagem popular em alguns lugares.
fonte
Recentemente, eu pensei sobre isso e o que me ocorreu foi uma grande biblioteca de métodos comuns, como foi mencionado até agora, mas com uma reviravolta. O projeto da biblioteca permite que você configure, em tempo de compilação, quais partes são incluídas, como o projeto BusyBox . Com essa abordagem, você pode ter um repositório de biblioteca de estilo de pia de cozinha, mas pegue apenas as ferramentas necessárias ao compilar.
fonte
O GitHub tem uma ferramenta bastante útil para salvar trechos de código https://gist.github.com/
Ele armazena seus trechos como repositórios git que você pode manter em sigilo ou usar para compartilhar trechos com outras pessoas.
fonte
Dependendo do tamanho da equipe / projeto / empresa, isso será uma tarefa bastante difícil, a menos que já esteja incorporado ao seu ambiente de alguma forma e todas as soluções que você encontrar (se implementá-lo) custarão algum dinheiro. (Isso pode protegê-lo mais, mas você não poderá medir com facilidade). Você terá que verificar se vale o preço. Lembre-se também de que as soluções reutilizáveis tendem a se tornar abstratas e geralmente se ajustam a muitas situações, mas sem serem ótimas.
De qualquer forma, se você quiser fazer isso pelo código produzido por mais de uma pessoa, primeiro precisará ter consciência de todos e cooperação. Isso inclui desenvolvedores e gerentes.
Então, você precisa ter certeza de que conhece o escopo em que deseja fazer isso. Equipe? Projeto? Departamento? Companhia? Dependendo da resposta, o tipo de código que você colocará em tais soluções variará, assim como a granularidade com a qual você adapta as dlls. Depois de decidir sobre isso, alguém (de preferência com algum entusiasmo pela idéia - você?) Deve sentar-se e começar a colocar alguma estrutura nisso.
Apenas criar essas DLLs não será suficiente para fazer o truque. Para torná-los úteis, você precisará divulgá-los (para usuários e colaboradores) e mantê-los como qualquer outro software, o que geralmente significa que você precisa colocar alguém no comando por um longo tempo. Você também precisará de documentação confiável, que também precisará de manutenção. Com um pouco de sorte e cooperação, você pode ter algumas práticas recomendadas, mas também pode evoluir para um projeto próprio, dependendo do tamanho e do número de equipes envolvidas. E para isso você ainda precisará de suporte de gerenciamento.
fonte
Eu já tive muitos problemas e minha solução preferida é postar o código em um repositório habilitado para web do github / pubic. resolve muitos problemas -
Uma coisa que eu recomendaria - não importa onde você mantenha seus trechos, sempre pesquise no Google antes de usá-lo. as coisas mudam o tempo todo. os snippets salvos economizam tempo, mas também geram complacência .
fonte
Temos um projeto separado "utilitários", onde armazenamos todos esses pequenos métodos junto com testes.
Quando um projeto precisa de algum utilitário, ele apenas adiciona o arquivo de origem com o método necessário com "add as link".
Isso significa que não há dependências de tempo de execução adicionadas (a menos que o arquivo incluído precise de uma).
O sistema funcionou bem, mas como todos os outros, ele precisa discernir sobre o que é um utilitário. A solicitação de alta cobertura de teste funcionou bem para nós e os testes também são uma boa documentação de uso. A descoberta ainda é um problema não resolvido para nós.
Uma complexidade do projeto de utilidade é decidir o nível de visibilidade dos itens. Uma regra prática é que os métodos devem ser internos e as estruturas de dados públicas.
fonte
Minha empresa usa serviços da Web locais da intranet. Temos alguns serviços da web configurados como serviços internos da web comuns e, quando outro projeto precisa acessar um dos serviços, ele envia uma solicitação http com uma interface definida. Como está na intranet, hospedada no mesmo farm de servidores, essas solicitações são muito rápidas.
Obviamente, isso funciona apenas com aplicativos da Internet (e funciona apenas em milissegundos quando na mesma rede local), mas possui algumas vantagens muito boas.
fonte
Recentemente, criei este serviço: Snip2Code ( http://www.snip2code.com ).
É uma maneira interessante de compartilhar apenas seus snippets (não inteiramente de bibliotecas) com sua equipe. Ele quebra o ponto usual de criar bibliotecas comuns que devem ser referenciadas em outros projetos e, na minha opinião, essa é uma visão valiosa.
Além disso, existem muitos cenários em que o uso de uma biblioteca comum simplesmente não se aplica: vamos considerar, por exemplo, alguns padrões de design como Singleton, Strategy ou Observer. Você pode criar bibliotecas para suportar esses padrões, mas ainda não há 100% de cobertura.
A real necessidade é ter uma ferramenta para compartilhar práticas comuns entre a equipe. Tentei usar as essência do Github, mas estou preso à pesquisa delas (muito ruim) e ao fato de não poder compartilhá-las apenas entre minha equipe e não com outras ...
(Aviso: sou um dos fundadores do Snip2Code e estava - junto com meus co-fundadores - em sua mesma mentalidade há algum tempo: foi por isso que decidimos iniciar este projeto !!)
fonte