Does it violate GRASP if a Character class checks if it can carry a weapon?

Before I ask my question, I’m aware of Eric Lippert’s Wizard and Warrior series.

I’m trying to understand GRASP, but I’m having a hard time determining if this class violates GRASP.

Suppose if I had the following Character class:

class Character(ABC):

        def __init__(self, name, strength, attributes):
            self._name = name
            self._strength = strength
            self._attributes = attributes
            self._inventory = []
            self._found_attributes = []
            self._cannot_equip = False
            self._equipped = True

        def add(self, game_object):
            self._inventory.append(game_object)

        # I may obviously want to do more checks, such as required strength,
        # if I currently have another weapon equipped, etc..
        def try_equip(self, game_object):
            if self._check_for_conflicting_attributes(game_object):
                return self._cannot_equip
            return self._equipped

        def _check_for_conflicting_attributes(self, game_object):
            for attrib in self._attributes:
                if game_object.contains_attribute(attrib):
                    self._found_attributes.append(attrib)
            return len(self._found_attributes) > 0

Weapon class:

class GameWeapon(ABC):

    # imports and other methods left out. 

    def __init__(self, name, required_strength, damage, attributes):
        self._name = name
        self._required_strength = required_strength
        self._damage = damage
        self._attributes : List[Attributes] = attributes

    def contains_attribute(self, attribute):
        return attribute in self._attributes 

and Main:

def main():

    wizard_attributes : List[Attributes] = []
    wizard_attributes.append(Attributes.LongBlade)
    wizard_attributes.append(Attributes.Reloadable)

    wiz = Wizard("Gandalf", 100, wizard_attributes)

    sword_attributes : List[Attributes] = []
    sword_attributes.append(Attributes.LongBlade)
    sword = Sword("Standard Sword", 5, 10, sword_attributes)

    # Will print false
    print(wiz.try_equip(sword))


if __name__ == "__main__":
    main()

Explanation:

Both Wizard and Sword have attributes, for example, Wizard might have attribute called mana-drinker and Sword might have LongBlade as an attribute. Before adding a LongBlade weapon to my character inventory, I check for specific attributes, for example, a Wizard can’t use a Sword, so I check for LongBlade and if the weapon has that attribute it will prevent that weapon from being added to the character inventory.

One topic that’s always mentioned is class responsibility, if the Character class does violate GRASP is it because it has the responsibility of checking and verifying if it could add a weapon to the player inventory?

My larger question is, how do you know when a class may be violating GRASP? What if I want the class or subclass to be responsible for check before adding a weapon or doing another task? Is it still a violation?

4

Answer to the immediate example

GRASP includes the pattern Information Expert, which states that whatever object contains the information required to perform an action is responsible for performing it.

In your example, your Sword does not contain sufficient information to determine whether a character can equip it or not. This information resides in the Character class. Therefore, it should be the Character‘s responsibility to perform the action.

To answer the broader question

Whether your objects violate GRASP differs depending on which pattern it violates. A violation of the Information Expert pattern mentioned above, for example, can be recognized because you find your method doing more calls for data from another object than it does consulting its own; there is not enough information to perform your task so you do an unreasonable amount of reach to gather that information.

When I apply GRASP to a design, I follow a sort of checklist.

  • Do the methods and members all make sense together (have high cohesion) or should they be divided into multiple smaller, more specialized components?
  • Can cohesion be improved or operations simplified by extracting functionality from one object to another which has a greater amount of the data required for the operation (Information expert)
  • How tightly knit are objects with other objects? Are they too tightly coupled with their dependencies, such that one cannot exist without the other, changing one irrevocably means I have to change the other and are their reuse too limited as a result of either of these cases.
  • What is the relationship between an object and any other object it might instantiate. Does instantiation follow the creator pattern rules.
  • Do I have operations that depend on conditional statements based on some attribute on otherwise interchangeable components? Can I abstract these components in order to avoid branching? (Polymorphism)
  • Does any of my objects contain members such that I cannot extend the functionality of the contained member without altering functionality on the object containing it? (Protected variation)
  • Can I reduce coupling between any objects by introducing an intermediary object? (Indirection)
  • Do my data-model classes contain input handling or otherwise allow data-models to be directly modified without an intermediary controller?
  • Is there any problem in my domain that can be simplified by the introduction of an intermediary that is not itself part of the domain? (Pure fabrication)

As you may notice, almost every bulletin on that checklist relates to interaction between objects, and that’s because GRASP does not exist in isolation. In general, it does not make sense to ask if an individual object violates GRASP, because with only one object you only have one locus of responsibility. It’s when you connect objects to one another that the overall design of the system may violate GRASP.

Edit

To clarify, the Information Expert pattern does not state that an object can never request information from another object, but rather that the object that needs to ask for the least amount of information should be responsible for the task.

Given the situation in the question, Character contains a rule stating it cannot equip Weapons with the LongBlade attribute. Therefore, all we need to do to find out if the Character is allowed to equip a weapon, is ask for the Weapons attribute contains LongBlade.

If we reverse this responsibility, and instead give Weapon the responsibility of deciding without changing anything else, the game asks the Character to equip a Weapon, the Character asks the Weapon if it can be equipped, and the Weapon asks the same Character if it is allowed to be equipped. The decision ultimately then remains in Character, and it should have the responsibility to make it.

12

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật