Python: How to decide which class’ methods should provide behavior (functionality) affecting multiple classes

I have a question about object oriented design that is not specific to Python but since my code is in Python, I tagged it as such. How do I decide which of my classes should be responsible for implementing certain functionality that may affect more than one class? What are some good guidelines >(if any) or considerations?

In the below example of a Town class, the behavior of moving to/from a town is split up among the Town class and Inhabitant class. The code works. But I am wondering if there are compelling reasons to assign this behavior to only one class, e.g. allow the Town method addpeople to update the Inhabitant attribute town so it’s possible to track each inhabitant’s place of residence.

Just trying to get a sense of what would be good practice or smart object oriented design.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class Town():
def __init__(self,name):
self.name = name
self.inhab = []
def addpeople(self,person):
self.inhab.append(person)
def removepeople(self, person):
self.inhab.remove(person)
class Inhabitant():
def __init__(self,name):
self.name = name
self.town = ""
def move(self,town):
if self.town:
print self.name,"is moving from",self.town.name, "to",town.name
self.town.removepeople(self)
else:
print self.name,"is moving to",town.name
self.town = town
town.addpeople(self)
</code>
<code>class Town(): def __init__(self,name): self.name = name self.inhab = [] def addpeople(self,person): self.inhab.append(person) def removepeople(self, person): self.inhab.remove(person) class Inhabitant(): def __init__(self,name): self.name = name self.town = "" def move(self,town): if self.town: print self.name,"is moving from",self.town.name, "to",town.name self.town.removepeople(self) else: print self.name,"is moving to",town.name self.town = town town.addpeople(self) </code>
class Town():

    def __init__(self,name):
        self.name = name
        self.inhab = []

    def addpeople(self,person):
        self.inhab.append(person)

    def removepeople(self, person):
        self.inhab.remove(person)


class Inhabitant():

    def __init__(self,name):
        self.name = name
        self.town = ""

    def move(self,town):
        if self.town:
            print self.name,"is moving from",self.town.name, "to",town.name
            self.town.removepeople(self)
        else:
            print self.name,"is moving to",town.name
        self.town = town
        town.addpeople(self)

2

In the below example of a Town class, the behavior of moving to/from a town is split up among the Town class and Inhabitant class. The code works. But I am wondering if there are compelling reasons to assign this behavior to only one class, e.g. allow the Town method addpeople to update the Inhabitant attribute town so it’s possible to track each inhabitant’s place of residence.

There is actually a good reason to not assign this behavior to only one class and keep it similar to what you have – in object-oriented programming you really want to have each object maintain control over its own data. Your code can easily become very complicated and hard to debug if you change variables outside of the object that the variable belongs to. This is part of the concept of encapsulation that is central to object-oriented programming.

Another part of OOP that is relevant here is abstraction, i.e you want the interaction between objects in your code to make sense at a higher level. Just from looking at this sample code, I would guess that the inhabitants of the towns are more the focus of your program than the towns themselves. If the user is interacting more with the town, I would expect the town to be doing more of the work (Town.addpeople calling Inhabitant.move, for example).

So as you are writing your program, think about which entities will be the ones doing the work. When your code matches your intuitive abstraction of what is happening, it will be much easier for you to keep track of what is going on and not introduce bugs into your code.

One other piece of advice I would give you may or may not be helpful, depending on what this project is for. If this is a program you are going to be actually using, maintaining, and upgrading, write a throwaway prototype first. As Joel Cornett mentioned in the comment, “It depends on the use case“, meaning that in order to know the best way to write the code you have to understand the situation. Some of this comes from experience, but unless you are perpetually writing pretty much the same program time and again, you will run into a situation that is not entirely familiar. Writing a prototype is an excellent way to get some experience with the specific problem that you are facing, because you often will not be able to see why one way or another will work better until you are fairly far into writing the program.

One thing that prevents people from creating a good system is that they get attached to their code. So if you choose to write a prototype, realize that it is a throwaway – something you write rapidly just for the purpose of getting a good feel for the problem. It can also help if you realize while you’re writing it that it doesn’t even have to work, as long as it helps you figure out what it would take for it to work well. Once you’ve written your prototype, you will have a much better feel for how you should have written your code. Then you can start over and write it correctly much faster.

In short, “It depends on the use case“, so make sure you understand the use case and have the code match your understanding.

1

Q. How do I decide which of my classes should be responsible for implementing certain functionality that may affect more than one class? What are some good guidelines (if any) or considerations?

A. The General Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, consists of guidelines for assigning responsibility to classes and objects in object-oriented design.

These guidelines help you balance the trade-offs and advantages for writing class methods with behaviors that affect multiple classes. In general, you are trying to put the methods in a class that has the most knowledge of how to implement the method, in the class that serves as a controller for other classes, and in a way the minimizes the number of cross-dependencies between each class.

I don’t see anything wrong with either. This is a question which has different answers for different cases – just do what seems more natural to you.

In some cases, you should stick to one of the methods. In other cases, both methods may be applicable to use in parallel, but you should be careful if you choose to do so:

Make sure that both have exactly the same outcome.

I’ve already identified a potential bug in your sample: The addpeople of Town doesn’t update the inhabitant’s town. If the Inhabitant doesn’t have a town yet, the town attribute is set. If you choose to move the person using Inhabitant.move though, the town is set. This is a typical way to introduce bugs, so please be careful if you choose this path!

2

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