É apropriado que uma classe seja apenas uma coleção de informações sem lógica?

8

Digamos que eu tenha uma classe Personque tem as variáveis de instância age, weighte height, e outra classe Fruitque tem as variáveis de instância sugarContente texture. A Personclasse não possui métodos, exceto setters e getters, enquanto a Fruitclasse possui setters e getters e métodos lógicos, como calculateSweetness. A Fruitclasse é o tipo de classe que é a melhor prática que a Personclasse? O que quero dizer com isso é que a Personclasse parece que não tem muito objetivo; existe apenas para organizar dados, enquanto a Fruitclasse organiza dados e, na verdade, contém métodos para lógica.

pasawaya
fonte
Então, uma pessoa tem setters para altura, peso e / ou altura, certo? Os setters seriam inúteis, a menos que haja lógica que manipule esses atributos em algum lugar. Essa lógica está em uma classe correta?
Vem de
@ COMEFROM: você está certo, essa é a pergunta a ser feita aqui. No entanto, em sistemas de informação, não é incomum que o objetivo de alguns atributos seja que eles sejam armazenados, mostrados e relatados nesse sistema, sem lógica real (processos de negócios que realmente usam esses atributos podem existir fora do sistema de informação).
Doc Brown
@ Doc Brown: Eu sei e concordo. Não vejo nada de errado com classes sem lógica, mas ter levantadores nessa classe é um tanto suspeito. Eu verificaria onde esses setters são necessários. Como você escreveu: adicione funcionalidades a uma classe quando necessário. Um setter é uma funcionalidade.
Vem de

Respostas:

8

Se sua pessoa não está realmente fazendo nada, não há necessidade de executar nenhuma ação. É possível ter classes que apenas coletam dados e, em seguida, haverá classes que operam com esses dados. No seu caso, pode ser possível que você não tenha nenhuma ação em uma única pessoa, mas pode haver ação em um grupo de pessoas, como CalculateAverageHeight (). Nesse caso, faz sentido ter apenas Pessoa sem ação e, em seguida, ter outra classe (pode ser amiga) que trabalha nisso.

Manoj R
fonte
1
Eu não diria que é "comum" dividir seus dados e lógica em diferentes classes em um sistema OOP projetado corretamente. Para o seu exemplo, eu esperaria CalculateAverageHeight()ser um método estático no Personqual leva uma coleção de Personobjetos. Dessa forma, mesmo que CalculateAverageHeight()não seja aplicável a uma instância individual Person, você ainda a mantém próxima dos dados em que opera.
TMN
1
@TMN - Desculpe pela palavra comum. Não é comum, mas possível. Não concordo que o cálculo da altura média esteja intimamente relacionado à classe da pessoa. Considere outra função HighDensityArea (), que descobre qual é a área em que a maioria da população reside. Esta função precisa apenas do campo de endereço da pessoa. Não há necessidade de vincular isso de perto com a classe Person.
precisa
4

É difícil adotar uma regra dizendo que todas as classes devem ter alguma lógica. Em geral, classes sem nenhuma lógica são consideradas AnemicDomainModel .

Mesmo assim, é melhor organizar os dados se as informações relacionadas estiverem aumentando. Por exemplo, neste caso, você ainda pode precisar de uma coleção de Pessoa do que muitas coleções não relacionadas.

Jayan
fonte
3
Eu não acho que isso (AnemicDomainModel) seja sempre verdadeiro apenas porque você não tem lógica. Na verdade, acho que muitos tipos básicos de entidades são apenas isso: uma coleção de informações relacionadas a um objeto em particular, mas sem nenhuma lógica específica conectada a ele. Uma Pessoa apenas ... é, mas seria difícil argumentar que você não deveria ter uma classe para representar uma Pessoa.
Peter Rowell
@ Peter Rowell: A Entidade (bean) do J2EE recebe menção especial no artigo.
Jayan
1
Você também pode ter implementado o padrão de design de comando
Eoin
Uma boa definição de trabalho do Anemic Domain Model é um domínio em que regras de negócios devem existir para impor a integridade dos dados em um objeto, mas essas regras não são encapsuladas no mesmo objeto . Se um objeto não precisar de lógica para manter um estado internamente consistente, como um padrão Money, não deveria ter dito essa lógica. No entanto, se uma Fatura tiver uma propriedade Subtotal de dados que sempre deve ser a soma dos Custos Estendidos de seus itens de linha (cada um deles, por sua vez, Preço Unitário * Quantidade), essas propriedades deverão ser calculadas e não diretamente ajustáveis.
Keiths
Se você tem muitas classes assim, você tem um problema. No entanto, às vezes você simplesmente deseja organizar alguns itens de dados, mas não há métodos que não façam mais sentido em outro lugar.
Loren Pechtel
3

O DataTransferObject é um bom exemplo de uma classe que não tem lógica, apenas dados. Esse é o seu propósito; é explicitamente uma exceção à regra geral que todas as classes implementem a lógica de negócios que afeta seu estado interno. Ter uma classe cujo estado interno é alterado pela lógica externa geralmente é um cheiro de design. Nem sempre está errado, mas quase sempre é algo que você deve considerar refatorar.

TMN
fonte
3

Inverta a questão, olhe para o outro lado. Se você tem uma coleção de informações que obviamente pertencem uma à outra, você deve mantê-las separadas apenas porque não existem métodos que você possa adicionar a essa classe? Você deve ser forçado a inventar métodos arbitrários apenas para justificar a classe?

MSalters
fonte
2

Os modelos não têm fim para si mesmos - você deve adicionar funcionalidades a uma classe quando realmente precisar delas em seu programa, sem adivinhar que provavelmente precisará delas no futuro. Portanto, é natural que, em um determinado momento, você tenha classes sem métodos "reais" e, posteriormente, quando você determinar que faz sentido adicionar métodos à classe, faça exatamente isso. A qualidade de um modelo não é medida por "eu tenho métodos aqui e não existem métodos" - a qualidade é medida por "eu tenho todos os métodos que meu aplicativo realmente precisa lá".

Por exemplo, quando seu aplicativo na versão 1.0 precisar de algo como calculateSweetnessa Fruit, mas não executar operações, Personexceto obter e definir os atributos, seu modelo deverá refletir exatamente isso, não tendo nenhuma lógica na classe Person. Na versão 2.0, pode fazer sentido adicionar alguma lógica a um Persontambém; portanto, quando você estiver nesse ponto, adicione os métodos em questão.

Doc Brown
fonte
1

Eu acho que isso depende do idioma e de como você está usando o idioma.

No caso trivial, algumas linguagens insistem em que tudo esteja em uma classe; portanto, por exemplo, coleções de constantes precisam entrar em uma classe que então pode ou não ter lógica, em outras linguagens elas podem acabar em um espaço para nome.

Em linguagens multiparadigmas, também pode depender de qual paradigma você deseja que seu design adira. Tomando emprestado o exemplo de CalculateAverageHeight (), como provavelmente deve residir em uma classe PersonCollection, no entanto, isso pressupõe uma solução OOP. em um design mais funcional, você pode usar uma função de ordem superior com uma coleção genérica, por exemplo, em C #

List<Person> personList = GetListOfPeople();
personlist.Average(p => p.Height);

e a lógica não está no PersonCollection ou mesmo estaticamente no Person. De fato, funções de ordem superior e tipos de dados genéricos em geral significam que é mais provável que você acabe com objetos que são apenas pacotes de dados, pois a lógica está operando em um nível de abstração mais alto que o seu modelo de dados específico .

jk.
fonte
1

Parece que você está falando sobre um POD (dados antigos simples). Linguagens diferentes podem representá-las de diferentes maneiras - pode ser uma classe com membros públicos, por exemplo, ou uma estrutura com apenas membros públicos em C ++.

A organização de dados é uma razão perfeitamente válida para a existência de uma classe - geralmente pode tornar o código mais limpo e fácil de ler. std::pairno STL do C ++, é um bom exemplo de uma estrutura que existe apenas para organizar dados - simplesmente uma estrutura que contém dois valores de qualquer tipo chamado firste second. Provavelmente uma das classes mais úteis em todo o STL (na minha opinião de qualquer maneira :))

Bok McDonagh
fonte