Problema
Estou trabalhando em um projeto Python cuja classe principal é um pouco " God Object ". Não são tão friggin muitos atributos e métodos!
Eu quero refatorar a classe.
Tão longe…
Para o primeiro passo, quero fazer algo relativamente simples; mas quando tentei a abordagem mais direta, ela quebrou alguns testes e exemplos existentes.
Basicamente, a classe tem uma lista loooonga de atributos - mas eu posso examiná-los claramente e pensar: "Esses 5 atributos estão relacionados ... Esses 8 também estão relacionados ... e depois há o resto".
getattr
Basicamente, eu só queria agrupar os atributos relacionados em uma classe auxiliar do tipo ditado. Tive a sensação de __getattr__
que seria ideal para o trabalho. Então, mudei os atributos para uma classe separada e, com certeza, __getattr__
funcionou perfeitamente bem sua mágica…
No primeiro .
Mas então tentei executar um dos exemplos. A subclasse de exemplo tenta definir um desses atributos diretamente (no nível da classe ). Mas como o atributo não estava mais "fisicamente localizado" na classe pai, recebi um erro dizendo que o atributo não existia.
@propriedade
Eu então li sobre o @property
decorador. Mas também li que isso cria problemas para as subclasses que desejam fazer self.x = blah
quando x
é uma propriedade da classe pai.
Desejado
- Faça com que todo o código do cliente continue trabalhando
self.whatever
, mesmo que awhatever
propriedade do pai não esteja "fisicamente localizada" na própria classe (ou instância). - Agrupe atributos relacionados em contêineres semelhantes a dict.
- Reduza o barulho extremo do código na classe principal.
Por exemplo, eu não quero simplesmente mudar isso:
larry = 2
curly = 'abcd'
moe = self.doh()
Nisso:
larry = something_else('larry')
curly = something_else('curly')
moe = yet_another_thing.moe()
... porque ainda é barulhento. Embora isso faça com que um atributo simplesmente seja algo que possa gerenciar os dados, o original tinha 3 variáveis e a versão aprimorada ainda possui 3 variáveis.
No entanto, eu ficaria bem com algo assim:
stooges = Stooges()
E se uma pesquisa self.larry
falhar, algo verificará stooges
se larry
há. (Mas também deve funcionar se uma subclasse tentar fazer isso larry = 'blah'
no nível da classe.)
Sumário
- Deseja substituir grupos de atributos relacionados em uma classe pai por um único atributo que armazena todos os dados em outro local
- Deseja trabalhar com o código do cliente existente que usa (por exemplo)
larry = 'blah'
no nível da classe - Deseja continuar permitindo que as subclasses estendam, substituam e modifiquem esses atributos refatorados sem saber que algo mudou
Isso é possível? Ou estou latindo na árvore errada?