Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

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)
share|improve this question

migrated from stackoverflow.com Jan 7 at 9:42

This question came from our site for professional and enthusiast programmers.

1  
The short short answer is: It depends on the use case. –  Joel Cornett Jan 3 at 21:59
    
Recommended reading: en.wikipedia.org/wiki/SOLID_(object-oriented_design) –  Johnsyweb Jan 3 at 23:30

3 Answers 3

up vote 0 down vote accepted

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.

share|improve this answer
    
Thanks for the good feedback. I was expecting more responses like "you should have..." or "why didn't you ...?". But what I was really hoping was a contribution like Rob's. I agree and - even with fewer coding years under my belt than most of you - would strongly endorse the section about getting attached to your own code. Very good point. Of course, I will take a look at SOLID ad GRASP - thanks for referencing those concepts. –  Arne Jan 7 at 15:10

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.

share|improve this answer

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!

share|improve this answer
    
I don't think that there's a bug here - self.town = town will be called whether or not the Inhabitant has the town attribute set. –  Rob Watts Jan 3 at 22:45
    
Thanks for the correction, but the town isn't set for the Inhabitant in the addpeople method, though. –  Steinar Lima Jan 3 at 23:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.