law of demeter and planeshift

2019-07-30 06:25发布

问题:

The source code of this game is open source, so I decided to check it out. In it, I found something like:

// This ActionManager is basically a controller like in the MVC pattern.
void ActionManager::HandleQueryMessage(csString xml, Client* client)
{
    //check the two hands as a start.
    psItem* item = client->GetCharacterData()->Inventory().GetInventoryItem(PSCHARACTER_SLOT_RIGHTHAND);
    if(!item || !item->GetItemCommand().Length())
        item = client->GetCharacterData()->Inventory().GetInventoryItem(PSCHARACTER_SLOT_LEFTHAND);
}

The first line to get the item clearly violates the law of demeter. However, even if it was changed to client->GetCharacterData()->GetInventoryItem(PSCHARACTER_SLOT_RIGHTHAND);, it would still violate the law of demeter (as far as I know).

What can be done about it? or is this one of the places where LOD doesn't apply [as in my second example]?

Moving the GetInventoryItem up to the client class doesn't makes sense in my point of view since the client has nothing to do with the character.

Creating wrappers in the client class for all the xx methods the character class seems overkill.

Any thoughts?

回答1:

As you suggest yourself, if you want to follow LOD completely, you'd need functions like...

Item* Client::GetCharacterInventoryItem(int itemID) 
{
    return characterData->getInventoryItem(itemId);
}
/* ... */
Item* CharacterData::getInventoryItem(int itemID)
{
    return inventory->getItem(itemId)
}
/* ... */ 
Item* Inventory::getItem(int itemID)
{
    assert_valid_itemID(itemID);
    return inventory_table[itemId];
}

Is this additional indirection worth it? I don't know, that depends on the case, your personal preference, etc. As the comments indicate, the LOD should be viewed as a guideline, not really a law. On the other hand, in my personal experience, break it frequently and you will get into trouble... :)