Pergunta

Eu tenho alguns manipulador de eventos em uma classe de fronteira que administra um mecanismo de persistência para uma dada operação genérica:

void MyBoundaryClass::MyEventHandler(...)
{
  //retrieve stuff from the UI
  //...
  //declare and initialize trasaction to persist
  SimpleTransaction myTransaction(.../*pass down stuff*/);
  //do some other checks
  //...
  //declare transaction persistor
  TransactionPersistor myPersistor(myTransaction, .../*pass down connection to DB and other stuff*/);
  //persist transaction
  try
  {
    myPersistor.Persist();
  }
  catch(...)
  {
    //handle errors
  }
}

Seria melhor ter algum tipo de TransactionManager para embrulhar SimpleTransaction e TransactionPErsistor objetos?

Existe alguma regra útil para entender se eu precisar de mais um nível de encapsulamento?

No momento, a regra de ouro que eu sigo é "se o método fica muito grande - fazer algo sobre isso". É difícil às vezes para encontrar o equilíbrio certo entre processual e orientada a objetos quando se lida com manipuladores de eventos de fronteira.

Qualquer opinião?

Felicidades

Foi útil?

Solução

Considerando que:

  • de encapsulamento é sobre a definição de um recipiente, e
  • design orientado a objetos é baseada no conceito de passagem de mensagens (invocação de métodos)

Eu diria que o API é uma boa indicação sobre a pertinência de um encapsulamento nova de alto nível (ou seja, a definição de um novo objeto)

Se os serviços (ou seja o API) oferecidos por este novo objeto são coerentes, e são mais expostos ao resto do programa, quando se reagruparam em um objeto especial, em seguida, por todos os meios, use um novo objeto.

Caso contrário, é provável um exagero.

Uma vez que você expor um público API através da criação de um novo objeto, a noção de test pode ser mais fácil de fazer dentro desse novo objeto ( e algumas outras simulada objetos), em vez de criar muitos objetos antigos, a fim de testar essas mesmas operações.

No seu caso, se você quiser testar a transação, você deve realmente MyEventHandler teste de MyBoundaryClass, a fim de recuperar dados a partir da interface do usuário.

Mas se você definir um TransactionManager, que lhe dá a oportunidade de diminuir o acoplamento de diferentes níveis de arquitetura (GUI vs. dados) presente em MyBoundaryClass, e para o gerenciamento de dados de exportação em uma classe dedicada. < br> Em seguida, você pode testar a persistência de dados no cenário de teste independente, com foco principalmente nos valores-limite, e falha de banco de dados, e condições não-nominais, e assim por diante.

cenário de teste pode ajudá-lo a refinar o coesão (grande ponto mencionado por Daok ) de seus objetos diferentes. Se os testes são simples e coerente, as chances são de que seus objetos têm um bem-definir limites de serviço.

Uma vez que pode-se argumentar que Acoplamento e Coesão são dois pilares de OO programação, a coesão de uma nova classe como TransactionManager pode ser avaliada em termos do conjunto de ações que irá realizar.

meios coesa que uma certa classe executa um conjunto de ações intimamente relacionadas. A falta de coesão, por outro lado, significa que uma classe está realizando várias tarefas não relacionadas. [...] o software de aplicação acabará por se tornar incontrolável como mais e mais comportamentos tornam-se dispersos e acabar em lugares errados.

Se você se reagrupar comportamentos de outra forma implementadas em vários lugares diferentes em sua TransactionManager, ele deve estar bem, desde que a sua API pública representam passos claros de que uma transação envolve e não "coisas sobre transação" como várias funções utilitárias. Um nome em si não é suficiente para julgar a coesão de uma classe. é necessária a combinação do nome e sua API pública.

Por exemplo, um aspecto interessante de um TransactionManager seria encapsular completamente a noção de Transação, que seria:

  • tornar-se praticamente desconhecida pelo resto f o sistema e reduziria o acoplamento entre as outras classes e 'Transaction'
  • reforçar a coesão do TransactionManager centrando sua API em torno de etapas de transação (como initTransaction (), persistTransaction (), ...), evitando qualquer getter ou setter para qualquer instância de transação.

Outras dicas

Elaborando sobre a sugestão de VonC, considere as seguintes diretrizes:

  • Se você espera para invocar as mesmas funções em outros lugares, da mesma forma, é razoável para encapsular-los em um novo objeto.

  • Se uma função (ou um objeto) fornece um conjunto de instalações que são úteis individualmente, é razoável refatorar em componentes menores.

ponto de VonC sobre o API é um excelente teste decisivo:. Criar eficaz Interfaces e objetos , muitas vezes tornam-se aparentes

O nível de encapsulamento deve ser diretamente ligada à coesão do seu objeto. Seu objeto deve fazer uma única tarefa ou deve ser dividido em múltiplas classes e encapsular todos os seus comportamentos e propriedades.

Uma regra de ouro é quando é hora de testar o seu objeto. Se você estiver fazendo o teste da unidade e você percebe que você está testando coisa diferente múltipla (não na mesma ação de área) do que você pode tentar dividi-lo.

Para você caso , gostaria de encapsular com a sua ideia de "TransactionManager". Desta forma, o "TransactionManager" vai lidar com como funciona a transação e não "MyBoundaryClass".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top