How to manage coupling in model classes

I’m doing a class diagram for a game project, but I’m stuck on a coupling problem.

Context

The projet is a turn-based game. Two users are playing. They’ve got units on a map. They play until 1 player has all his units dead or if a predefined number of turns are reached.
At each round, each player will review his units one by one:

  • he can move an unit until the unit hasn’t got any movement point left
  • he can skip the unit’s turn

Modeling

Class diagram

Classes irrelevant to the questions have been cut

The Game class holds all the relevant objects : the players, the units, the current turn (which player(s) have already played, who’s next, …). The Turn object holds a PlayerTurn object, which keeps tracks of which units have already been played, which units are left to play, …

Problem

-> Let’s suppose we’re creating the GetNextPlayableUnit method (in class PlayerTurn).

We’ll have to iterate through the current player’s units and find one that is not in the “PlayedUnits” list. Therefore, we’ll have to call Game.Units.GetUnits with the parameter Game.Turn.CurrentPlayer (Game refers to the current Game’s instance).

-> Let’s suppose we’re creating the MoveTo method (in class Unit).

If the Unit hasn’t got any movement point left, we’ll have to call Game.Turn.PlayerTurn.Finish which will either select the next playable unit or finish the current player’s turn if he already played all of his units this turn.

-> … There are a lot of other scenarios where we’ll need to access other classes’ method. E.g., a “Kill” method on Unit will have to check if the current player has still got at least 1 unit alive, and it will have to call a Finish method on Game otherwise.

Question

I think the coupling can’t be avoided (correct me if I’m wrong though!). I’ve thought about two possible ways of dealing with coupling:

Solution 1

When constructing instances of these classes, I could pass the current Game’s instance. After all, it makes sense: Unit instances, Turn instances, … all belong to a game.
Then, I could implement the methods GetNextPlayableUnit, MoveTo, Killed, … easily by using this instance. Somehow, I don’t feel comfortable sharing the current game’s instance between all the model classes, even though I read here and there that it was the principle of dependency injection.

Solution 2

  1. Analyse the method dependencies: e.g., Kill method depends on Game.Units.Unit.Player (to retrieve the Player owning the Unit), on Game.Units.GetUnits (to find all other Units owned by the player), on Game.End to end the game if unit count of the player has reached 0.
  2. Find the dependencies common root: in the example above, the common root between Game.Units.Unit, Game.Units and Game is Game. In another example, if we had the dependencies Game.Units.Unit & Game.Units.SomethingElse, the common root would be Game.Units.
  3. Implement the method in this common root class. We’re guaranteed not to need to access parent classes (in the association hierarchy).

Risks:

  • lots of methods will have the Game class for common root => lots of methods in Game class => lots of code in Game class.
  • methods won’t belong to their rightful classes. Consider the method “KillUnit”: you’d expect to find it in the Unit class directly, not in the Game class. Same goes for “MoveTo”, “Finish”, …

Is there any other solution you can think of? What would be the best approach in this particular case?

You ask about other solutions. These might be reflections on your process of finding solutions:

  1. This is your first version of the diagram and you do not want to throw it away and restart. It makes it more likely that you mix old, maybe irrelevant thoughts with new thoughts.
  2. While you model you think about implementing it. That mixes how you think the model should be and how the programming language wants it to look like. Modeling is not implementing. You should end up with more methods and hopefully more classes in your implementation than your model.
  3. I think the Units class is one way of implementing the desired behavior. It can be let out at your level of granularity. For example, the Player class does not point at a String-subclass PlayerName. Keep one level of granularity in your diagrams.
  4. Starting with a class diagram might not be the choice. An object diagram is more specific. Class diagrams are more general. So I think one can get lost in generalizations that do not need to make sense.
  5. You have different scenarios, play-throughs. You can make several object diagrams from them and generalize from there. No need to put everything in one diagram at once.

To your concern: behavior can be found in several methods Unit.Die() Playfield.RemoveUnit(), Player.KillUnit() at the same time. That is OK. But you want to avoid copy and pasting the code into every method.

About coupling. I think you do/can/must/want not avoid coupling. Some objects should interact. A bad case is when all objects always interact with all other objects in every method. That is too much coupling with no separation of concerns.

And maybe an outdated opinion: OOP is about objects and their interactions, not about classes, not about inheritance.

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

How to manage coupling in model classes

I’m doing a class diagram for a game project, but I’m stuck on a coupling problem.

Context

The projet is a turn-based game. Two users are playing. They’ve got units on a map. They play until 1 player has all his units dead or if a predefined number of turns are reached.
At each round, each player will review his units one by one:

  • he can move an unit until the unit hasn’t got any movement point left
  • he can skip the unit’s turn

Modeling

Class diagram

Classes irrelevant to the questions have been cut

The Game class holds all the relevant objects : the players, the units, the current turn (which player(s) have already played, who’s next, …). The Turn object holds a PlayerTurn object, which keeps tracks of which units have already been played, which units are left to play, …

Problem

-> Let’s suppose we’re creating the GetNextPlayableUnit method (in class PlayerTurn).

We’ll have to iterate through the current player’s units and find one that is not in the “PlayedUnits” list. Therefore, we’ll have to call Game.Units.GetUnits with the parameter Game.Turn.CurrentPlayer (Game refers to the current Game’s instance).

-> Let’s suppose we’re creating the MoveTo method (in class Unit).

If the Unit hasn’t got any movement point left, we’ll have to call Game.Turn.PlayerTurn.Finish which will either select the next playable unit or finish the current player’s turn if he already played all of his units this turn.

-> … There are a lot of other scenarios where we’ll need to access other classes’ method. E.g., a “Kill” method on Unit will have to check if the current player has still got at least 1 unit alive, and it will have to call a Finish method on Game otherwise.

Question

I think the coupling can’t be avoided (correct me if I’m wrong though!). I’ve thought about two possible ways of dealing with coupling:

Solution 1

When constructing instances of these classes, I could pass the current Game’s instance. After all, it makes sense: Unit instances, Turn instances, … all belong to a game.
Then, I could implement the methods GetNextPlayableUnit, MoveTo, Killed, … easily by using this instance. Somehow, I don’t feel comfortable sharing the current game’s instance between all the model classes, even though I read here and there that it was the principle of dependency injection.

Solution 2

  1. Analyse the method dependencies: e.g., Kill method depends on Game.Units.Unit.Player (to retrieve the Player owning the Unit), on Game.Units.GetUnits (to find all other Units owned by the player), on Game.End to end the game if unit count of the player has reached 0.
  2. Find the dependencies common root: in the example above, the common root between Game.Units.Unit, Game.Units and Game is Game. In another example, if we had the dependencies Game.Units.Unit & Game.Units.SomethingElse, the common root would be Game.Units.
  3. Implement the method in this common root class. We’re guaranteed not to need to access parent classes (in the association hierarchy).

Risks:

  • lots of methods will have the Game class for common root => lots of methods in Game class => lots of code in Game class.
  • methods won’t belong to their rightful classes. Consider the method “KillUnit”: you’d expect to find it in the Unit class directly, not in the Game class. Same goes for “MoveTo”, “Finish”, …

Is there any other solution you can think of? What would be the best approach in this particular case?

You ask about other solutions. These might be reflections on your process of finding solutions:

  1. This is your first version of the diagram and you do not want to throw it away and restart. It makes it more likely that you mix old, maybe irrelevant thoughts with new thoughts.
  2. While you model you think about implementing it. That mixes how you think the model should be and how the programming language wants it to look like. Modeling is not implementing. You should end up with more methods and hopefully more classes in your implementation than your model.
  3. I think the Units class is one way of implementing the desired behavior. It can be let out at your level of granularity. For example, the Player class does not point at a String-subclass PlayerName. Keep one level of granularity in your diagrams.
  4. Starting with a class diagram might not be the choice. An object diagram is more specific. Class diagrams are more general. So I think one can get lost in generalizations that do not need to make sense.
  5. You have different scenarios, play-throughs. You can make several object diagrams from them and generalize from there. No need to put everything in one diagram at once.

To your concern: behavior can be found in several methods Unit.Die() Playfield.RemoveUnit(), Player.KillUnit() at the same time. That is OK. But you want to avoid copy and pasting the code into every method.

About coupling. I think you do/can/must/want not avoid coupling. Some objects should interact. A bad case is when all objects always interact with all other objects in every method. That is too much coupling with no separation of concerns.

And maybe an outdated opinion: OOP is about objects and their interactions, not about classes, not about inheritance.

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