Encontrei no GitHub o projeto PythonPlantsVsZombies. É um clone do lendário "Plants vs. Zombies" em Pygame: com animações, diferentes tipos de zumbis e níveis via JSON. Mas quando você olha "debaixo do capô" — começa a sentir pena dos zumbis. Pelo menos eles não precisam dar manutenção nesse código.

Vamos dissecar essa obra-prima da engenharia.

1️⃣ Inferno de if-elif ou "Fábrica de muletas"
No arquivo source/state/level.py vive o método addPlant. Quando você planta uma planta em uma célula, o motor inicia um interrogatório com 19 ramos elif.

"Você é um girassol? Não? E talvez um atirador de ervilhas? Também não? Então, talvez uma cereja?"


if self.plant_name == c.SUNFLOWER:
new_plant = plant.SunFlower(x, y, self.sun_group)
elif self.plant_name == c.PEASHOOTER:
new_plant = plant.PeaShooter(x, y, self.bullet_groups[map_y])
# ... e mais 17 vezes


Quer adicionar um novo tipo de girassol? Vá para o meio do arquivo e escreva mais um:
elif self.plant_name == c.SUNSHROOM:
new_plant = plant.SunShroom(x, y, self.sun_group)


Isso é um antipadrão clássico. No mundo normal, usamos um registro de classes ou mapeamento. Um dicionário — e essa vergonha se transforma em duas linhas elegantes.

2️⃣ Sincronização de listas — caminho para a esquizofrenia
Em source/component/menubar.py, os dados das plantas (nomes, custo, cooldown) estão espalhados por quatro listas independentes.
Todas devem ter estritamente o mesmo comprimento e estrita ordem.
Errou por um índice em plant_sun_list? Parabéns, agora seu atirador de ervilhas custa como uma cereja, e a cereja é grátis.

Temos dataclasses, dicionários, OOP, afinal. Agrupe dados relacionados em objetos, senão a depuração vira um inferno.

3️⃣ Efeitos colaterais globais.
Em source/tool.py, a inicialização do Pygame e criação da janela (SCREEN) ocorrem diretamente no nível do módulo.
Qual o problema: Você não pode simplesmente importar uma constante ou função auxiliar deste arquivo para testes sem inicializar todo o núcleo gráfico. Isso mata a possibilidade de testes unitários. A lógica deve ser separada do "hardware".

4️⃣ Cérebro inteligente com objetos burros
Em vez de usar polimorfismo (onde cada planta sabe como atacar), a classe principal Level verifica manualmente os nomes das strings: if plant.name == c.THREEPEASHOOTER, e decide para onde atirar. Isso torna as classes de plantas meras decorações com imagens, e a lógica do jogo um monolito intragável.

Veredito:
O projeto é legal como demo e forma de brincar com Pygame. Mas se você chegar com essa abordagem arquitetural em um projeto sério — será devorado mais rápido do que zumbis comem uma nogueira na primeira linha.

🎓 O que aprendemos:
1. Não faça cadeias gigantes de if-else onde o polimorfismo funciona.
2. Agrupe dados relacionados em objetos ou dicionários.
3. Se no seu código há a frase "o índice nesta lista corresponde ao índice naquela lista" — delete tudo e reescreva.
4. Recursos (gráficos/som) devem ser carregados preguiçosamente (Lazy Loading), não "tudo de uma vez" ao importar o módulo.

#fritando_codigo