Corri para algum código (c #, se for o caso) que possui classes que têm o mesmo nome, mas diferem em seus namespaces. Todos eles tendem a representar a mesma coisa lógica, mas geralmente são "visões" diferentes do mesmo objeto. Os diferentes namespaces às vezes fazem parte da mesma solução e até da mesma dll.
Tenho meus pensamentos, mas não consegui encontrar nada definitivo sobre essa prática para ser considerado um uso inteligente das ferramentas disponíveis ou um padrão a ser evitado.
Essa pergunta sobre a nomeação de smurfs toca nisso, mas de outra direção. Desambiguar os nomes provavelmente exigiria um prefixo arbitrário e difundido, que essa pergunta queria eliminar.
Quais são as diretrizes em torno dessa prática?
FooAdapter
,FooViewer
,FooCalculator
, etc., mas certamente não chamado a mesma coisa. Porém, sem mais informações sobre as classes específicas sobre as quais você está falando, é difícil fornecer uma resposta.Employee
como o exemplo. Há um funcionário que é para outros funcionários, um para RH, outro para exposição externa. Todos eles são chamados de "funcionários" e todos têm variedades de auxiliares (EmployeeRepository, EmployeeView, etc.). Todos eles estão na mesma DLL e, embora compartilhem algumas propriedades comuns (nome, título), todos diferem (número de telefone, salário).Employee
várias vezes, parece que você precisa de um modelo com a união de todos os atributos e inclui umtype
oudepartment
atributo. Caso contrário, haverá duplicação desnecessária de código.Respostas:
Tentarei dar uma resposta contra esse uso, depois de ter visto e trabalhado nisso em um dos meus projetos também.
Legibilidade do código
Antes de tudo, considere que a legibilidade do código é importante e essa prática é contrária a isso. Alguém lê um pedaço de código e digamos que ele tem uma função
doSomething(Employee e)
. Isso não é mais legível, porque, devido às 10Employee
classes diferentes existentes em pacotes diferentes, você precisará primeiro recorrer à declaração de importação para descobrir qual é realmente a sua entrada.Essa é, no entanto, uma visão de alto nível e, geralmente, temos conflitos de nomes aparentemente aleatórios, com os quais ninguém se importa ou que encontra, porque o significado pode ser derivado do código restante e do pacote em que você está. Portanto, pode-se argumentar que, localmente, não há problema, porque é claro que, se você vir
Employee
dentro de umhr
pacote, precisará saber que estamos falando de uma visão de RH do funcionário.As coisas se desfazem assim que você deixa esses pacotes. Depois de trabalhar em um módulo / pacote / etc diferente e precisar trabalhar com um funcionário, você já estará sacrificando a legibilidade se não qualificar totalmente seu tipo. Além disso, ter 10
Employee
classes diferentes significa que o preenchimento automático do IDE não funcionará mais e você deverá escolher manualmente o tipo de funcionário.Duplicação de código
Devido à natureza de cada uma dessas classes estar relacionada entre si, seu código provavelmente se deteriorará devido a muita duplicação. Na maioria dos casos, você terá algo como o nome de um funcionário ou algum número de identificação, que cada uma das classes precisa implementar. Embora cada classe inclua seu próprio tipo de visão, se elas não compartilharem os dados subjacentes dos funcionários, você terá uma enorme quantidade de códigos inúteis, mas caros.
Complexidade do código
O que pode ser tão complexo que você pode perguntar? Afinal, cada uma das classes pode mantê-lo tão simples quanto desejar. O que realmente se torna um problema é como você propaga as mudanças. Em um software razoavelmente rico em recursos, você pode alterar os dados dos funcionários - e deseja refletir isso em qualquer lugar. Digamos que uma senhora acabou de se casar e você precise renomeá-la de
X
paraY
devido a isso. Difícil o suficiente para fazer isso em todos os lugares, mas ainda mais quando você tem todas essas classes distintas. Dependendo de suas outras opções de design, isso pode facilmente significar que cada uma das classes precisa implementar seu próprio tipo de ouvinte ou ser notificado sobre alterações - o que basicamente se traduz em um fator aplicado ao número de classes com as quais você deve lidar. . E mais duplicação de código, é claro, e menos legibilidade de código. Fatores como esse podem ser ignorados na análise de complexidade, mas certamente são irritantes quando aplicados ao tamanho da sua base de código.Comunicação de código
Além dos problemas acima com a complexidade do código, que também estão relacionados às opções de design, você também reduz a clareza de design de nível superior e perde a capacidade de se comunicar adequadamente com especialistas em domínio. Ao discutir arquitetura, projetos ou requisitos, você não é mais livre para fazer declarações simples como
given an employee, you can do ...
. Um desenvolvedor não saberá mais o queemployee
realmente significa nesse momento. Embora um especialista em domínio saiba disso, é claro. Todos nós fazemos. tipo de. Mas, em termos de software, não é mais tão fácil se comunicar.Como se livrar do problema
Depois de tomar conhecimento disso e se sua equipe concordar que é um problema grande o suficiente para ser resolvido, você terá que encontrar uma maneira de lidar com isso. Normalmente, você não pode pedir ao seu gerente que dê uma semana inteira à equipe para que ele possa retirar o lixo. Portanto, em essência, você terá que encontrar uma maneira de eliminar parcialmente essas classes, uma de cada vez. A parte mais importante disso é decidir - com toda a equipe - o que
Employee
realmente é. Você não integrar todos os atributos individuais em um deus-empregado. Pense mais em um funcionário principal e, mais importante, decida onde essaEmployee
classe residirá.Se você faz revisões de código, é particularmente fácil garantir que o problema não melhore ainda mais, ou seja, interrompa todo mundo no caminho certo quando quiser adicionar outro
Employee
novamente. Também verifique se os novos subsistemas aderem ao acordadoEmployee
e não têm permissão para acessar as versões antigas.Dependendo da sua linguagem de programação, convém marcar as classes que eventualmente serão eliminadas com algo como
@Deprecated
para ajudar sua equipe a perceber imediatamente que eles estão trabalhando com algo que precisará ser alterado.Quanto a se livrar das classes de funcionários desatualizadas, você pode decidir, para cada caso individual, como é melhor eliminá-las ou simplesmente concordar com um padrão comum. Você pode afixar o nome da classe e envolvê-lo em torno do funcionário real, pode usar padrões (decorador ou adaptador), ou, ou ou.
Para resumir uma longa história: Essa "prática" é tecnicamente sólida, mas está cheia de custos ocultos que só ocorrerão mais adiante. Embora você não consiga se livrar imediatamente do problema, você pode começar imediatamente contendo os efeitos nocivos.
fonte
O Scala Collection Framework é um bom exemplo disso. Existem coleções mutáveis e imutáveis, bem como coleções seriais e paralelas (e no futuro talvez distribuídas também). Portanto, existem, por exemplo, quatro
Map
características:mais três
ParMap
s:Ainda mais interessante:
Então,
ParMap
estendeParMap
estendeMap
eMap
estendeMap
estendeMap
.Mas, vamos enfrentá-lo: o que mais se você chamá-los? Isso faz todo o sentido. É para isso que servem os namespaces!
fonte
Essa é uma pergunta realmente interessante, onde as duas respostas essencialmente opostas estão corretas. Aqui está um exemplo real dessa discussão que estamos tendo em um projeto meu.
Eu acho que existem duas considerações muito importantes até agora que poderiam fazer com que você seguisse uma direção ou outra, baseando-se nas duas respostas de @Jorg e @Frank:
hr.Employee
mas ao mesmo tempo precisa acessar as permissõessecurity.Employee
, isso será muito rápido e irritante.Map
classes implementam a mesma interface ou são subclasses uma da outra. Nesse caso, a ambiguidade ou "confusão" pode ser considerada uma coisa boa, porque o usuário pode tratar corretamente todas as implementações da classe ou interface da mesma maneira ... qual é o ponto das interfaces e subclasses.fonte