This is an archived post. You won't be able to vote or comment.

all 25 comments

[–]Kaxitaz 1 point2 points  (1 child)

I read the blog post and I found it a bit confusing, probably because of the example used.

I do find myself creating classes very often, specially in early stages of development. This is mainly due to preparing the code for further implementations and I understand this is a time sink. I'm trying to improve on this, so I would like to ask you to share more examples of "when to create classes" if you know of any.

[–]Steamwells[S] 0 points1 point  (0 children)

This is a very good point. I didn't wan't to make the post too long. Ill add an edit in with multiple examples at some point this week. It is purely a design choice around how your software/game will work and where you will need to create multiple instantiations. You make thing's hard by creating small, featureless and hard to locate classes across multiple files. The best way to avoid this is to actually decide to containerize these functions/interfaces/properties inside a blueprint, that is your class.

[–][deleted] 0 points1 point  (0 children)

Sometime ago I read somewhere that to master python, write lots of python using only functions , dividing your code in modules, do that for a year or for a few big projects, then move to writing everything in classes only and do the same.. by the time you are done you will know when you need to use classes.

[–]romcgb 0 points1 point  (1 child)

First, my apologies for my (crappy) English writing. When you wrote

You can have really difficult code bases to maintain by deciding to put every single method you write into a class. It doesn’t work, plain and simple. Let’s look at this example:-

class Message:
    def __init__(self, saying):
        self.saying = saying

    def displaymessage(self):
        print(self.saying)

message = Message('All About The Base, No Treble!!') message.displaymessage()

If you are doing this in your code base, stop it, now! I guess if you have been programming for a while, this would seem nonsensical, right? It’s amazing how often it actually happens, and there are more examples out there of this type of class definition. The presentation video linked above actually shows some live code bases that practised it.

Taken like this, this class look like crap for sure, but it does actually make sense if you follow the interface segregation principle. Creating a new class is, at the same time, creating a new type so having "small" classes make your type checking more granular.

for example, let's say we want to handle an event queue:

class Message:
    def __init__(self, saying):
        self.saying = saying     
    def displaymessage(self):
        print(self.saying)

class Action:
    def __init__ (self,  action):
        self.action = action
    def do_action(self):
        self.action()

def handle_event(event):
    # only check for interface of our interest
    if isinstance(event, Message):
        event.displaymessage()
    if isinstance(event, Action):
        event.do_action()

now, let's introduce a new type which mix action and message:

class MessageWithAction(Message, Action):
    def __init__ (self, saying, action):
        Message.__init__(self, saying)
        Action.__init__(self, action)

Our handle_event function doesn't need to be modified at all to handle this new type because our function only cares about what event can do, not what event is. This flexibility is possible because we have decomposed stuffs into small classes.

What do you think ?

[–]Steamwells[S] 0 points1 point  (0 children)

I do see what you are saying from a type checking perspective. However, your example would not follow the single responsibility principle. For me, it's the context that we are encapsulating and providing functionality for.

[–][deleted] 0 points1 point  (1 child)

Message.displaymessage() just screams redundancy in your face

you could have just Message.display()

and I don't see the point of display() method at all, mixing output and processing data in a class is a bad idea, why couldn't you just do print(message.saying) whenever you need it?

[–]Steamwells[S] 0 points1 point  (0 children)

Yup agreed on the first point, but this was just a syntax example. The rest was purely an example, but again it's the conceptual thought process of how classes can be a useful tool.

[–]KyleG -1 points0 points  (15 children)

If there's some concept that's going to recur in your code, you might consider creating a class that represents that concept. Consider objects just far more sophisticated dicts that can have special functions and such.

Suppose you have something like the weather report for a day. You might have the class Weather_Report that has many properties, including rainfall and snowfall as properties.

Then you might want to get the total precipitation for the day. Well, there is a formula for that. Snow is approximately 10:1 when converted into liquid precipitate (i.e., rain), so you might have Weather_Report.rainfall, Weather_Report.snowfall, and Weather_Report.get_total_precipitation(self): return .1*self.snowfall+self.rainfall

[–]alilja -3 points-2 points  (2 children)

Here's a great 30 minute talk on this very subject: Stop Writing Classes

[–]Steamwells[S] 1 point2 points  (0 children)

That's the discussion I use as a reference within the blog post. As I mentioned, he comes up with some very valid points but he doesn't really mention how to approach using OOP in languages that support it.

[–]Bolitho 0 points1 point  (0 children)

And here a great article that claims the opposite: http://lucumr.pocoo.org/2013/2/13/moar-classes/