jeudi 8 février 2018

Law of Demeter with SRP

I am struggling with the concept of following SRP with the Law of Demeter.

Here are some example classes of a unfinished example program representing an RPG.

class Weapon
{
    public int MinimumDamage { get; set; }
    public int MaximumDamage { get; set; }
    public string Name { get; set; }

    public int Damage => new Random().Next(MinimumDamage,MaximumDamage);

    public void Attack(Entity monster)
    {
        monster.ReceiveDamage(Damage);
    }
}

class Entity
{
    public int CurrentHealth { get; set; }
    public int MaxHealth { get; set; }
    public Stats Stats { get; set; }
    public string Name { get; set; }
    public Weapon EquippedWeapon { get; set; }

    public void ReceiveDamage(int damage)
    {
        CurrentHealth -= damage;
    }

    public void Attack(Entity target)
    {
        EquippedWeapon.Attack(target);
    }
}

class Stats
{
    public int Speed { get; set; } = 1;
    public int Armor { get; set; } = 1;
}

class Battle
{

    private readonly Entity _player;
    private readonly Entity _monster;

    public Battle(Entity player, Entity monster)
    {
        _player = player;
        _monster = monster;
    }

    public void StartBattle()
    {
        if (_player.Stats.Speed >= _monster.Stats.Speed)
        {
            _player.Attack(_monster);
            _monster.Attack(_player);
        }
        else
        {
            _monster.Attack(_player);
            _player.Attack(_monster);
        }
    }
}

The example does not violate Law of Demeter (Stats is a data only structure), but both Weapon and Entity have an attack method. Those were implemented to avoid a Law of Demeter violation.

Is this the proper way of working around the issue, is it good design or bad design?

Entity could end up doing too much like calculating how much damage they receive depending on their own armor.

I always figured if a class does too much you make it a member and it's own type. But if I end up doing that, it will easily violate the Law of Demeter.

You could call _player.EquippedWeapon.Attack() or _player.Attack(), just seems like its adding more methods to a class potentially causing bloat or a god object.

Aucun commentaire:

Enregistrer un commentaire