Em nossa aplicação Delphi 2007, estamos usando muitas das seguintes construções
FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));
O FindOwnerClass percorre a hierarquia do proprietário do componente atual para cima para encontrar uma classe específica (no exemplo TdmBasicData). O objeto resultante é armazenado na variável de campo FdmBasic. Usamos isso principalmente para repassar os módulos de dados.
Exemplo: ao gerar um relatório, os dados resultantes são compactados e armazenados em um campo Blob de uma tabela acessada por meio de um módulo de dados TdmReportBaseData. Em um módulo separado do nosso aplicativo, há funcionalidade para mostrar os dados do relatório em um formulário Paginado usando o ReportBuilder. O código principal deste módulo (TdmRBReport) usa uma classe TRBTempdatabase para converter os dados compactados do blob em diferentes tabelas que são utilizáveis no Reportbuilder runtime reportdesigner. O TdmRBReport tem acesso ao TdmReportBaseData para todos os tipos de dados relacionados ao relatório (tipo de relatório, configurações de cálculos de relatório etc.). TRBTempDatabase é construído em TdmRBReport, mas precisa ter acesso a TdmReportBasedata. Portanto, isso agora é feito usando a construção acima:
constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }
Meu sentimento é que isso significa que o TRBTempDatabase conhece muito de seu proprietário, e eu queria saber se isso é algum tipo de cheiro de código ou Anti-padrão.
Quais são seus pensamentos sobre isso? Isso é um cheiro de código? Se sim, qual é a melhor maneira?
fonte
Respostas:
Parece um padrão de localizador de serviço que foi descrito pela primeira vez por Martin Fowler (que foi identificado como um antipadrão comum).
A Injeção de Dependência baseada na construção é preferida a um Localizador de Serviço, pois promove a visibilidade dos parâmetros requeridos e promove Testes de Unidade mais simples.
Também notavelmente também quebra a Lei de Deméter
A melhor maneira
Efetivamente, a melhor maneira é remover a chamada do localizador de serviço dentro da classe e passar o proprietário correto como um parâmetro dentro de seu construtor. Mesmo que isso signifique que você tem uma classe de serviço que executa uma consulta de proprietário e a passa ao construtor da classe
fonte
As a simple example, when one wants to walk a dog, it would be folly to command the dog's legs to walk directly; instead one commands the dog and lets it take care of its own legs.
Uma das dificuldades em fazer com que os objetos filhos saibam demais sobre o pai é que você acaba implementando padrões que podem (e geralmente o fazem) ficar muito acoplados, o que cria grandes dores de cabeça por dependência e muitas vezes depois se torna muito difícil modificar e manter com segurança mais tarde.
Dependendo de quão profundamente suas duas classes estão conectadas, parece um pouco com a descrição de Fowler do código de inveja de recursos ou odores de código de intimidade inadequada.
Parece haver a necessidade de carregar ou ler uma classe com dados; nesse caso, você pode usar vários padrões alternativos para quebrar a dependência entre a criança e sua cadeia de pais, e parece que você precisa delegar a tarefa de acessar sua classe de dados em vez de tornar a classe do acessador de dados responsável por fazer tudo sozinho.
fonte