OOP and Functional Programming (for the sake of my sanity, only talk about Python)

Resource for OOP Python

For Python, I really like the python-course.eu tutorials/writeups.

They have a whole series about OOP (object oriented programming is a deeeep rabbit hole in python): OOP Python Tutorial: Object Oriented Programming

My thoughts on OOP

The definition of OOP is not set in stone and most people understand something different under it.

However, most languages use OOP as a kind of “syntactic sugar” to enable (hopefully) more readable code.

Instead of the need to include the object in the function parameter list, e.g., do_something(object,a,b,c) it enables one to express it in a construct that is similar to the English sentence structure (Subject Verb Object (SVO)) object.do_something(a,b,c): this can be read as “object do something with a,b,c”. (The object is the subject, do_something the verb and a,b,c the objects).

Functional programming

Functional programming is all about having as little side effects in the code as possible:
When looking at a do_something(a,b,c) function call, a side effect could be that one or multiple of the parameter objects (a,b,c) are changed after the function call. Global variables can be also seen as parameters of the function. Also for object.do_something(a,b,c) the object can be seen as a parameter and should therefore when programming functionally not change.

Now in python it is not possible to enforce these functional restrictions within the “python language”, which is why so many people recommend learning a functional language like haskell such that one is forced to program in a functional style.

There is an additional “problem” with functional programming: a program with no side effects will do, effectively, nothing. This tells us that at some level “code with side effects is necessary”. For example the print function has side effects because a global variable somewhere is changed such that the printout appears on the screen.

So why is functional programming becoming popular? The reason is that functional code is a lot easier to reason about.


Edit: do no longer use the term “purely functional program”

4 Likes

While you are not completely wrong, a PFP (Purely Functional Programming) program is not quite the same as a PFP function. A PFP program has a single place where “side effects” are allowed to happen; the main function. Otherwise I completely agree with what you said. :slight_smile:

1 Like

Why not both? I’m in college rn, and theoretical stuff is all college is. I spend half my free time working on my own projects. It’s called time management. Learn it. (yes, I’m a little salty and offended xD).

My current university (and the universities before it) don’t even care that functional exists. They try to teach OOP, but my brain cannot wrap around OOP very well. To a large extent, modern-day OOP seems counterintuitive to me. Essentially, no such course exists for me.

https://docs.python.org/3/howto/functional.html

Not the only resource out there for doing this. I could go on Amazon and look up a bunch of books. :roll_eyes:

Quite simply, Python does not force you into a specific programming style, unlike Java for example. I’m sure a “Functional language” like Haskell or Clojure forces functional style programming.

If you are having a difficult time understanding it, don’t beat yourself up about it.

Get some good real-world experience, stretch your legs, and see what problems you run into. Eventually you will run into a problem and think “gosh, if only there were some easier way to solve this!” and suddenly you understand X language feature.

I had the same issue with horizontal inheritance for a while. I didn’t get it, beat myself up over it, then eventually gave up. Eventually I ran into an issue where I thought “It sure would be nice if I could do X” and it clicked into place.

1 Like

I can not recommend reading https://python-course.eu enough! (No need for a book.)

(Nobody seems to have clicked on it yet, there is no number next to the link I posted :wink: )

You can probably jump directly into the “OOP” and “Advanced” section. The “Advanced” section contains a lot of concepts that come from functional ideas.

The website was created by a person that professionally teaches. And the explanations are not just great to understand, but also deep enough to learn about how python works.

Thank you thank you thank you for explaining state like this. I’ve researched it so much, but nothing has ever been this succinct! :smiley:

That was me with OOP, actually. I remember watching a video before on “Object-Oriented Programming is Bad”. I didn’t understand most of it. Soon after creating this forum thread, I went back through my YT history trying to find some of the programming videos I’d watched in the past and found that one. I rewatched it and was amazed at how much I understood compared to about a year ago.

I apologize, but I realize that I must clarify something. When I said, “…no such course exists for me.” I meant that functional programming courses do not exist, and also a “Programming languages and compilers course” doesn’t exist for me either.

Also, idk how to put this, but the reason I asked about this is because Functional Programming intrigues me. I feel like it may fit my style better than OOP. For example, Tyler Gautney / linuxdragon_cms · GitLab. This is my Devember project btw, and it is unfinished, yes. I knew it wouldn’t be finished for a long time, but my goal with Devember 2020 was for me to just make something. I hope that this year, however, my goal will be to try to win Devember2021. Notice the style. Honestly, idk if I am using Structural, Functional, or OOP style. I’m just trying to write something that works. That being said, however, everything is done through function calls with the exception of database management. That is created, updated, and deleted through PeeWee which is an Object-Oriented ORM.

Oh yeah, I do want to know something. Some of the videos I’ve watched say that inheritance is bad, and composition should replace it. And indeed, when I looked it up, the internet provided me with yet more examples of this sentiment. What are y’all’s thoughts on this? And for me, I personally want to know why it is bad, and how I can replace subclassing with whatever the heck composition is.

The argument against inheritance is mainly that in practice it is most of the time not possible to correctly identify “is a” relations.

Inheritance example:

class Robot:
  pass
        
class PhysicianRobot(Robot):
  pass

A PhysicianRobot is a Robot.


Now composition tries to model “has a” relations.
Composition example:

class Robot:
  pass
        
class PhysicianRobot:
  def __init__(self):
    self.robot = Robot()

A PhysicianRobot has a Robot.


For simple examples, defining “is a” relations with inheritance works most of the time (which is probably why it is popular to be teached).


Regarding what I like to do:

  • I like to use OOP (i.e., create classes) only when it simplifies the task.
  • Do not use inheritance
  • I think the SOLID principles are decent OOP guidelines. (mostly use S, I and D. O might be good to keep in mind for some high level design. And L should strongly be followed if you want to use inheritance.)

if you don’t mind my asking, how can I turn these into composition classes?

from datetime import datetime
import peewee

db = peewee.SqliteDatabase('test.db')



class BaseModel(peewee.Model):
    # A base model that will use our database
    class Meta:
        database = db


class Author(BaseModel):
    userID = peewee.IntegerField(primary_key=True)
    username = peewee.CharField(unique=True, null=False)
    passwd_hash = peewee.CharField(null=False)
    f_name = peewee.CharField(null=False)
    l_name = peewee.CharField(null=False)
    admin = peewee.BooleanField(null=False, default=False)


class Entry(BaseModel):
    id = peewee.IntegerField(primary_key=True)
    title = peewee.CharField(null=False)
    content = peewee.TextField(null=False)
    created_on = peewee.DateTimeField(default=datetime.now, null=False)
    genre = peewee.CharField(null=False)

class AuthorEntries(BaseModel):
    author = peewee.ForeignKeyField(Author, backref='blogposts')
    posts = peewee.ForeignKeyField(Entry, backref='created_by')

Honestly my biggest fear of this is it not working because there is so much I don’t understand about what I am doing. IMO, Peewee’s documentation isn’t great - but that may just be me. (I don’t even understand the Meta class within the BaseModel class; that’s just how Peewee recommended to me to do it.

And it’s not that I didn’t try to look up what a Meta class is when it’s nested like that. The explanations flew over my head and I was already so inundated with information overload at the time that I just gave up so that I could move on xD.

Looks to me like a pattern the peewee library decided on.
I do not think that this is something that would be worth it to change.

If something is always done in the same way, i.e., every application that uses the peewee library does it in the same way, and there are no practical disadvantages, then it probably does not make sense to try and do it differently.

I feel like the KISS principle plays into that a bit:

  • Do not overengineer
  • Do not try to be clever
1 Like

Inheritance is still useful for polymorphic relations, and it very much does make sense in some cases. But it should be treated as another tool, rather than the first tool ones reaches for.

Of course, to know which tools are appropriate, one must have knowledge of a wide selection of tools.

Yep. I myself believe that OOP is the proverbial hammer, and every computer science problem isn’t a nail.

Yeah. I was trying to stay in the Python world were polymorphism can be achieved with ducktyping.

If the language has interfaces/protocols/abstract classes/traits/type classes, they are used for polymorphism, and according do the I and (sometimes) D in SOLID.

Though, I basically never decide on my own to inherit from “real classes”.
Sure, if a framework is used that requires inheriting some class, I will use inheritance in the way the framework intended.

Inheritance of interfaces/protocols/… is pretty ok as well.

It is when state comes into play and invariants need to hold where inheritance gets gnarly.

Modern languages like Rust and Julia do not even have “real class” inheritance.

Thankfully you don’t usually need much deeper than that, though I vaguely recall reading about a seventh-order function as some sort of DSL compiler.

1 Like

I think the original question was what is Object Oriented Programing (OOP) and want is Functional Programming. Of course I can be easily confused so I may be missing the point.

Just my two cents.

OOP - It is all about objects. Objects own/contain data and functions (referred to as methods many times) all the other stuff (constructors, destructors, classes, inheritance, polymophism, etc.) are just facilities/techniques for managing certain complexities that come up with objects.

Functional Programing - It is all about functions (some languages call them procedures and just to add to the confusion some languages have both function and procedures, I’m looking at you Pascal). A function is given input parameters and is expected to act with those parameters and do something interesting. What is interesting is a pretty long list, but the simplest something is to give back some data.