Reducing state and OOP is not against each other, I believe FP+OOP is a good match. Many problems are data-oriented where FP is hands down better, but I think OOP helps exactly at the side-effecting edges.
But eventually a junior developer realizes that a Triangle is an PolygonalOpenFrameMetallicPercussionInstrument and it now has 4kb of private state, 307 inherited member functions, and floods your console when its logged.
Presumably thinking of virtual methods, in the context of C++ ? At least that used to make your code very slightly slower. Might be measurable in a tight loop?
You don't know how much memory an object of a given type takes to instantiate. This makes object allocation slower. This also means that you can't allocate a Vector<T> inline. It has to be a vector of pointers.
You don't know what fields a type has. This makes GC scanning more expensive.
You can't optimize the layout of a type. If you know an object doesn't have subtypes, you can move it's fields around to reduce padding. If you want to be able to look up fields quickly, you need to put all the fields of the supertype first in memory which will increase the size of your objects.
You can surely allocate a Vector<T> inline, no need for pointers, just make use of compile time polymorphism instead of runtime one.
On OOP languages with GC, you can reduce GC scanning by having precise GC, and if the languages support value types by making use of structs with method pointers.
With the help of PGO for AOT or the JIT, the compiler can optimize the layout of types for the target architecture.
You are comparing having a feature vs not having it. To make it fair you have to provide for polymorphism, and at that point most of your points become moot in lower level languages as well. Also, bounded subclassing exists (sealed/final classes) so in theory most/some of the optimizations you mention are possible.
Sure you can — in your own code. But everywhere else inheritance is a virus. Spring, Rails, .NET Core, Django, Pydantic — just to take some random examples are all fundamentally base on inheritance.
Not a concern if PolygonalOpenFrameMetallicPercussionInstrument is just a pure interface/type-class/trait. Now, is that (i.e. interface-only inheritance) still OOP proper, or just a case of "object based" coding, a straightforward "common sense extension" of simple data abstraction? People will disagree about this point, and it's mostly just a matter of definition.
If you have to justify proposals with explicit reasoning (or conversely, if you're allowed to), then it's hard to reject them because they go against common sense, since it's hard to just say "my intuition told me this would be bad".
Agreed, of course so many reasoned conversations it seems like at some point have a moment of intuition because not everything can be known at the time. I think this is the stuff that makes engineering fun. That combination of well reasoned responses sprinkled with gut feeling and heuristics.
OOP's greatest crime is needlessly adding an I-thou dichotomy to the realm of programming languages. The "switching" or context sensitive properties of deictic pronoun referents is one of the last and most difficult linguistic skills that first language learners acquire. Class instances add deixis to programming languages, which never needed it and don't benefit.
I think they're complaining about `this`, which I also find annoying, but don't feel the need to dress that up in fancy terms.
My issue with `this` and things like it is that the first argument (the 'object') is usually the most important thing, and it's easier to read methods if they have a name.
Ok, you can call this deixis but do you need to? Clearly not.
Your fancy terms are someone else's terms. It was critical to their point about how deixis specifically being difficult for new language learners. Addutionally I enjoyed skimming the Wikipedia articles and considering programming languages as languages; I got more out of it than I do most HN comments.
I think it's fair to skip over a comment using terminology you find tiresome, be it because you aren't familiar, or you find it irritating for some reason, or for any reason; it's your time. I think it's unnecessary to insist we all use the same terminology, as that just limits what conversations can be had and who can have them. One of the things that makes HN feel magical is when people from a weird discipline jump in to give their two cents, and they add value to the community when they bring their terminology with them.
There is no value in the terminology. A sign of true expertise in a field is the ability to explain fundamental concepts without having to resort to jargon. Jargon helps communication between people who are already familiar with the concept.
This does not mean that we need to dumb things down, but if OP can not explain things in a simplified matter, I'd take it as a signal that OP's criticism at best as non-practical and at worst as pseudo-intellectual BS.
Words are tools of thought, and it's good to be exposed to new tools. They give you different angles and nuances to approach a problem. Presenting things plainly is nice. But insisting it's the only way to communicate is silly. Not every form of communication has to be nonchallenging. Not everything has to be predigested for you. It's okay for some things to take a little work to unpack.
Dismissing someone for using different terminology is dismissing someone who could surprise you or teach you something new because you don't like the aesthetics of their speech and you aren't willing to put in the effort to understand them. If you don't want to spend your time that way I understand, but why is that a stance? Why isn't that just how you've prioritized your day, without making it a moral judgement about the quality of their speech?
> This does not mean that we need to dumb things down, but if OP can not explain things in a simplified matter, I'd take it as a signal that OP's criticism at best as non-practical and at worst as pseudo-intellectual BS.
What you're saying here is that you'd rather rely on this heuristic to dismiss what they have to say, then figure out whether what they say has value. And you do you. But this isn't a reflection on anyone other than you. It isn't a criticism of their statement. You're kinda cheating yourself. You've just decided that along this certain axis, your thinking is done expanding and you have no more to learn. And that's unfortunate, I hope you'll reconsider because there's a lot of richness there.
That is a lot of words to say "I have a fetish for intellectual babble".
I didn't say that the type of speech alone is enough to dismiss the argument. I am saying that resorting to terms more complicated than needed hinders communication.
If "words are tools for thought", OP is using the wrong tool and you are jerking off to someone who is employing a (overtly fancy) chisel to sand a block of wood.
(And yes, I did read up on the terms. His criticism is still vague and does not seem rooted in actual experience as a programmer, teacher or programming language designer.)
> (And yes, I did read up on the terms. His criticism is still vague and does not seem rooted in actual experience as a programmer, teacher or programming language designer.)
This being precisely why I found it to be a fresh and interesting viewpoint; I've heard a lot from programmers and language designers on this topic, I hadn't heard from linguists before. I found their use of different tools of thought than I had seen applied to this area intriguing and it made me see things in a different way; you seem to have interpreted this as "using the wrong tools" because they weren't the ones you were used to. This is exactly what I was saying; you're limiting the conversation to an insular set of perspectives.
You've bought my premise about what you're saying, and in lieu of justification you've provided some cheap insults. I'm glad we understand each other.
Different perspectives are interesting if they can be used to solve the problem at hand.
> I hadn't heard from linguists before.
Are you sure? Larry Wall, creator of Perl, is a linguist. His education certainly guided his decisions when designing the language. He certainly had different "tools of thought" compared to other programmers at the time, and it shows. You can hear him multiple talks and read books from him about the topic, and none of them are filled with out-of-context, unnecessary jargon.
I think he's trying to say that object methods now can refer to two different tenses of things - this/self/me, and everything else (it/that). In C there is only the latter. (And also "look at the clever words I know!")
It's nonsense though because this/self is barely more than syntactic sugar for what C programmers do anyway - in fact languages with UFCS let you choose arbitrarily. Writing free functions with `this` as the first parameter doesn't really change anything.
They are saying they favor the emacs model over that of vi, and that subsequent editors have not added any appreciable value. Well, that's what they said, after transpiling into an editor discussion about modal vs. non-modal editors against the backdrop of forking editors in order to add new features.
Is it that programming languages don't need deixis or that OOP does it badly? I think OOP makes context more diffuse and you encounter it more often. I think that data-oriented languages like SQL do a better job of managing context. But I can't say whether or not it is necessary and I don't think I've used a programming language without it, so I don't know what that programming paradigm would be like and whether I'm missing out something.
It's far from needless - doing so enables syntonic reasoning [0] by the programmer, as originally explored by Papert in Logo's turtle graphics, which was one of the direct inspirations for Smalltalk. There's a reason this "last and most difficult linguistic skill" is so handy - with it we can refer to objects across space and time.
I don't know what to make of this comment. On the one hand, I've worked with people who technobabble so I wonder if that's what this is. On the other hand, I question if maybe I'm just an idiot who doesn't operate on your level. Either way, I think there is something to be said about communicating succinctly in plain English. This comment reminds me of the joke/quote "Never use a long word when a diminutive one will do."
I was unfamiliar with these terms as well, but I looked them up and was able to figure it out. It's not technobabble and I doubt that it's just above you either, they're just words you don't know that you can look up. They didn't use words that were unnecessarily complex, they were just referring to concepts you hadn't heard the word for before, and they happen to have a stiff and academic feel to them.
Concurrency, syntactic sugar, object oriented, monotonic clock, these all sound like babble to someone uninitiated as well.
I consider OOP's greatest crime to be 'reification' at the finest level, i.e. to give small bits of data 'identity' or a concrete location. Thus suddenly you have things like the I-thou dichotomy and deictic pronoun referents, which have no place in data processing, and also potentially replicated state and thus complexity explosion.
Of course this was inevitable given the place orientated von Neumann architecture (the tape, with its distinct locations). Much as OO practitioners like to think OO is special or deep in some sense, it is in fact just a conceptual hack to accommodate the inherent clumsiness of our particular adding machines, dressing their flaws in fancy clothes to hide our shame. If it wasn't for C pointers, programmers would think OO was some sort of nightmare fuel from another dimension.
The biggest problem with OOP is the concept of class hierarchies. They're an unnatural representation of units of work and state that force obtuse topological reasoning where there should be none.
Traits and type classes are a much better solution that offer far more flexibility, yet still allow the programmer their own balance of expressiveness and rigidity.
Of course data can have defined behavior. Don't try to marshall it into genetic lineages of parents and ancestors. That's an orthogonal and entirely made up problem.
Traits and type classes are broadly the same as interface inheritance. So there still is a hierarchy, it's just restricted to the interface layer as opposed to impacting the implementation.
In terms of readability and maintainability, one problem with OOP is the development process that tends to go with it, where you're asked to create upfront the separation of concerns, before code has had a chance to run and breathe for a while. Most of the time, you end up being wrong on how things should be segregated, and your behavior ends up fragmented across a variety of objects, making it difficult to easily see the flow of your program. Actions related to a Widget end up not actually being neatly encapsulated in a Widget, and encapsulation is one of the major selling points of OOP.
It's probably best to start off a solution with plain old data structures, and plain old functions (ie. procedural style). Build with that until right abstractions or separations emerge.
Also, within the context of an individual class, variables can be modified and accessed anywhere in the class, creating all the same problems as global variables.
If the single responsibility principle is followed and cohesion is strong, it should help mitigate these concerns. Creating large uber classes can quickly become troublesome.
> Most of the time, you end up being wrong on how things should be segregated, and your behavior ends up fragmented across a variety of objects, making it difficult to easily see the flow of your program.
This can only become a problem if you pay little to no attention to modularization, software architecture, and even encapsulation.
The responsibility of a paradigm and a language is to allow a developer to freely express their concepts. The programming paradigm is not to blame if the developer chooses to express poorly thought-out ideas that are riddled with detrimental consequences.
the problem is not about software development, it's about business logic that change, when a new client arrive and want new features, some feature where not usefull, other needed change ...
> the problem is not about software development, it's about business logic that change, when a new client arrive and want new features, some feature where not usefull, other needed change ...
You're giving the textbook example of problems created and solved by putting together a working software architecture. Books like Bob Martin's "Clean Architecture" refer explicitly to needs to accommodate changes to business and application layers, and the need to design components to accommodate changes, and the book is language-agnostic.
I disagree. Consider the Brainfuck argument. You can totally blame Brainfuck and its “paradigm” for detrimental consequences.
My point is it’s easier to modularize and encapsulate properly with procedural or functional paradigms because they don’t force you to do that work before you start solving problems. The dev flow is: solve problem, then modularize. With OOP, the flow is: modularize, then solve problem.
I’m simplifying and of course you can architect correctly upfront, it’s just harder because you’re doing speculative generalization (akin to premature optimization).
> I disagree. Consider the Brainfuck argument. You can totally blame Brainfuck and its “paradigm” for detrimental consequences.
That's a poorly put-together red-herring. Brainfuck is not one of the leading production programming languages that has been used for decades to write all sorts of applications, from operating systems to web services and specially desktop applications, AAA games, and high-performance computing. Brainfuck is a gimmick "esoteric" programming language used as a challenge.
> My point is it’s easier to modularize and encapsulate properly with procedural or functional paradigms because they don’t force you to do that work before you start solving problems.
The thing is your point does not hold at all. It's trivial to modularize and encapsulate and even isolate components with C++. You only need to want to do it. If you don't want to modularize or encapsulate or isolate components then you get what you want. Don't blame the language for the software architecture you chose to adopt for your project.
First you backtrack your generalization regarding languages, which makes one ask what other omitted features have to be present to rely on the statement.
Second you're not supporting your claim "It's trivial to modularize and encapsulate and even isolate components with C++. You only need to want to do it." It directly contradicts the observation that programs, when written, are often found to be designed incorrectly, and it's important that the language would support enough their recomposition. Just wanting to make a good architecture doesn't make it right all by itself, sometimes you have to change already existing things, and how easy it is has a lot to do with the language.
I think you and the GP are actually saying the same things. Where GP says OOP requires you to "create upfront the separation of concerns, before code has had a chance to run...", you refer to allowing "a developer to _freely_ express their concepts" (emphasis mine).
I think that "freely" is what GP is complaining about; that OOP practices limit your freedom by encouraging early lock-in and making past decisions hard to revisit in light of new facts.
I'm not sure I entirely agree, mind you, but I do think you're in more agreement than disagreement.
This is the same reason why I think TDD is the wrong approach too. How do you test before you know what you're building?
I've tried everything but my favored approach these days is just to stream of conscious psuedocode in main() to get the shape of what needs to happen, and then backfill until there's something working. Once I know what I want, only then do I break things up so that everything is in the right place. It seems to end well every time.
Yes, that would make sense... unfortunately companies I know that follow TDD religiously have taken the approach that tests drive design and development.
Something being common sense is not a good argument for it making sense. The most obvious demonstration of that is physics. Our common sense is hopeless at modelling the world around us accurately. Maths is better at that. In programming, similarly, algebraic properties and representation in memory should be preferred over a reasoning that something is just “common sense”.
I’m not sure what I supposed to be reading here but the title at least rang a bell of recognition for me.
Programming to an interface, composition, immutable classes and objects as fancy closures that can do more than one thing: Drake-yes-please.jpg
Inheritance for code sharing: Drake-no-thanks.jpg.
One thing I really miss from my Java days, and which I don’t really think has anything to do with OOP, is the concept of package visibility. Private data for the class itself. Protected data for inheritors if you dare have them. Public for anyone using your library. And package level visibility for me and my team to have special privileged access to these things in the same module, but which one outside of it is allowed to touch. It’s a great feature for large groups of programmers.
I like to think I'm a decently intelligent person. UC Berkeley Mechanical Engineering. I self taught a few years ago and wrote an entire project management SaaS for a certain industry in PHP and jQuery front end. 34 small companies use it.
Even though I once took a highschool C++ course long ago that talked about OOP and made us do a few things with it.....
I still have no idea what OOP really is, and why I need it. Unless I'm using it without knowing, I have a feeling I'm either dumber than I think or people have lost their minds. I can't tell.
Self-taught programmers have an easier time thinking in a simple, direct, solution-oriented way. CS-educated programmers tend to think too much about whether this project gives them an excuse to use fancy things they learned in courses (how can I cram algebraic types into my recipe management program?).
The downside of being self-taught is well-known - you might end up convincing yourself that for loops don't work, strings with more than 10 characters are unreliable, numbers can only reliably be added using BigDecimal, etc.
Self-taught programmer checking in: OOP is about isolating private implementation details, akin to using local variables inside a function. Seems pretty direct to me.
At some point in time "the other people" are going to end up being different versions of Future You :-P . So if you take the "other people" argument, then it's definitely worth learning just for that reason. OO is pretty handy for the You Of Today too though.
The basic low down is that this is all about encapsulation (tidying things away in boxes).
You hopefully already know a bit about that.
Say you just have all globals through all your files, you probably know you end up with a big mess of spaghetti.
To help with that, you've probably already learned about tidying away code and variables into functions. And you might know that if you have a local variable, it is only visible inside the scope of your function. If you're doing it right, then nothing outside your function will ever directly touch the local variables inside the function, or vice versa.
This makes it really really easy to reason about what happens inside the function, since -with the exception of your parameters and your return- what happens in vegas... uhh... your function, stays in your function. And the inputs and outputs to the function are well defined.
This saves hours and hours of hunting out every last spot that some global was used, just in case it is interfering with something 1000 lines away. If you've done a lot of programming, you've probably been there a hundred times, cursing the laziness of Past You as you went.
Maybe you also separate your program out into different files. Model.php, View.php, Controller.php DoImportantThing.php ... maybe something like that?
So you probably already realize that tidying things away in boxes is a good idea. Everything you can tidy or organize away inside some box is something you don't need to worry about elsewhere at least. Out of sight is out of mind.
Wouldn't it be great if there were more ways to help you tidy things away into boxes? Well, we're in luck. PHP has classes and objects. These are a further way to organize functions and data together into a next-size box.
The idea is to tightly control what gets in and what gets out of these boxes again. And if you do, that's an additional level of things you don't need to worry about constantly. This frees up that part of your mind for other things.
Of course if you're a PHP programmer you don't NEED to use classes and objects. You don't NEED to use anything. But they're a very powerful tool to help you keep your code squared away. And since they're built right in to the language already, right at hand, why wouldn't you use them?
Classes and objects make most non-trivial projects easier and quicker to write (especially if you can reuse old classes, which you often can!) , and they make medium to large projects rather more manageable and tractable.
If you poke me, I could find some time to show you how you can make classes and objects work for you?
[disclaimer: Classes and Objects are definitely not the first/last/only/best/worst tools to organize code. Different languages have different tools sometimes. PHP just happens to provide Classes and Objects, so that's what you've got to work with there.]
I really appreciate your offer regarding PM, and the time you took to write that post. As you figured, I have learned those easier parts of not making things global, writing functions, separating files, all that. The way you explained it does make it clear that OOP could be the next step in helping me keep my sanity and my code clean. Since writing this post I looked up a few explainer videos regarding OOP and somewhat get it now.
I somehow get the feeling that if you do a good job with functions, it's almost working the same way. But I'm sure there's still parts I'm missing.
I appreciate your offer but I don't think it's fair to use your time when I haven't personally tried to use the countless resources explaining OOP that are available online.
I'll look into them so I know what the possibilities are when I work on my next project.
Thank you for the response.
Which you can do with modules in Python, so the particular utility of classes gets increasingly hard to tease out.
One neat use of classes is model objects in scikit-learn. But R manages to do the same thing with a much more basic system called S3. In this system, you have "generic" functions which dispatch to different methods based on the data type of the first argument. This is used to endow the programming environment with predict and plot functions that behave differently depending on what kind of model you feed into them. This is essentially the same as how two different OOP classes can have two different methods with the same name. But S3 has none of the other trappings of object-oriented programming whatsoever: no encapsulation, no inheritance, no polymorphism.
I found it a fascinating revelation. It's hard to point to anything that R's object system makes unnecessarily difficult, any killer app that proves how pure OOP is better. I would guess that traditional OOP excels in GUI systems, but outside that context, people seem to increasingly find it wanting as a paradigm. We are seeing an evolution away from unipolar OOP ideology and towards a more multipolar exploration of different paradigms and their comparative advantages.
Many content on that website is straight up ridiculous claiming shit like gcc, any format, everything more complex than a rock basically is harmful, so I’m not sure it helps your case.
But I can agree with the Carmack quote, but that in itself doesn’t contradict OOP’s supposed benefits.
Object oriented programming is quite simple in theory.
Say you want to draw a window, it's one of many windows in your program. You could either write out the code to draw a window each and every time you want to draw a window, but that's probably inefficient at best and a nightmare to maintain at worst.
So you instead write a generalized class to draw a window. You then invoke that class as a new object when you want to draw a window, and pass to it any information unique to this particular window (eg: dimensions, contents).
This means the code to draw a window only exists once in your program. If you need to change how windows are drawn, you only need to change the one class instead of thousands of instances of drawing windows.
In essence, any action that you are likely to repeat many times in a program benefits from object oriented programming because it centralizes the code in one place and is abstracted away when the time comes to use it.
By contrast, if a given action is something a program would only do once or at most very seldomly, object oriented programming starts to lose importance because there's little value in centralizing and abstracting away a piece of code that will only ever execute once anyway.
> In essence, any action that you are likely to repeat many times in a program benefits from object oriented programming because it centralizes the code in one place and is abstracted away when the time comes to use it.
This isn't really the unique benefit of OOP. Plain functions also centralize code in one place and allow you to avoid writing repetitive code.
To make it more OOPy you would probably give a few instance variables to the window like width, height, title, etc. That way, a simple drawWindow function would not be a better replacement anymore.
I think this is why some people call software development software engineering. If you don't take into account a lot of different things and engineer for stability and maintainability it can become a headache in the future. It may be simple and direct, but I wouldn't feel comfortable crossing a bridge made of 2x4s and plywood that was slapped together in a weekend and it would just make more work for someone else down the line because it probably wouldn't last very long.
I imagine it all depends on what the use case it. If your bridge is for hikers and mountain bikers, that seems fine and the best use of the local resources for trail maintenance. You could definitely hire some professionals to build a bridge that a tank or 18wheeler could cross over, but it might be a bit overkill. Would be impressive though!
As mostly self-taught, I found that OOP makes more sense when you're working with many people and to simplify organization boundaries you deal with interfaces on abstract objects. Your team owns a window which calls click() on something owned by another team that implements IWindowControl. That IWindowControl interface is something you agree upon, but the internals of each object are invisible to each of you.
PHP (and JavaScript for that matter) historically did not have a good implementation of OOP, nor a culture around it. As far as I know, things have changed on that front, but it certainly does not surprise me that you were able to deliver a PHP product without touching it.
Doesn't mean that you're dumb or that other people lost their minds. My guess is you haven't given it a serious go, which is fine if you don't have a need for it. I personally find OOP fantastic for large codebases with multiple people working on them. Makes code a lot more maintainable and easier to reason about. The downside is that folks without a strong sense of architecture can get carried away with enterprise patterns and end up with abstractions on top of unnecessary abstractions. The basic tenets of OOP should be easy to understand if you just spend some time on it, though benefits can be hard to see if you haven't experienced procedural spaghetti code.
I think JS had a perfectly reasonable and workable OOP implementation, actually pretty elegant, but so different from the C++/Java class paradigm that almost nobody used it the way it was supposed to be. Instead, JS Objects were treated like broken Java classes, which led to all sorts of problems.
Uncle Bob argues that the point of OOP is dependency inversion. That is, your core logic doesn't know exactly some of the methods that will be called and some of the data structures that will be involved at execution time. Instead, those can be provided externally, which will make the logic resilient to code rot. Sounds like polymorphism, interfaces and method signatures.
I'm in the same boat, but not self-taught. I used to knew OOP. It was so obvious, you just made classes of things with methods to do actions. Then the things could be inherited from to create sub-category objects to be acted upon.
Then I read some articles. And I read forum posts. And I read comments. And I read OOP doesn't need this or that. I read multiple people define OOP in many different ways. Now I don't know how to define OOP.
I thought I could "know OOP if I saw it". And then I wrote code. I wrote in procedural languages. I wrote in functional languages. I wrote in declarative languages. I wrote in languages that like to blur the lines between them. And now I don't really know where the lines are. It all is just "programming".
Answering the question: "What is Object-Oriented Programming" used to be so easy. Now I don't know.
Having worked with physical models that store state in memory during simulations, I assure you that OOP has its place and works very well.
Without OOP, we quickly get into codebases much like JavaScript where every new framework attempts to reinvent the same thing in even more contrived ways.
The only place where OOP style doesn't make sense is in stateless programs, which a lot of web backends are (but even there, it's often useful to hold connections and to create good interfaces).
Don't let your code in any language go down the JavaScript framework path.
OOP is just a buzzword. There's no clear meaning behind "OOP" as far as I see, it's not even close to being well-defined, it just serves to confuse and fuel pointless discussions and arguing about semantics (see this thread, for example).
"OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things." – Alan Kay
Simula was the first language to have objects but Alan Kay's Smalltalk was what really caused it to take off and is what most OOP languages today were derived from. Today he feels he mis-named it and that he should have called it Message-Based Programming, which is what he feels should be the primary focus of languages with objects.
Most OOP languages today are not message-based and do not offer the full benefits of message-based programming. A few that do are Self, Ruby, and Erlang.
The reason OOP seems like a buzzword with no clear meaning is because there are so many languages that implement OOP only partially and not always the same parts.
I model systems that naturally have block diagrams (modulators, phase locked loops, power amplifiers, channels...). I came to an object oriented approach relatively late, but I would not go back. I don't know about general software, but for simulating physical systems it seems ideal.
It's important to note that there are two schools of OOP that often get conflated and muddy the waters of understanding. On the one hand is the one evidenced in the OP and C++, where OOP is mostly an organizing principle and function calls are bound early. On the other side is the Smalltalk school, emphasizing message passing and late bound everything, which is slower but a lot more dynamic and flexible, as best laid out by Kay in his famed email [0]. At this point, object-oriented programming is about as precise a term as socialism (and equally likely to start a flamewar).
Taken to a basic extreme, OOP is basically extensible modules.
Just pick a modular language like Modula-2, and add the capability to store module instances into variables, and extend them from there.
Polymorphism and dynamic dispatch at their root are plain function pointers, and anything else is just syntax sugar to avoid manually dealing with them.
Languages like Oberon or Lisp show how minimal the language has to have native support for OOP features, while still supporting most of its concepts.
106 comments
[ 3.3 ms ] story [ 166 ms ] threadAs for the handwaving about simulation & modelling and We Must Design The Matrix and all that nonsense... not applicable to most programming.
OOP helps encapsulate state to make it more manageable.
I am starting to reject OOP because I find working at reducing state is much more fruitful than encapsulating it.
But eventually a junior developer realizes that a Triangle is an PolygonalOpenFrameMetallicPercussionInstrument and it now has 4kb of private state, 307 inherited member functions, and floods your console when its logged.
I love OOP, but caution is indeed warranted.
In fact "composition over inheritance" is a thing in the OOP world.
https://en.wikipedia.org/wiki/Composition_over_inheritance
You don't know how much memory an object of a given type takes to instantiate. This makes object allocation slower. This also means that you can't allocate a Vector<T> inline. It has to be a vector of pointers.
You don't know what fields a type has. This makes GC scanning more expensive.
You can't optimize the layout of a type. If you know an object doesn't have subtypes, you can move it's fields around to reduce padding. If you want to be able to look up fields quickly, you need to put all the fields of the supertype first in memory which will increase the size of your objects.
On OOP languages with GC, you can reduce GC scanning by having precise GC, and if the languages support value types by making use of structs with method pointers.
With the help of PGO for AOT or the JIT, the compiler can optimize the layout of types for the target architecture.
Inheritance x composition is orthogonal to OO.
My issue with `this` and things like it is that the first argument (the 'object') is usually the most important thing, and it's easier to read methods if they have a name.
Ok, you can call this deixis but do you need to? Clearly not.
I think it's fair to skip over a comment using terminology you find tiresome, be it because you aren't familiar, or you find it irritating for some reason, or for any reason; it's your time. I think it's unnecessary to insist we all use the same terminology, as that just limits what conversations can be had and who can have them. One of the things that makes HN feel magical is when people from a weird discipline jump in to give their two cents, and they add value to the community when they bring their terminology with them.
This does not mean that we need to dumb things down, but if OP can not explain things in a simplified matter, I'd take it as a signal that OP's criticism at best as non-practical and at worst as pseudo-intellectual BS.
Dismissing someone for using different terminology is dismissing someone who could surprise you or teach you something new because you don't like the aesthetics of their speech and you aren't willing to put in the effort to understand them. If you don't want to spend your time that way I understand, but why is that a stance? Why isn't that just how you've prioritized your day, without making it a moral judgement about the quality of their speech?
> This does not mean that we need to dumb things down, but if OP can not explain things in a simplified matter, I'd take it as a signal that OP's criticism at best as non-practical and at worst as pseudo-intellectual BS.
What you're saying here is that you'd rather rely on this heuristic to dismiss what they have to say, then figure out whether what they say has value. And you do you. But this isn't a reflection on anyone other than you. It isn't a criticism of their statement. You're kinda cheating yourself. You've just decided that along this certain axis, your thinking is done expanding and you have no more to learn. And that's unfortunate, I hope you'll reconsider because there's a lot of richness there.
I didn't say that the type of speech alone is enough to dismiss the argument. I am saying that resorting to terms more complicated than needed hinders communication.
If "words are tools for thought", OP is using the wrong tool and you are jerking off to someone who is employing a (overtly fancy) chisel to sand a block of wood.
(And yes, I did read up on the terms. His criticism is still vague and does not seem rooted in actual experience as a programmer, teacher or programming language designer.)
This being precisely why I found it to be a fresh and interesting viewpoint; I've heard a lot from programmers and language designers on this topic, I hadn't heard from linguists before. I found their use of different tools of thought than I had seen applied to this area intriguing and it made me see things in a different way; you seem to have interpreted this as "using the wrong tools" because they weren't the ones you were used to. This is exactly what I was saying; you're limiting the conversation to an insular set of perspectives.
You've bought my premise about what you're saying, and in lieu of justification you've provided some cheap insults. I'm glad we understand each other.
> I hadn't heard from linguists before.
Are you sure? Larry Wall, creator of Perl, is a linguist. His education certainly guided his decisions when designing the language. He certainly had different "tools of thought" compared to other programmers at the time, and it shows. You can hear him multiple talks and read books from him about the topic, and none of them are filled with out-of-context, unnecessary jargon.
Terms?
"I think you meant 'words' which I also find annoying, but don't feel the need to dress that up in fancy words."
I don't feel the need to blunt precise terms down to imprecise terms.
If I did find "fancy terms" annoying, I wouldn't be proud of nor advertise that.
People are neither allowed to use their preferred terminology nor disagree with you? That's really the experience you're going for? Why?
It's nonsense though because this/self is barely more than syntactic sugar for what C programmers do anyway - in fact languages with UFCS let you choose arbitrarily. Writing free functions with `this` as the first parameter doesn't really change anything.
0. https://www.tech.dmu.ac.uk/~mjdean/notes/modules/education/E...
Concurrency, syntactic sugar, object oriented, monotonic clock, these all sound like babble to someone uninitiated as well.
Of course this was inevitable given the place orientated von Neumann architecture (the tape, with its distinct locations). Much as OO practitioners like to think OO is special or deep in some sense, it is in fact just a conceptual hack to accommodate the inherent clumsiness of our particular adding machines, dressing their flaws in fancy clothes to hide our shame. If it wasn't for C pointers, programmers would think OO was some sort of nightmare fuel from another dimension.
Traits and type classes are a much better solution that offer far more flexibility, yet still allow the programmer their own balance of expressiveness and rigidity.
Of course data can have defined behavior. Don't try to marshall it into genetic lineages of parents and ancestors. That's an orthogonal and entirely made up problem.
The whole abstract factory generator class iterator thing I see in other languages scares the bejeezus out of me.
Isolating some kinds of state in more manageable units can be very handy while remaining maintainable.
Even inheritance can be nice under the right circumstance.
Object oriented programming? An unmitigated disaster.
It's probably best to start off a solution with plain old data structures, and plain old functions (ie. procedural style). Build with that until right abstractions or separations emerge.
This can only become a problem if you pay little to no attention to modularization, software architecture, and even encapsulation.
The responsibility of a paradigm and a language is to allow a developer to freely express their concepts. The programming paradigm is not to blame if the developer chooses to express poorly thought-out ideas that are riddled with detrimental consequences.
You're giving the textbook example of problems created and solved by putting together a working software architecture. Books like Bob Martin's "Clean Architecture" refer explicitly to needs to accommodate changes to business and application layers, and the need to design components to accommodate changes, and the book is language-agnostic.
My point is it’s easier to modularize and encapsulate properly with procedural or functional paradigms because they don’t force you to do that work before you start solving problems. The dev flow is: solve problem, then modularize. With OOP, the flow is: modularize, then solve problem.
I’m simplifying and of course you can architect correctly upfront, it’s just harder because you’re doing speculative generalization (akin to premature optimization).
That's a poorly put-together red-herring. Brainfuck is not one of the leading production programming languages that has been used for decades to write all sorts of applications, from operating systems to web services and specially desktop applications, AAA games, and high-performance computing. Brainfuck is a gimmick "esoteric" programming language used as a challenge.
> My point is it’s easier to modularize and encapsulate properly with procedural or functional paradigms because they don’t force you to do that work before you start solving problems.
The thing is your point does not hold at all. It's trivial to modularize and encapsulate and even isolate components with C++. You only need to want to do it. If you don't want to modularize or encapsulate or isolate components then you get what you want. Don't blame the language for the software architecture you chose to adopt for your project.
First you backtrack your generalization regarding languages, which makes one ask what other omitted features have to be present to rely on the statement.
Second you're not supporting your claim "It's trivial to modularize and encapsulate and even isolate components with C++. You only need to want to do it." It directly contradicts the observation that programs, when written, are often found to be designed incorrectly, and it's important that the language would support enough their recomposition. Just wanting to make a good architecture doesn't make it right all by itself, sometimes you have to change already existing things, and how easy it is has a lot to do with the language.
I think that "freely" is what GP is complaining about; that OOP practices limit your freedom by encouraging early lock-in and making past decisions hard to revisit in light of new facts.
I'm not sure I entirely agree, mind you, but I do think you're in more agreement than disagreement.
I've tried everything but my favored approach these days is just to stream of conscious psuedocode in main() to get the shape of what needs to happen, and then backfill until there's something working. Once I know what I want, only then do I break things up so that everything is in the right place. It seems to end well every time.
tl;dr: bottom-up, and top-down are too extreme!
You could apply TDD at this point. Doesn't have to be before you write a single line of code.
Programming to an interface, composition, immutable classes and objects as fancy closures that can do more than one thing: Drake-yes-please.jpg
Inheritance for code sharing: Drake-no-thanks.jpg.
One thing I really miss from my Java days, and which I don’t really think has anything to do with OOP, is the concept of package visibility. Private data for the class itself. Protected data for inheritors if you dare have them. Public for anyone using your library. And package level visibility for me and my team to have special privileged access to these things in the same module, but which one outside of it is allowed to touch. It’s a great feature for large groups of programmers.
C++ has that in the form of internal linkage. You can have all the symbols you want that are only visible within your own translation unit.
Even though I once took a highschool C++ course long ago that talked about OOP and made us do a few things with it.....
I still have no idea what OOP really is, and why I need it. Unless I'm using it without knowing, I have a feeling I'm either dumber than I think or people have lost their minds. I can't tell.
The downside of being self-taught is well-known - you might end up convincing yourself that for loops don't work, strings with more than 10 characters are unreliable, numbers can only reliably be added using BigDecimal, etc.
The general answer seems to be that OOP starts really helping when many people/teams are involved.
Being self taught and a one person team I suppose hasn't forced me into it yet.
The basic low down is that this is all about encapsulation (tidying things away in boxes).
You hopefully already know a bit about that.
Say you just have all globals through all your files, you probably know you end up with a big mess of spaghetti.
To help with that, you've probably already learned about tidying away code and variables into functions. And you might know that if you have a local variable, it is only visible inside the scope of your function. If you're doing it right, then nothing outside your function will ever directly touch the local variables inside the function, or vice versa.
This makes it really really easy to reason about what happens inside the function, since -with the exception of your parameters and your return- what happens in vegas... uhh... your function, stays in your function. And the inputs and outputs to the function are well defined.
This saves hours and hours of hunting out every last spot that some global was used, just in case it is interfering with something 1000 lines away. If you've done a lot of programming, you've probably been there a hundred times, cursing the laziness of Past You as you went.
Maybe you also separate your program out into different files. Model.php, View.php, Controller.php DoImportantThing.php ... maybe something like that?
So you probably already realize that tidying things away in boxes is a good idea. Everything you can tidy or organize away inside some box is something you don't need to worry about elsewhere at least. Out of sight is out of mind.
Wouldn't it be great if there were more ways to help you tidy things away into boxes? Well, we're in luck. PHP has classes and objects. These are a further way to organize functions and data together into a next-size box.
The idea is to tightly control what gets in and what gets out of these boxes again. And if you do, that's an additional level of things you don't need to worry about constantly. This frees up that part of your mind for other things.
Of course if you're a PHP programmer you don't NEED to use classes and objects. You don't NEED to use anything. But they're a very powerful tool to help you keep your code squared away. And since they're built right in to the language already, right at hand, why wouldn't you use them?
Classes and objects make most non-trivial projects easier and quicker to write (especially if you can reuse old classes, which you often can!) , and they make medium to large projects rather more manageable and tractable.
If you poke me, I could find some time to show you how you can make classes and objects work for you?
[disclaimer: Classes and Objects are definitely not the first/last/only/best/worst tools to organize code. Different languages have different tools sometimes. PHP just happens to provide Classes and Objects, so that's what you've got to work with there.]
Yes. A lot of what people profess about the "clean" ways to write OOP is essentially just the same as using Functions with Namespaces
One neat use of classes is model objects in scikit-learn. But R manages to do the same thing with a much more basic system called S3. In this system, you have "generic" functions which dispatch to different methods based on the data type of the first argument. This is used to endow the programming environment with predict and plot functions that behave differently depending on what kind of model you feed into them. This is essentially the same as how two different OOP classes can have two different methods with the same name. But S3 has none of the other trappings of object-oriented programming whatsoever: no encapsulation, no inheritance, no polymorphism.
I found it a fascinating revelation. It's hard to point to anything that R's object system makes unnecessarily difficult, any killer app that proves how pure OOP is better. I would guess that traditional OOP excels in GUI systems, but outside that context, people seem to increasingly find it wanting as a paradigm. We are seeing an evolution away from unipolar OOP ideology and towards a more multipolar exploration of different paradigms and their comparative advantages.
http://harmful.cat-v.org/software/OO_programming/
"Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function." – John Carmack
Unfortunately, many college-educated programmers have been taught OOP design ideology and profess it uncritically.
But I can agree with the Carmack quote, but that in itself doesn’t contradict OOP’s supposed benefits.
Say you want to draw a window, it's one of many windows in your program. You could either write out the code to draw a window each and every time you want to draw a window, but that's probably inefficient at best and a nightmare to maintain at worst.
So you instead write a generalized class to draw a window. You then invoke that class as a new object when you want to draw a window, and pass to it any information unique to this particular window (eg: dimensions, contents).
This means the code to draw a window only exists once in your program. If you need to change how windows are drawn, you only need to change the one class instead of thousands of instances of drawing windows.
In essence, any action that you are likely to repeat many times in a program benefits from object oriented programming because it centralizes the code in one place and is abstracted away when the time comes to use it.
By contrast, if a given action is something a program would only do once or at most very seldomly, object oriented programming starts to lose importance because there's little value in centralizing and abstracting away a piece of code that will only ever execute once anyway.
This isn't really the unique benefit of OOP. Plain functions also centralize code in one place and allow you to avoid writing repetitive code.
Using Classes when you should be using functions is one of my biggest peeves with OOP and the programmers who write it.
Especially those who wind up writing a "Window" Class with one function "draw" and nothing else
Doesn't mean that you're dumb or that other people lost their minds. My guess is you haven't given it a serious go, which is fine if you don't have a need for it. I personally find OOP fantastic for large codebases with multiple people working on them. Makes code a lot more maintainable and easier to reason about. The downside is that folks without a strong sense of architecture can get carried away with enterprise patterns and end up with abstractions on top of unnecessary abstractions. The basic tenets of OOP should be easy to understand if you just spend some time on it, though benefits can be hard to see if you haven't experienced procedural spaghetti code.
Then I read some articles. And I read forum posts. And I read comments. And I read OOP doesn't need this or that. I read multiple people define OOP in many different ways. Now I don't know how to define OOP.
I thought I could "know OOP if I saw it". And then I wrote code. I wrote in procedural languages. I wrote in functional languages. I wrote in declarative languages. I wrote in languages that like to blur the lines between them. And now I don't really know where the lines are. It all is just "programming".
Answering the question: "What is Object-Oriented Programming" used to be so easy. Now I don't know.
NB: I am from California and I like object oriented programming.
Without OOP, we quickly get into codebases much like JavaScript where every new framework attempts to reinvent the same thing in even more contrived ways.
The only place where OOP style doesn't make sense is in stateless programs, which a lot of web backends are (but even there, it's often useful to hold connections and to create good interfaces).
Don't let your code in any language go down the JavaScript framework path.
Simula was the first language to have objects but Alan Kay's Smalltalk was what really caused it to take off and is what most OOP languages today were derived from. Today he feels he mis-named it and that he should have called it Message-Based Programming, which is what he feels should be the primary focus of languages with objects.
Most OOP languages today are not message-based and do not offer the full benefits of message-based programming. A few that do are Self, Ruby, and Erlang.
The reason OOP seems like a buzzword with no clear meaning is because there are so many languages that implement OOP only partially and not always the same parts.
0. http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-...
Just pick a modular language like Modula-2, and add the capability to store module instances into variables, and extend them from there.
Polymorphism and dynamic dispatch at their root are plain function pointers, and anything else is just syntax sugar to avoid manually dealing with them.
Languages like Oberon or Lisp show how minimal the language has to have native support for OOP features, while still supporting most of its concepts.
The Actor model seems to fit well with OOP also.