Bueno, pues... #asamos_el_código!
Un RPG en consola es la base. El código cumple su función, pero está escrito de tal manera que cualquier intento de escalarlo causará DOLOOOOOOR. Analicemos los problemas más importantes 👇
1️⃣ Herencia Ctrl+C, Ctrl+V
Miremos la jerarquía de armaduras:
class Armor(Item):
def __init__(self, name, category, strength=None, value_strength=None...): # y otros 100500 argumentos
super().__init__(name, category)
# ...
class Helmet(Armor):
def __init__(self, ...):
super().__init__(...)
class Chestplate(Armor):
# Copia de Helmet
class Greaves(Armor):
# Copia de ChestplateTodas estas clases (
Helmet, Chestplate, Greaves, Boots) son absolutamente idénticas. No añaden nuevos atributos ni nuevo comportamiento. No hacen nada más que llamar a super().__init__. La POO no se creó para describir cada objeto físico del mundo con una clase separada. Si las entidades solo se diferencian por el nombre de la categoría, debería ser una sola clase
Armor con un atributo slot_type (idealmente mediante Enum). 2️⃣ Constructor Frankenstein
Miren cómo se crea un objeto:
crown = Helmet('Шлем Господства', 'Шлем', 'Сила', 5, 'Ловкость', 7, 'Интеллект', 3)Nunca codifiquen los nombres de los atributos en la firma del método. Usen diccionarios.
En lugar de esa sábana de parámetros, el objeto debería recibir
stats={'strength': 5, 'agility': 7, 'intellect': 3}.3️⃣ Incesto de clases
La clase
Characteristic recibe un hero y luego hace esto:for item in self._hero.slots_equipment.values():
if item:
if hasattr(item, 'value_strength') and item.value_strength:
self.attributes['strength'] += item.value_strengthEsto se llama "Acoplamiento fuerte" (Tight Coupling). La clase de características mete sus manos sucias en el inventario del héroe, verifica si hay objetos y luego, mediante
hasattr (que de por sí es un parche en el 99% de los casos), intenta extraer sus estadísticas. El héroe debería consultar su propio equipamiento y pasar los modificadores finales al sistema de características. Ahora es la cola la que mueve al perro.
4️⃣ Uso de Excepciones para lógica
En el método
equip_armor vemos esto:try:
if key not in self.slots_equipment:
print('Нет такого слота.')
# ... lógica ...
except KeyError:
print(f'Предмет не найден')Primero, capturar una excepción genérica
KeyError enmascarará errores reales en el código (por ejemplo, un error tipográfico en un diccionario dentro del try). Segundo, las excepciones son para situaciones excepcionales, no para verificar si un objeto está en el inventario. Para eso está el método de diccionario .get().En resumen, para empezar, en lugar de 10 clases de armadura inútiles y constructores monstruosos, se podría hacer al menos esto:
from dataclasses import dataclass
from enum import Enum
class EquipmentSlot(Enum):
HEAD = "Casco"
CHEST = "Peto"
WEAPON = "Arma"
@dataclass
class Equipment:
name: str
slot: EquipmentSlot
stats_bonus: dict[str, int]
# Creación de objeto:
crown = Equipment(
name='Casco del Dominio',
slot=EquipmentSlot.HEAD,
stats_bonus={'strength': 5, 'agility': 7, 'intellect': 3}
)Y ya está. Sin duplicación de código, protección contra errores tipográficos en los slots mediante Enum, y un sistema de estadísticas extensible al que mañana se le puede añadir "Suerte" sin reescribir
__init__ en una docena de clases.La POO no es cuando tienes una clase separada para cada entidad del universo. La POO trata sobre la gestión de la complejidad y el estado.
Pero para un mes de aprendizaje, esta es una etapa de evolución completamente normal.
📖 Lecturas:
- Cuando una clase en Python es mala: 6 casos en los que te complicas la vida
- Principios SOLID en POO con ejemplos en Python
Comentários
0Ainda não há comentários.