61 ms·
Why OO Sucks by Joe Armstrong (2000)
- jasonhansel 8y agoWorth noting that most of these criticisms also apply to existential types, which are fairly common in functional languages (e.g. Haskell).
- kjeetgill 8y agoUnfamiliar with Haskell. What are existential types.
- l_dopa 8y agoThat's not entirely accurate. Abstract data types (e.g. ML modules) can also be modeled as existential types and don't have the same problems. I think it's the particular combination of only having nominal typing, only allowing the oo-flavor of data abstraction, and encouraging programming with state and using inheritance for code reuse that leads to the object-spaghetti nonsense in heavily-oo Java/C++ codebases.
- jasonhansel 8y agoI just mean that (at least in Haskell) existential types provide information hiding & combine functions with data. In fact, they're implemented with dynamic dispatch, just as with OOP. The problem is not that OO languages have these features; the problem is that they lack other features common to functional languages.
- mises 8y agoI think this may be another one of those swearing-in-church type opinions, but I think C++ is excellent as a compromise here. It's got its faults, but C++ allows use of objects when necessary or helpful without the ridiculously pedantic OO of Java. It is quite nice to be able to use it when convenient while not having to do so when stupid.
- tyingq 8y agoIt's one of many languages where OO is optional.
- mises 8y agoThere are other reasons I like it: huge library support, ability to do low-level stuff for performance but use higher-level features for an easier time, etc. Mostly, I've yet to see something better that has the maturity, libraries, depth of talent (!), etc. that doesn't have problems of its own. It's certainly not perfect, but there are reasons it has remained so popular in many fields.
- musingsole 8y agoI'd extend the same argument to Python
- mises 8y agoI can't speak to python as much, as I haven't really used it, but I've heard a lot of good things about it (recently read a comment saying it was simply good at nothing but good enough at everything).
- QuackingJimbo 8y agoYou getting downvoted for this completely inoffensive (at worst) comment is pretty sad I swear C++ gets a bad rap because most people have only seen a gross mixture of C++98 and C in their codebases A fully modern C++11 codebase is a beautiful thing
- bhaak 8y agoWhy are you so sure the downvotes are not coming from the opinion of the "ridiculously pedantic OO of Java"?
- mises 8y agoMaybe because no body had commented as such until now? I am rather practical about this: I don't really like Java because it forces things that make more sense as functions to be under an object. What if I just want a simple global utility function, and don't want to make every single class inherit from a class containing only that? It's a lot of unnecessary hassle for something like that. I'm not saying OO is bad, I said it was too pedantic. I like languages which allow you to do what makes sense.
- hartator 8y agoThe thing is ‘filename’ is a bad example for a an object. Of course, it should be a string. However ‘File’ object is a better example that favors OOP. When you call ‘.read’ on a file object, you expect its content. It doesn’t matter if it’s a windows file, unix file, an IO string, or a web resource. When you call ‘.read’, it just work. Whereas in the functional world, you’ll have to 4 different ‘.read’ function calls with an if statement.
- incompatible 8y agoI think you could use a curried read function, in this case. The read function would be passed as an argument instead of your I/O stream. I fear I've slipped somewhat into OO habits by using Go interfaces.
- pacala 8y agoExactly right. "Polymorphism" is nothing more than passing a function [or bunch of functions] as argument[s] of another function.
- deleted 8y ago[deleted]
- SamBam 8y agoBut wouldn't you have four different read functions in your OOP example anyway, just each in it's own object?
- rifung 8y agoIt's unfortunate you're being downvoted for your opinion instead of having other ideas presented to you so I'll do my best though I'm no expert. > Whereas in the functional world, you’ll have to 4 different ‘.read’ function calls with an if statement. You could do this but that's not idiomatic. What you would preferably do is have a function that takes a read function as a parameter. This is essentially the same thing as what OO languages implicitly do. For an example of generic functions you can take a look at map or fold/reduce. You'll see they don't need to use if statements in the way you described.
- keithnz 8y agoEverything sucks, they just all suck differently. I still think OO provides a pretty easy mental framework for programming. You can get good results. Bit of discipline without going crazy and it works really effectively. Despite its shortcomings.
- tootie 8y agoOO is the worst programming paradigm in the world except for all the others.
- markdog12 8y agoThis is a decently clever Churchillian quip. At the very least, it does not deserve downvotes.
- tombert 8y agoAdmittedly I'm somewhat of a FP fanboy, but I seriously cannot disagree with you more on this. Functional Programming (and Logic Programming) are better than other paradigms because, unlike Java (or C++, or C#...) there is an emphasis on correctness, and the people working on FP compilers (like Haskell and Idris) are utilizing mathematics to do this. No idea on your opinion on mathematics, but to me Math/Logic reign supreme; the more mathematically-bound your program is, the less likely it is to do something you don't want later. Compare this to Java. It's 2019, and we're still doing `if (x==null) return null` all over the place (I'm aware that the option type exists but that doesn't really help when it's not enforced and none of my coworkers use it). How about having to create six different files for something that I could have written in 20 lines in Haskell? Or how about the fact that the type system exists to help with optimizations, and due to a lack of support for structured typing, it can only be useful for that. I realize that I'm picking on Java, but Java is the biggest target when it comes with OOP as the industry understands it. I personally cannot stand having to create fifty files do to something like a database wrapper, and in Java that's effectively the only way to program.
- libria 8y ago> How about having to create six different files Took me a few reads but it's better stated "six different classes". At first I was confused about why you rely on `java.io.File` for business logic. So, if I'm stuck on JVM, what's my FP alternative that compiles and runs comparatively? Clojure? Scala?
- peterashford 8y agoI'm really sick of these 'why blah sucks' posts. Clearly OOP works for a lot of people. If it doesn't work for you, don't use it. My personal feeling is that FP works better when the problem domain is more data oriented, requiring transformation of data streams whereas OOP is good when the problem domain is about simulating or modeling where you want to think about interacting agents of some kind. The whole 'X is one true way' argument is narrow sighted. I feel the problem should always precede the solution
- chx 8y ago> If it doesn't work for you, don't use it. How many of us actually get a choice in this...?
- k__ 8y agoAlso, for how many does it really work? I mean, most devs don't really know anything else, just accept it and try to get by...
- mikekchar 8y agoI wonder if it would be constructive to modify the OP's statement a little bit. You can get there from here using any approach (as long as it is Turing complete ;-) ). Some approaches will work better than others, but optimising your approach first and convincing others second is putting the cart before the horse. Having a happy team that works well together is going to provide at least an order of magnitude more ROI than choosing the best approach. Compromising on your approach to make others happy will almost certainly pay off hugely. Get good at as many types of approaches as you can so that you can take advantage of those payoffs. The cult of "I must use the absolute best approach for this problem, everyone else be damned" is one that leads to misery IMHO (especially if it turns out that your "best approach" isn't, which happens most of the time in my experience ;-) ).
- shortoncash 8y agoThese days many languages are so expressive you can establish a dominant paradigm in the part of the code you work on. We have a kind of micro-level choice that even the most authoritarian code-reviews can't largely stamp out (provided that the interface you provide is in harmony with the rest of your organization.)
- graycat 8y agoI don't mind object oriented programming too much: Occasionally, at most a small fraction of the time, it helps me write good code, and then I use it. Otherwise I don't. Here are some of the things I'd like to see in programming languages: (1) Some semantics that admit some useful static analysis, that is, tell me some useful things about my code, e.g., for a variable, where does it get used and where might it get changed? (2) Offer me some useful code transformation properties. For this, a start is the relatively powerful scope of names constructs in PL/I: There can just drop into the source code another function and know that in the more common and important respects that function being there won't hurt anything else already there. So, if I have some function I like for something or other, then I can just drop it in. There's a lot more: The main point is just to try, so that given 100,000 lines of typing of code, some tools can tell me where the lines of spaghetti and the meatballs are!!!! So, that code is a system and treat it as such, i.e., instrument the thing and tell me what is going on, both statically before it runs and as it runs.
- jasoneckert 8y agoI definitely C the arguments he makes, and agree with them.
- billconan 8y ago> Objection 1. Data structure and functions should not be bound together I don't understand the above: a. functions do things, b. objects don't do things, therefore, we shouldn't combine them together? Why? I'm not convinced? what's the logic? doesn't seem to be a strong argument to me. factories make things. warehouses don't make things. so we should build them together?
- crubier 8y agoWe should be forced to combine them together.
- vhb 8y agoWell, I disagree with 99% of this... I'm a guy that started with C, moved to functional programing, added C++, and now do all 3. > Objection 1. Data structure and functions should not be bound together Well, in my experience, in every almost every code-base (either from functional, or imperative programing), we end up with modules, witch are a set of function taking the same type as a parameter. This is very close to binding the functions and the types... > Objection 2. Everything has to be an object. I don't get the example. The only thing that this show, is the benefits of having a range type built in the language. Then it's just type aliases. "There are no associated methods.", yes, but you will need functions to manipulate those types (just translate one type into another), at the end, it's going to a module, which is almost an object. > Objection 3. In an OOPL data type definitions are spread out all over the place. That's true. It also makes thinking about the data layout complex. That's why other paradigm have been developed (DOP), on top of OOP. Now you can also think that having those defined together makes dependency management easier. > Objection 4. Objects have private state. False. Objects can have a private state. This a problem with mutability, not oriented object programing. You can have non mutable OOP. > Why was OO popular? >> Reason 1. It was thought to be easy to learn. The past 20 years have shown how easy it is. In fact, I actually think it's too easy, people rely too much on abstraction, without even trying to understand what's going on. I my opinion, it promotes a lazy mindset (This is my biggest criticism about OOP). >> Reason 2. It was thought to make code reuse easier. I would like an evidence that it's not. >> Reason 3. It was hyped. True, but that does not make it bad. People tried to hype every technologies... Some stayed, some went away. >> Reason 4. It created a new software industry. How has OOP created a software industry that would not have existed if functional programing had "won the fight"?
- mikekchar 8y agoI pretty much agree with your statements, but I'd like to take a stab at: >> Reason 2. It was thought to make code reuse easier. > I would like an evidence that it's not. Mainstream OOP approaches achieve better cohesion by coupling data structures to functions. In the worst case you end up with essentially modules that contain "global variables" local to that module. In other words the only reason to have your instance variables is to remove the need to pass those variable to the functions as parameters. This hurts the ability to write generic code. In fact you see this problem all the time in OO code. You have a base class and a bunch of basically unrelated child classes. It's not so much that the child ISA base, it's more that the child ACTS_AS_A base. But then, you run into all sorts of problems because one child (because it is using very different data structures) requires specialised code. There are ways of getting around this, but often those ways end up encouraging you to implement an alphabet soup of design patterns that interact with each other -- causing more coupling rather than less. All for the want of a generic function. IMHO OO is actually a poor vehicle for achieving code reuse. In fact, aiming towards this goal is usually one of the root causes I find in really poor OO designs. What OO is really good at is separating concerns and building highly cohesive code. This sometimes comes at the cost of increased coupling which inherently reduces reusability. I don't actually think that's a bad thing when used appropriately, but the old school "OO creates reusable code" is just a bad idea IMHO. It's the kind of thing that several of us threw out the window in the 90's along with large inheritance hierarchies -- nice idea, but didn't work out in practice.
- dang 8y agoThis doesn't contain his most famous line on the topic: You wanted a banana but what you got was a gorilla holding the banana and the entire jungle. https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/ https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/
- freddie_mercury 8y agoWhy would a post written before 2000 include a quote from an interview done in 2008?
- dang 8y agoIt wouldn't!
- apoph3nia 8y ago> If you want to reuse (or test) a functional banana, you don’t have to set up a stateful gorilla to hold the banana first. ...& if you don't want the stateful gorilla?
- S_A_P 8y agoI agree with a lot of the arguments made in this post. However I think there is an assumption that programming is programming and there aren’t different problem sets to solve. To me, UI development lends itself naturally to the everything is an object paradigm. I need a button to start event x. Hmm the button needs to know what size it is and other miscellaneous attributes about itself. Oh it also should have a function that handles what to do when the button is pressed. Hey that sounds a lot like an object that has state, data structure and functions all in one. Now as we traverse the environment to basic CRUD type applications, OOP can be overkill. If all you want to do is pull x number of rows out of a database and put them in a dataset, do we really need objects for this? Nope. Most of the time the objects for these types of problems are just wrappers around an array of pointers. Creating DAO type objects is a lot of the time more trouble than it’s worth, but if were already in an OO paradigm, why switch?
- namelosw 8y agoThe biggest problem of OO languages for me is - it always depends. Composition or inheritance or template or concrete? It depends. Extract methods? It depends. Design patterns? It depends. Although to master good OO design - knowing what and when to do something - is surely an art, it doesn't handle dynamic business model very well. If I just express the business, I cannot handle requirement change. If I want to deal with some future change, I have to do a lot of non-business oriented design, making the code less expressive. And most of the OO language don't have algebra data types, which makes expressing business model more awkward.
- ganonm 8y agoI think this article is quite old, so I can forgive the author for being out of touch with modern OO language practices. Nonetheless, I find myself disagreeing with almost all of his arguments. When he talks about state for example, I assume he means mutable state. Everyone knows this is best avoided if possible. The vast majority of OO languages provide mechanisms to avoid mutability e.g. data classes or keywords to make references constant. He also rails against private state specifically. I assume again that he means private mutable state. This is generally a bad idea and is accepted pretty uncontroversially as a bad idea. The principle of data hiding in general however is definitely not a bad idea. Being able to enforce scoping rules on classes/functions/members is not meant to facilitate creating 'black box' entities whose internal mutations are difficult to reason about, but is instead meant to provide guarantees about dependencies between different parts of a system, i.e. Separation of Concerns. Regarding 'everything is an object', in many cases this is perfectly acceptable as it guarantees some sort of basic interface that all entities conform to e.g. being able to ask an entity to provide a hash code, or to carry out a comparison check with some other entity. Some modern languages like Kotlin even eschew the concept of primitives altogether and just make everything an object. Finally, regarding his point about OO languages having data type definitions all over the place, I must be misunderstanding something here... Why on Earth would you want all your data type definitions in one place? Anyway, just wanted to give my $0.02 lest anyone get the impression that these are 'knockout punches' against any and all OO languages.
- anyfoo 8y ago> provide mechanisms to avoid mutability e.g. data classes or keywords to make references constant. So, functional programming? > guarantees some sort of basic interface that all entities conform to e.g. being able to ask an entity to provide a hash code, or to carry out a comparison check with some other entity. Isn't that terrible? You want to provide a generic interface to calculate a hash or perform comparison: Now the thing has to be an object! If it's a primitive type, you better wrap it in an object now. If it's an existing class, you have to extend it. It becomes an object of a different class. Or, instead, you could just have type classes to let the same apply to anything whatsoever, as long as it's a type, without the need for it to be an object. Heck, in some cases, the type could be a function instead.
- lr4444lr 8y agoIs it just me, or do these web articles written in plain <p> and <h*> tags just have some magical command over your attention as carrying some authority, like the author is so focused on his content that he doesn't a single mental cycle to waste on any more than the bare minimum UI to convey it?
- deleted 8y ago[deleted]
- jrochkind1 8y ago> In an OOPL I have to choose some base object in which I will define the ubiquitous data structure. All other objects that want to use this data structure must inherit this object. So... that's not actually how it works though, right?
- brians 8y agoIt was. Criticisms like this led to implementing hybrid-OO systems. Those are what we now call OO. He’s talking about Smalltalk, Self, that sort of thing.
- jrochkind1 8y agoIn no ever existing OO language do you have to inherit from a data structure to use the data structure, I don't think?
- deleted 8y ago[deleted]
- kbumsik 8y agoI have seen a lot of posts bashing OOP by FP advocates. They write so many points explaining why OOP sucks, however, strangely few of them try to present why and how FP can be better in those points. Most of them assume that FP is unconditionally better in all aspects of coding, so they don't even try to explain. This post is not different.
- zapzupnz 8y agoThey also falsely assume that bad OOP practices in the industry == OOP as a whole, full stop. Arguments against OOP tend to be strawmen arguments. I mean, sure, Java taught bad OOP to millions of developers in the 90s, early 00s, and even today. Sure, the legacy of bad OOP lives on today. That doesn't say anything about the principles of OOP when applied properly, when done in languages that avoid the pitfalls of bad OOP, and when the developer avoids the very patterns that tend to fall into criticism. (incoming FP advocate to call my statement a strawman argument in 3, 2, 1…)
- 0815test 8y agoShould be marked (2000), and the bulk of the text is probably earlier than that.
- Animats 8y agoA few notes: Binding data and functions together beats operating on global data visible to everything. One of the big wins of OOP is less exposed global data. A big problem with OOP in C++ was that it wasn't opaque enough. The headers needed to use an object contain info only useful to the object's private functions. This creates recompile hell. Multiple inheritance is seldom worth the headaches. Overriding a member function needs declaration support. The usual cases are 1) the parent function needs to be called first, 2) the parent function needs to be called last, and 3) the parent function needs to not be called at all. Which case is to be used is properly a property of the parent, but in most OOP languages, it's expressed as code in the child. The use cases for generics are rather limited. Collections, yes. Beyond that, it's usually someone getting cute. That way leads to the "metaprogramming" mess. Go has a few built in parameterized types - maps, arrays, and channels. Go2 may have generics, but the designers are struggling with what to add that doesn't take them down the rabbit hole. Objects are probably more useful than some of the things invented to replace objects, like "traits".
- skybrian 8y agoWhy, what's wrong with traits?
- weberc2 8y ago> Binding data and functions together beats operating on global data visible to everything. One of the big wins of OOP is less exposed global data. “Passing state as parameters” is what solved the “everything operating on global state” problem. Binding functions and state permitted polymorphism/abstraction. > Multiple inheritance is seldom worth the headaches. Single inheritance is never worth the headaches. :) > Objects are probably more useful than some of the things invented to replace objects, like "traits". Traits don’t replace objects; they are interfaces with static dispatch semantics.
- humanrebar 8y agoThere are so many kind of polymorphism. Many of them do not require objects. Executing a closure is a form of polymorphism. As is manipulating a generic type.
- cubano 8y agoThis is so obviously old-school flame bait that I can't understand why we are even discussing it, unless the idea is to go meta with its discussion.
- DonaldPShimoda 8y agoThe author died a couple of days ago in (I think) a bicycling accident. I imagine people are going through his old posts as they remember him or hear about him for the first time.
- lsiebert 8y agoObject oriented programming isn't about an individual programmer. It's about creating discrete APIs so that a bunch of different programmers can work on different aspects or sections of code. It's an organizing principle for discrete elements that encapsulates internal state. You don't need to know your datastore is SQL or Redis, or Redis caching SQL data, or marshalled JSON, you just call Users.getUser(id), and get a User Object with a defined API. OO is in many ways just microservices for a single codebase. I think people ignore the importance of OO in terms of unit and integration testing.
- weberc2 8y agoYou just described abstraction. Abstraction is not specific to OO... The only thing that strikes me as specific to OO is implementation inheritance, and that has been an unmitigated disaster.
- overgard 8y agoDiscrete apis and encapsulation don’t require OO at all. For instance in C you can easily encapsulate things by just not exposing it in the header file. Even things like data structures can be encapsulated by just returning a handle/pointer to a structure and not exposing the structure itself. The only thing OO gets you is embedding functions in the data structure.
- lsiebert 8y agoNot sure where people are getting the idea that I'm saying that OO is the only way to do abstraction and encapsulation. I'm saying it is a way, and a sometimes useful one. Certainly when I'm thinking about a SQL schema, I'm often thinking about it using OO design principles, even though SQL is functional.
- gpsx 8y agoI have a different opinion about why OO was popular. I think it can work well for small programs. But it doesn't scale well to bigger problems. It just becomes too confusing. Once people used it for bigger things, possibly because programs got bigger with Moore's law, it can just be untenable. (But, then again, in some places it still can make sense.)
- abraae 8y agoYou are right, but not wrt small vs large. Instead, OO works well for artificial situations (classic case - UI frameworks) vs. real world situations (classic case - person isa contractor vs. person isa employee). As soon as you start modeling real world situations (like bill being an employee but at the same time working a late shift as a contractor), then you're in the world of complex stuff that single inheritance, multiple inheritance, or anything less than insanely complex relationships requiring tens or hundreds of underlying entities to enact just can't handle. IMO one reason for these fruitlesd ideological arguments -is OO good? Is it bad? - is that OO was originally sold using these real world examples. Which anyone who's worked on a real world system knows is BS.
- lincpa 8y agoFP and OO are overly complicated, and it is not feasible in large industries. It is also a kind of production method that emphasizes personal technology in hand workshops. Personal technology greatly affects product quality and extremely unreliable production methods.FP and OO are actually taking a detour, highly embellished and ineffectual, and produce all kinds of fail. Most OO systems are just simulations of real-world surface phenomena, and the whole system, like a mess, I think it is not good method of OO to simulate the real world, but to design it correctly with an abstract refined data model as a prototype. For example, the ggplot2 of the R language, the system is clear, with the perfect data model as the prototype. So a good OO system is more inclined to a data flow system, and I think Ggplot2 is more likely to be a data-driven plot system if OO was not in vogue at the time. Excessive application of OO and FP design patterns, in addition to increasing complexity and error probability, reduce performance, without any benefit. Complex networks of relationships between objects in the OO system are also difficult to maintain. I tend to construct systems with the simplest concepts and the most basic techniques, syntax, and functions. Used to implement my mind, The Pure Function Pipeline Data Flow is the simplest, stable, reliable and readable.. There is a great poet Bai Juyi in China. even illiteracy understands and appreciates his poetry. I hope that my code can be understood by the junior programmer even in the most complicated system. For me, programming is the process of designing a data model that is simple and fluent in manipulation. More than 80% functions of my project is ->> threading macro code block, each step is simple, verifiable, replaceable, testable, pluggable, extensible, and easy to implement multithreading. The clojure threading macro provides language-level support for PurefunctionPipeline&Dataflow. https://github.com/linpengcheng/PurefunctionPipelineDataflow https://github.com/linpengcheng/PurefunctionPipelineDataflow
- cottsak 8y agoLargely agree with this except the initial objection "Data structure and functions should not be bound together" and the "Why was OO popular?" which is missing the response - because using the notion that "objects" from the real world encapsulate state and behaviour was not only a solid premise, but it was an attempt to interface the computer world with the real. This was not a failed concept. It makes some sense. Just very few teams find the discipline to model their core domain this way. Which brings be back to the original objection. I think this is true most of the time, except when it's not - which is your core Domain Model. The first 1/2 of the Blue Book[1] lays out straightforward means to arrange code, functions, data/state and related behaviours in a way which can be managed and maintained over time. This is pretty important as most folks who've spent any length of time maintaining vast applications will know that it's incredibly hard to reason about a first-class concept in an application without clear boundaries around said concept, it's structures and it's behaviour. Most of us are unlucky and find this scattered across the landscape. Few applications take the focus to "model" these concepts clearly. Does this modelling have to be done with "Domain Model", or DDD, or something else that can be loosely coupled with OOD - probably not. But another developer absolutely has to be able to reason about said structures and behaviour. They have to be able to read it easily and grok it quickly. And having done that, they don't want to be surprised by some distant missing element, 20 calls or 1000 lines or 15 modules (repos, submodules, etc, etc) away! This is possibly the biggest time-sink and therefore "cost" of development. One could also take this further and postulate that about 1/2 of us are employed as a direct result of applications whose core concepts are so poorly designed or hard to reason about, that a massive volume of work (time?) is dedicated to unwinding the ambiguity that results. I don't want to suggest that OOP or OOD/DDD/{other modelling process} would necessarily fix this, but the attempt to clarify and find a means to make modelling these critical concepts easier and less costly is admirable IMO. It's ok if your infrastructure takes a different approach, or is "functional" or "dynamic" in nature. If your test suite uses completely different patterns and paradigms because the tooling makes that easy then - awesome! But if the core model/concepts of your application are hard to understand, reason about, and therefore maintain, then you're pretty fucked. OO doesn't "suck". It's spirit is just largely lost and like many other things in life, it's been hijacked and mutilated into something many of us come to loathe because we've never seen it deliver on the promises. I guess we will be having this conversation again in another decade about something else that's hugely popular right now. [1] https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215 https://www.amazon.com/Domain-Driven-Design-Tackling-Complex...
- ilovecaching 8y agoObjects should be used when you need to maintain invariants between members, or need an opaque stateful "thing" like a resource handle. They shouldn't be used to structure a program, but act like any other type in a functional or procedural setting. An object should also have completely private members and no concept of inheritance. This greatly simplifies thinking about and designing objects. There should be no distinction between a regular and special method like a constructor or destructor. They should essentially be simple constructs with no magic that force interacts with a particular kind of data through functions that maintain the invariants. That's it. That aligns with the message passing origin of OO and Erlang in that there is no "breaking the rules" to get to an objects state. This is basically how they work in Rust and Go. The key in both of these languages is the use of traits and interfaces to obtain special behavior and polymorphism. Neither of them forces a composite type to be completely public or private though, and Go limits visibility to the package level. I used to really hate OO, but I started to think about what the parts I really disliked about it, and saw that in Erlang, Haskell, etc there is always a need for an "object" whether it be a GenServer or a Monad. Java and C++ just took the concept too far, and took an absolutist approach that most features need to be part of the OO machinery, although Java is by far the worst. Objects have their place, but they should be just as common as any of other type, and should not be used to think of program structure in most cases.
- Iv 8y agoThat's a bit weird to see a seasoned programmer harboring those views. I remember that when learning OOP I was equally confused. "I can do all that with functions and structures already." And indeed you can. There is nothing you can't technically do without OOP. OOP is not a programming feature, it is a software engineering feature. It allows for cleaner APIs and higher levels of abstractions. IMO the core feature of OOP is less the ability to bind functions with data but the ability to overload operators. Sure, you can have functions that have the "this" pointer as the first argument and have exactly the same things. You can add a bunch of flags and have the core features of inheritance. You can. Now what do you prefer to write, when finding the middle of a 3d segment? mid = (a + b)/2 or mid = scalar_division(vector_add(a,b),2) ? If you allow operators to be overloard, is there any good reason to not place them close to your structure definition? Isn't it a good practice to force these functions to be defined if your structure is? The core idea of OOP is that it extends the language by allowing to build more abstract concepts in top of lower level abstractions. That's a core misunderstanding that I keep seeing with low-level programmers. They want to see the implementation details of everything and refuse to obscure some behaviors and trust the libs/compiler makers. People who spend more time in higher level algorithms can't bother with all the implementation details. When I do DL, I want the ability to concatenate layers of different types (that inherit the same generic type), be able to check their output(), manipulate tensors of floats, assign them a scalar value or multiply them by some. You can go a very long way without using any kind of OOP and staying at the implementation level. I am actually in awe of how much one can do that way. But OOP is a tool for teams to work together without knowing the details of each other's parts and build increasingly complex abstractions.
- overgard 8y agoThere's nothing about operator overloading that requires OOP. Even in C++ you can overload an operator outside a class definition in a free function. For example... https://stackoverflow.com/questions/2425906/operator-overloading-outside-class https://stackoverflow.com/questions/2425906/operator-overloa... Also outside of numerical work and some set stuff there's not really that many times you actually need to overload operators.. And you can easily extend languages without objects (Lisp)
- 8y ago
- wmnwmn 8y agoI've felt that way for years. OO perhaps makes sense for certain things, mainly things that someone else writes and you use as a library. Using OO more widely leads to very inflexible code, and since specs are not inflexible, the result is disaster.
- apoph3nia 8y agoOOO sucks too
- kazinator 8y agoIF you don't like data and functions bound together, then use a CLOS-like object system with generic functions that don't belong to classes, but have methods whose arguments are merely specialized by class types. Functions and data are in fact tied together. Almost any thing in mathematics is described in terms of some collection of properties which are elements of sets, and operations. The operations are part of the representation. A Universal Turing machine is the tape, the symbols, the rules of how the head moves and reads and writes symbols, all together.
- opportune 8y agoObjected oriented programming became popular because a skilled software engineer could create an application outline/spec and then pass that on to lower skilled programmers who would implement the spec without completely fucking it up. It made it easy to separate out work among large teams and write tests (ok we are going to divide up the work between these implementations, each of which gets its own set of unit tests for each function) and standardized some of the high level interactions ahead of time (see: convert spec to code). It was never meant to be a surgical scalpel that a highly skilled developer could use to attain high individual productivity. Also I highly disagree with the assertion that "Data structure and functions should not be bound together". I would argue that if you are using any sufficiently complex or niche data structure that is not part of some standard library or a primitive, you absolutely do want to bind functions to the datastructure. It is much better to define a data structure with a set of logical human-readable functions for what you want to do with it than to keep it as some collection of primitives or standard lib datastructures you pass around everywhere. Let's say you are writing a spell checker. You really want to abstract away all the ugly details of the trie and any other helper datastructures. You also may want to create an interface for some "word library" that you can extend with different solutions to test e.g. performance (if you are trying to optimize for caching). Object oriented programming really simplifies things in a scenario like this.
- deleted 8y ago[deleted]
- TheAsprngHacker 8y agoI agree with a lot of the criticisms in Dr. Armstrong's article, but I would say that they mainly affect languages such as Java that enforce OO; multi-paradigm languages that allow for OO but don't force it on you don't have these problems. I believe that OOP has valid uses. > Objection 1. Data structure and functions should not be bound together In languages like OCaml and C, one defines types separately from functions. Sometimes, however, I find that a function is best associated with a particular type. In OCaml, that's one purpose of modules. (The convention is to call the main type "t.") However, this organization shouldn't be forced on you. > Objection 2. Everything has to be an object. This objection only applies to languages like Java that force OO on you. In OCaml or C++, I don't have to use OO, but I still can if I want to. > Objection 3. In an OOPL data type definitions are spread out all over the place. Armstrong complains about having to decide what to inherit from when making a Time object. IMO this is a strawman; in Java, classes inherit from Object by default and I don't see any inconvenience. I do agree that it can be annoying that Time has to be object-oriented, and this is where the benefit of OO being voluntary comes in. > Objection 4. Objects have private state. I either disagree with or don't understand this objection. Dr. Armstrong lists three ways to deal with state. His third option is to use pure functional programming. I see both the beauty and practical value in making functions be functions in the math sense, that is to say, mappings from elements of the domain to elements of the codomain. Then, you get equational reasoning. I am sympathetic to this idea. Nevertheless, languages like Haskell aren't for everybody. His second option is to control access to mutable variables with scope. You can implement a pure function in an imperative way, and that can be a form of encapsulation. This is a good approach, too. Dr. Armstrong's first option, which he says is the worst, is the idea that objects maintain hidden state which people control via methods. To me, this isn't about state, but rather encapsulation and abstraction. The idea is that when one, say, inserts into a hash table, the person doesn't think about the implementation ("hash the key and walk down the corresponding bucket"), the person thinks of the abstract problem domain ("map this key to this value"). The hash table interface hides its internal state behind the methods. Even in a programming language like C, one writes functions that operate on, and mutate, structs to abstract things away. Although the second option is good, I see it as orthogonal to the first option, not a superior alternative. If you are going to confine state to within a function, ultimately, don't you have to do mutations on the local variables, and therefore call some kind of method or impure function on them? However, perhaps I am misunderstanding this fourth point. A lot of arguments, including this submission, pit OOP against FP and argue that FP is superior to OOP. Even though I use FP, I also think that OOP can be useful. They are not opposites and don't have to conflict. OCaml is infamous for its object layer, yet I ended up using it for a project. I wanted to describe UI "widgets" such that I could compose arbitrary different types of widgets. Before deciding on objects, I had considered first-class modules or a record of functions, but ultimately decided that objects were the most readable choice. In my OCaml program, I mainly viewed OOP as a way to abstract different types into a common idea. Widgets are all different, and they have different behaviors, but they all have a position in space, a length, and a width. One can also reposition them (mutation!). To me, the purpose of OO is to express ideas such as these. I note that when I used OOP here, I cared less about state and more about the abstraction of what a "widget" was, via dynamic dispatch. It is bad when the language forces OO on you, but it has valid uses.
- rhblake 8y agoIt really should be noted that years later Joe changed his mind about OO and came to the realization that perhaps Erlang is the only object-oriented language :) From a 2010 interview: ..."I wrote a an article, a blog thing, years ago - Why object oriented programming is silly. I mainly wanted to provoke people with it. They had a quite interesting response to that and I managed to annoy a lot of people, which was part of the intention actually. I started wondering about what object oriented programming was and I thought Erlang wasn't object oriented, it was a functional programming language. Then, my thesis supervisor said "But you're wrong, Erlang is extremely object oriented". He said object oriented languages aren't object oriented. I might think, though I'm not quite sure if I believe this or not, but Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it's based on message passing, that you have isolation between objects and have polymorphism. Alan Kay himself wrote this famous thing and said "The notion of object oriented programming is completely misunderstood. It's not about objects and classes, it's all about messages". He wrote that and he said that the initial reaction to object oriented programming was to overemphasize the classes and methods and under emphasize the messages and if we talk much more about messages then it would be a lot nicer. The original Smalltalk was always talking about objects and you sent messages to them and they responded by sending messages back." See https://www.infoq.com/interviews/johnson-armstrong-oop https://www.infoq.com/interviews/johnson-armstrong-oop (2010) for the full answer (and more), it's worth a read.
- hota_mazi 8y agoBoth Alan Kay and Joe Armstrong struck me as having had the same attitude of trying to capitalize on the topic of object oriented programming, failing to recognize its importance, and then later trying to appropriate it by redefining it. Not the best moment of these otherwise two bright minds.
- skndr 8y agoDidn’t Alan Kay coin the term “object oriented”?
- 8y ago
- rkagerer 8y agoMy lukewarm enthusiasm for OO stems from a different set of reasons than these. I view its main benefit to be the way it reinforces encapsulation as a design pattern. But good code with clearly organized functions and data structures can achieve that just as well. I don't have anything against it, and wielded with skill I see its benefit. But after 30 years of programming I think you can achieve many of those benefits more simply without it.
- Havoc 8y ago>Consider “time”. In an OO language a “time” has to be an object. No it fukin doesn't. OO is a paradigm, useful at times, nothing more. That's what modern programming is all about - you pick the right tool for the right task. OP's attempt to force OO onto an abstract concept like time is so far off the mark calling it a strawman wouldn't even be the right word.
- jussij 8y agoI have worked on systems that had turned into the classic 'big ball of OOP spaghetti'. Likewise I've also had to deal with a 'big ball of structured programming spaghetti'. My take on the difference in these two types of systems is they are generally the result of too much coding with too little design. Personally, I think the OOP approach does have a tendency to turn into that spaghetti ball more easily, only because it needs more up front design. Most of places I've worked who adopted an OO approach have tended to focus predominantly on the OOP with little or no attention to the OOD and that tends to be a recipe for disaster.
- Const-me 8y ago> The “hide the state from the programmer” option chosen by OOPLs is the worst possible choice When you code C and write something as simple as fwrite( "Hello world", 1, 11, stream ); that line of code changes state of the file stream object in CRT, state of file caches in OS, state of B-tree nodes in file system driver, state of disk firmware, state of NAND flash chips… It’s not just OS and drivers. Any sufficiently complex software is built by layering abstractions on top of each other. Many problems that need to be solved have very complex state, often related to IO or GUI. You don’t have other choice but to use some form of OOP and hide lower-level implementation details behind abstractions, otherwise you won’t be able to get anything done due to overwhelming amount of state to reason about.
- andy_ppp 8y agoNobody is saying don’t have any abstractions, just that your program hiding state in layers of objects is often counterproductive.
- Const-me 8y ago> program hiding state in layers of objects is often counterproductive Do you think it was counterproductive to hide OS-specific file handles, CRT level of caching, and many other things CRT does behind these opaque FILE* object pointers? Such hiding allowed to have very similar and quite easy to use <stdio.h> across all platforms. The implementation of these fopen and fwrite functions relies on kernel calls like open/write on Linux and CreateFile/WriteFile on Windows. Do you think it was counterproductive to hide all the lower-level stuff like OS caches, inodes (linux) / NTFS (windows), and the rest of them, behind these OS kernel calls? If you’ll decide to unhide them, your OS won’t have any security at all, the OS file system cache is security sensitive. Modern OSes implement strict access control while they hide that piece of state, every file has permissions, every process accessing them has user identity, and the OS checks these things when process access files or file system cache.
- jstimpfle 8y ago> Do you think it was counterproductive to hide OS-specific file handles, CRT level of caching, and many other things CRT does behind these opaque FILE* object pointers? To answer that question for parent, no, he obviously doesn't think so. And yes, streams are basically OOP (they are implemented using "method dispatch"). Streams are one of the few successful abstractions out there. And when I say "successful" I mostly mean "necessary". Because they're leaky. Consider fseek(3), ftell(3), fileno(3), fflush(3), fclose(3), fsync(2), posix_fadvise(2), isatty(2), fcntl(2), ioctl(2) and many more. All operations that are not supported for all streams, but necessary for some (like file system files, network connections, terminals devices...). Essentially when you use any of these you concede to break the abstraction. It's incredibly hard to handle these streams correctly, and the vast majority of programs are faulty in that they don't handle most error conditions correctly. In some cases, it isn't even possible to handle errors through the API! See close(2) So again, not saying we shouldn't have a stream abstraction. But abstractions come at a huge price, and therefore it's incredibly misguided to make every program a layering of thousands of pseudo-isolated objects that bring their own bug-prone abstractions and idiosyncrasies.
- deleted 8y ago[deleted]
- fnrslvr 8y ago> I think this is a fundamental error since functions and data structures belong in totally different worlds. This is my biggest issue with the article. Blurring the boundary between program and data is one of the core principles at the heart of computer science, and was crucial to the works of Turing, Church, et al, that birthed computer science as a field.
- russellbeattie 8y agoThat's an interesting observation, however this discussion is at an abstraction level far removed from those basic concepts. No one is arguing whether OOP can be compiled into logic instructions that are better or worse than some other programming paradigm, we've got that figured out. We know how to convert just about any system of organizing data and functions into the billions of individual transactions that a CPU has to make to execute that program. Copying a byte value from one place into a register, interpreting another byte as an instruction and the next byte as the address for the result and the next as a hardware switch... These are the concepts Turing and Von Neumann figured out, but they're irrelevant to the modern day question of how to organize thousands or millions of lines of code to minimize errors and maximize understanding and efficiency. In fact, the OOP question isn't as much about science and technology as it is a social question concerning the best way to organize logic and information as a profession. What's the best way to make sure programmers don't screw things up? Is it to make sure the most incompetent developer can be somewhat productive with simple concepts, or are those simplified concepts inherently flawed? Or is it somewhere in the middle?
- olodus 8y ago> Conventional languages (like C or Pascal)... I've always heard of Pascal as "the Java before Java" or atleast quite an OO language. And since I knew Java I never thought to even go and look at it. Did I miss something here?
- colordrops 8y agoOne thing I find problematic about C++ style OOP is that classes are just bags of global-like variables. Unless you keep your classes very small, member data can be mutated in a dozen places in the class in a dozen ways, and it's just a big spaghetti mess. I understand that c++ code can be written cleanly and readably, but in most cases it's not.
- ne01 8y agoTo me OOP is complex and complexity is the enemy of writing good code. Also simplicity is relative. Most of us like OOP because we have learned it and invested time in it and most probably defined by it.
- profalseidol 8y ago> State is the root of all evil. Both in programming and in real life haha.
- oldpond 8y agoJoe was truly one of the greats. My favourite: https://www.youtube.com/watch?v=bo5WL5IQAd0 https://www.youtube.com/watch?v=bo5WL5IQAd0 Thank, Joe.
- gfiorav 8y agoOO is good for programmers to model problems, not for yielding the best result. I find that thinking in terms of functional code (info being passed from one place to another; not diluted into a lot of objects with state) yields the best result in terms of stability and lack of bugs
- axilmar 8y agoI disagree with every point he made. Data structures shall be bound to functions. It increases modularity. That does not mean common code shall not be refactored and be standalone. Data types are instantiated to objects. When in Erlang a time variable is declared, that variable is an object. OOP has data types too, called classes, and having everything to be an object does not mean it has to be the same data type. In some languages classes can be in the same file, so point #3 is actually about specific implementations. Inside point #3 he also mentions inheritance. Not all OOP languages require inheritance from a specific class. I also disagree with his 4th point about hidden state: hidden state enhances modularization tremendously. I don't need to see how something is implemented, treating it as a black box increases my chances of using it correctly through a predefined interface. If the interface is lacking or is not defined correctly, that's an entirely different problem and it's not due to hidden state.
- halayli 8y agoApproaching OO with the mentality that it's easy is what makes OO looks bad. It doesn't get treated with the same focus/attention as other methodologies. This realization often comes in retrospect, after programming for many years and watching how you misunderstood OO and how your abstractions improved over time. OO is not easy after all. You might be familiar with all the patterns which can give a sense that you know OO well, and you end up with pretty bad design.
- deleted 8y ago[deleted]
- hi56793 8y agoIt's always interesting to see "<insert popular paradigm/technology> sucks" headlines. Maybe that's also intrinsic to the popularity, on the one hand this got popular for a good reason most likely. But on the other many people might be very careless when using that paradigm and only inform themselves superficially - at best - about the background. That said, I really like how JS had been tamed through OO despite the FP approach being much more interesting. When I use OO, my main motivation is also that it's easier to share code and debugging becomes much more predictable. (Aahh, it's in this encapsulated part of the code...)
- raxxorrax 8y agoOO is basically about modeling data. It doesn't make any statements about procedures, even if it includes operations on said data. If you expect more from OO, you will be disappointed.
- bartimus 8y agoIt just makes sense to me: * Domain = logic + data * Application = logic + data * Object = logic + data Nothing wrong with using functions and data objects. But they're often still interdependent. A class just makes it official.
- daveheq 8y agoWhy Joe Armstrong sucks
- sonnyblarney 8y agoI suggest OO is a useful abstraction because it maps well to the universe we are trying to describe, especially with respect to state. Rule of thumb? Anything that can reasonably be done in FP should be done there, in 'library' like conditions (some people use the term 'FP core' - I think more as lib). The point is to parse out as much of the problem into highly individual parts that can be built/tested on their own. Think of parsers, pre-processors, utilities like lodash, node libraries. These things tend to be truly stateless. Then OO for the inherently stateful stuff. I also think the discussion might be coloured by the type of dev: UI is fundamentally stateful. Very much so and there's no avoiding it. OO lends very well to abstractions such as 'button' and 'text field' etc.. Backend, maybe less so, depending on.
- georgeecollins 8y agoWhat are the concepts today that smart people are convinced are the "right" way to do a thing that later will seem dubious? - Microservices? - Agile development? I feel like I am not trendy enough to know what the latest development religions are.
- stonefarfalle 8y agoObjection 1: Given a queue, priority queue, and stack, how do those data structures "just exist", without the behavior associated with them? The interactaction with them is their defining characteristic. Objection 2: I agree not everything should be an object. However where do you draw the line? To me a timestamp is a perfectly reasonable object. I can see the pros and cons of "3" being an object as well. Objection 3: I like things to be organized. What benfit do I get by jumbling everything together in one spot? Objection 4: Yes they do, pretending they don't doesn't help. Even in Haskell, files and sockets are represented as an opaque handle to hidden state. It very much looks like a OO interface in a non OO language. Given the three data structures in objection 1, hiding the state allows for a smaller surface area to prove that the data structures are correctly implemented. Allowing random access to their state does not improve them.
- IOT_Apprentice 8y agoJoe passed away last week.
- tabtab 8y agoThe "problem" with OOP is that it was originally oversold for the wrong reasons, and it took the industry a while to learn when and where to use it and where not to. Around the late 1980's OOP was hyped as a way to do domain modelling. That is, modelling the nouns and verbs of the subject at hand (employees, invoices, etc.) While some still defend it for domain modeling, most have found it a poor fit for any non-trivial model. But it did turn out a handy way to present and manage APIs to "external" libraries or services. This is largely how it's used today. The lessons: 1. Use the right tool for the job, and no one tool is right for everything. 2. Test an idea in production for a while before drawing conclusions about what its good at and what its not. Microservices is currently making similar mistakes, I would note. Those who don't learn history are bound to repeat it.