Tengo una Character
clase de línea 2500 que:
- Rastrea el estado interno del personaje en el juego.
- Carga y persiste ese estado.
- Maneja ~ 30 comandos entrantes (generalmente = los reenvía al
Game
, pero algunos comandos de solo lectura se responden de inmediato). - Recibe ~ 80 llamadas de
Game
acciones relacionadas con lo que toma y acciones relevantes de otros.
Me parece que Character
tiene una responsabilidad única: administrar el estado del personaje, mediando entre los comandos entrantes y el Juego.
Hay algunas otras responsabilidades que ya se han desglosado:
Character
tiene unaOutgoing
llamada para generar actualizaciones salientes para la aplicación cliente.Character
tiene unTimer
seguimiento que la próxima vez que se le permite hacer algo. Los comandos entrantes se validan contra esto.
Entonces mi pregunta es, ¿es aceptable tener una clase tan grande bajo SRP y principios similares? ¿Existen mejores prácticas para hacerlo menos engorroso (por ejemplo, tal vez dividir los métodos en archivos separados)? ¿O me estoy perdiendo algo y hay realmente una buena manera de dividirlo? Me doy cuenta de que esto es bastante subjetivo y me gustaría recibir comentarios de otros.
Aquí hay una muestra:
class Character(object):
def __init__(self):
self.game = None
self.health = 1000
self.successful_attacks = 0
self.points = 0
self.timer = Timer()
self.outgoing = Outgoing(self)
def load(self, db, id):
self.health, self.successful_attacks, self.points = db.load_character_data(id)
def save(self, db, id):
db.save_character_data(self, health, self.successful_attacks, self.points)
def handle_connect_to_game(self, game):
self.game.connect(self)
self.game = game
self.outgoing.send_connect_to_game(game)
def handle_attack(self, victim, attack_type):
if time.time() < self.timer.get_next_move_time():
raise Exception()
self.game.request_attack(self, victim, attack_type)
def on_attack(victim, attack_type, points):
self.points += points
self.successful_attacks += 1
self.outgoing.send_attack(self, victim, attack_type)
self.timer.add_attack(attacker=True)
def on_miss_attack(victim, attack_type):
self.missed_attacks += 1
self.outgoing.send_missed_attack()
self.timer.add_missed_attack()
def on_attacked(attacker, attack_type, damage):
self.start_defenses()
self.take_damage(damage)
self.outgoing.send_attack(attacker, self, attack_type)
self.timer.add_attack(victim=True)
def on_see_attack(attacker, victim, attack_type):
self.outgoing.send_attack(attacker, victim, attack_type)
self.timer.add_attack()
class Outgoing(object):
def __init__(self, character):
self.character = character
self.queue = []
def send_connect_to_game(game):
self._queue.append(...)
def send_attack(self, attacker, victim, attack_type):
self._queue.append(...)
class Timer(object):
def get_next_move_time(self):
return self._next_move_time
def add_attack(attacker=False, victim=False):
if attacker:
self.submit_move()
self.add_time(ATTACK_TIME)
if victim:
self.add_time(ATTACK_VICTIM_TIME)
class Game(object):
def connect(self, character):
if not self._accept_character(character):
raise Exception()
self.character_manager.add(character)
def request_attack(character, victim, attack_type):
if victim.has_immunity(attack_type):
character.on_miss_attack(victim, attack_type)
else:
points = self._calculate_points(character, victim, attack_type)
damage = self._calculate_damage(character, victim, attack_type)
character.on_attack(victim, attack_type, points)
victim.on_attacked(character, attack_type, damage)
for other in self.character_manager.get_observers(victim):
other.on_see_attack(character, victim, attack_type)
db.save_character_data(self, health, self.successful_attacks, self.points)
¿ Querías decirself.health
verdad?