Como evitar nomes gerais para classes abstratas?

10

Em geral, é bom evitar palavras como "manipular" ou "processar" como parte de nomes de rotina e nomes de classe, a menos que você esteja lidando com (por exemplo) identificadores de arquivo ou (por exemplo) processos unix. No entanto, as aulas abstratas geralmente não sabem o que farão com algo além de, digamos, processá-lo. Na minha situação atual, tenho um "EmailProcessor" que efetua login na caixa de entrada do usuário e processa mensagens a partir dela. Não está realmente claro para mim como atribuir um nome mais preciso a esse nome, embora eu tenha notado a seguinte questão de estilo:

  • melhor tratar as classes derivadas como clientes e nomear a classe base pela parte da funcionalidade que implementa? Dá mais significado, mas violará o is-a. Por exemplo, EmailAcquirer seria um nome razoável, pois está sendo adquirido para a classe derivada, mas a classe derivada não será adquirida para ninguém.
  • Ou apenas um nome realmente vago, pois quem sabe o que as classes derivadas farão. No entanto, "Processador" ainda é muito geral, pois está realizando muitas operações relevantes, como efetuar login e usar o IMAP.

Alguma maneira de sair desse dilema?

O problema é mais evidente para métodos abstratos, nos quais você não pode realmente responder à pergunta "o que isso faz?" porque a resposta é simplesmente "o que o cliente quiser".

djechlin
fonte
Você tem uma fonte (e algum contexto) para essa afirmação "em geral"? Além disso, uma regra de nomenclatura adicional para a lista - não perca tempo procurando um nome perfeito que provavelmente não existe. Em caso de dúvida, dê o melhor nome possível, adicione uma descrição mais longa como um comentário, onde for definido, se necessário, mas você poderá refatorar mais tarde se alguém não gostar da sua escolha ou se o nome perfeito lhe ocorrer repentinamente quando você ' está fazendo outra coisa.
Steve314
3
@ Steve314 - sim, Steve McConnell, Code Complete, 1º ed., Capítulo 4 ou 5 sobre rotinas. Discussão extensa sobre nomeação nesses capítulos, concluindo essencialmente se você não tem um bom nome, provavelmente não tem uma boa função.
djechlin
não encontrar um bom nome pode parecer um sinal ruim, mas na IMO você deve saber se a função está incorreta com base na própria função. A refatoração apenas porque o idioma inglês não foi projetado de maneira personalizada para o seu projeto é um pouco tonta. Não, não é um problema do dia a dia, mas você já decidiu que tinha um problema.
Steve314
11
@ Steve314 A programação é inteiramente sobre gerenciamento de complexidade, e se seu cérebro não conseguir encontrar uma palavra para alguma coisa, há uma boa chance de que não seja capaz de gerenciar a complexidade quando precisar fazer coisas como usá-lo em frases maiores ou como parte de sistemas maiores. Na verdade, não é uma afirmação ousada dizer que a incapacidade de encontrar um bom nome é uma grande causa de pausa para preocupação. Mas isso é discutido extensivamente em McConnell, eu recomendaria a leitura desses dois capítulos pelo menos, embora valha a pena ler o livro inteiro de capa a capa.
djechlin
as reivindicações no código completo não devem necessariamente ser confiáveis. Estou ciente da reputação dos livros, mas também estou ciente disso . Além disso, venho gerenciando perfeitamente a complexidade há muito tempo - erros acontecem, é claro, mas quando as coisas dão errado, às vezes o problema é uma função tão simples que obviamente não pode estar errada, mas é assim mesmo .
precisa saber é o seguinte

Respostas:

10

O problema não é o nome, mas você está colocando muito em uma classe.

Na sua classe de exemplo, algumas partes são muito concretas (como as mensagens serão obtidas). Outras partes são muito abstratas (o que você fará com os e-mails).

Melhor fazer isso com classes separadas, do que com herança.

Eu sugiro:

  • um MessageIterator abstrato, subclassificado por um POPMailBoxDownloader

  • outra classe que possui um POPMailBoxDownloader e faz algo com as mensagens.

Kris Van Bael
fonte
Isso parece exatamente certo. Parece que se você estiver nomeando algo "processEvent" ou uma classe "MessageProcessor", há uma boa chance de que você possa ter projetado sobre composição em vez de derivação. Nesse caso, é uma troca, pois, como mantenedores, a flexibilidade pode ser útil, mas um cliente ficaria irritado ao se perguntar exatamente o que cada função faz (mais do que o mantenedor).
djechlin
6

Se não conseguir encontrar um bom nome para uma classe, escrevo uma documentação de código embutido para a classe. Ele descreve o objetivo da classe em uma fragrância. Normalmente, posso derivar um bom nome para a classe a partir desta descrição. Isso também é útil para classes abstratas.

Se a descrição da classe for "Efetua login na caixa de entrada de um usuário e processa mensagens dela", eu sugeriria "InboxProcessor" como um nome de classe. Se uma classe derivada tiver "Efetua login na caixa de entrada de um usuário e move o email de spam para uma pasta de spam" como descrição, eu escolheria "InboxSpamMover" como nome.

Não vejo problema ao usar nomes genéricos como "processador", se refletir o objetivo genérico de uma classe abstrata.

Se você tiver problemas para descrever o propósito de uma classe em uma ou duas essências, poderá ter um problema de design. Talvez a turma esteja fazendo muito e viole o Princípio da Responsabilidade Única . Isso também se aplica a classes abstratas.

Theo Lenndorff
fonte
2

Parafraseando Frank Zappa, é o que é e deve ser nomeado dessa maneira. Seu exemplo não se aprofunda o suficiente no tipo de processamento. É um EmailToTroubleTicketProcessor, um EmailGrammarCorrectorou um EmailSpamDetector?

O problema é mais evidente para métodos abstratos, nos quais você não pode realmente responder à pergunta "o que isso faz?" porque a resposta é simplesmente "o que o cliente quiser".

Isso não é exatamente verdade; a pergunta que você não pode responder por algo abstrato é " como ela faz o que faz?" porque isso é específico da implementação. Se uma EmailSenderclasse tem um DeliveryStatus deliver(Email e)método, há um contrato implícito de que uma implementação receberá um email, tente entregá-lo e retornar algum status sobre como foi. Você não se importa se ele se conecta a um servidor SMTP ou o imprime para ser amarrado a um pombo-correio, desde que a implementação faça o que foi prometido. Os resumos apenas quantificam essa promessa para que uma implementação possa dizer "sim, eu faço isso".

Blrfl
fonte
E quando a função final é, em algum sentido, terminal, então a classe abstrata está dizendo "e isto aqui, faça o que você quiser com ela?" por exemplo, o método não tem acesso ao estado, tipo de retorno nulo, no-throw.
djechlin
Ainda é a mesma coisa. Mesmo que seu método seja void doWhatYouDoWith(Email e), você ainda pode chamar a classe an EmailDisposer, que é específica o suficiente para dizer o que faz, mas geral o suficiente para determinar como está a implementação. Embora eu ache que o @KrisVanBael acertou em cheio: se você recorreu a algo tão ambíguo, pode haver muito sob o mesmo teto.
Blrfl
0

Pense por que é ruim usar essas palavras. Eles são descritivos? Que palavras existem para descrever as aulas? EmailBaseClass? Isso poderia ser mais descritivo do que dizer EmailManager ou algo semelhante? A chave é ter uma visão sobre a classe em questão, para encontrar verbos ou substantivos adequados. Trate seu código como se fosse poesia.

zxcdw
fonte
"EmailBaseClass" seria como nomear int age"ageInteger", ainda pior, já que eu esperaria derivar emails em texto sem formatação, emails MIME etc. Não há necessidade de descrever o que é precedido pela palavra abstractem primeiro lugar (este é Java). Você tem algum insight específico para a parte base desta classe? E mais perspicácia ainda não resolve o problema de nomear algo que vai atravessar um relacionamento é, eu posso ter algo muito vago ou muito geral, não vejo uma saída disso a menos que eu tenha mais insights para ter mais insights.
djechlin
@ Djechlin - há casos raros em que ageIntegerou algo parecido é realmente apropriado. A notação húngara é uma versão abreviada de um contexto em que aconteceu muito. Certamente, há momentos em que você pode precisar de algo como ageNumerice ageStringno mesmo escopo, com uma indicação do tipo no nome como a maneira mais fácil e clara de desambiguar.
Steve314
@djechlin Pessoalmente, acho mais fácil trabalhar com código que eu posso espiar para entender. Ou seja, os nomes me dizem com o que estou trabalhando. Não é necessário saber se systemControllerhá uma classe base abstrata ou uma folha em uma enorme hierarquia. É claro que isso pode ser remediado com o IDE (como eu acho que é o caso da maioria dos desenvolvimentos em Java?), Que pode informar imediatamente o usuário sobre o conteúdo e a estrutura da classe, para que nomes realmente perspicazes não possam ser justificados de maneira semelhante.
Zxcdw 6/09/12