36 ms·
Case against OOP is understated, not overstated (2020)
- troupe 5y agoWe tend to judge OOP by the worse way we've seen it used. To really be fair, we need to find the best usages of OOP and see how those have faired over time. I'd suggest looking at NextStep as it seemed to be created by a team with a very high degree of expertise in OO as well as a strong design focus.
- blunte 5y ago-- (Even if you don't read this whole comment, I urge you to watch this fantastic video which illustrates procedural, OOP(lite), and FP approaches to a sample problem: https://www.youtube.com/watch?v=vK1DazRK_a0 https://www.youtube.com/watch?v=vK1DazRK_a0 (Despite the name, it illustrates JavaScript, not Clojure). If you follow this approach, you don't even have to tell people you are doing FP. You'll just end up with better, more understandable, and more easily testable code.) -- The early (early as in C++ days) benefit of OOP was probably that it made programmers stop and plan before coding. Having learned FP 20 years after learning OOP, I feel certain that I can do the same things in less and more understandable (and MUCH more easily testable) code in FP. OOP was awesome for a small set of cases and for academic scenarios. But like REST, it doesn't map well to all needs. Then it becomes awkward and unnecessarily complicated. FP, or simplified as immutable data transformations with necessary mutations pushed to the edges, works everywhere, all the time. In FP you can still choose to model your data in hierarchies, keeping some of the useful bits of OOP. But it's still data in, results out. Until you've spent time on real projects in both, you cannot appreciate why FP is superior. (And to be clear, I'm not even talking about Haskell and type-obsessed FP. Perhaps because I'm not a Haskell guy, I can't appreciate it. But it smells to me like an extreme of a good thing (and therefore not usually the best thing for the situation); but I digress.) Concretely, I worked recently for a client that needed Ruby on Rails development done on a production product. It was fairly OOPish (in the Ruby way, which is to say much less insane than Java from the past OOP). Even so, the OOP at the business logic level was unnecessary. Testing was complicated and full of code to mock and fake. When we were given the task to build a completely new solution to the same problem, greenfield, I immediately began building modules with almost entirely pure functions. Because Ruby isn't designed for this approach, it does involve a bit of care to respect memory and object copy time costs. But in many business cases, the volume of data being processed isn't significant or isn't fast-repetative. The new product had many fewer lines of code, and the test cases were as close to beautiful as maybe is possible for tests. That's a different subject for debate... The less experienced devs took a bit of time to accept and adjust, but the mid-level engineers became big fans of the approach. The juniors just accepted it (so nice :D). Test coverage went up, and the cost of adding new features went way down. My FP languages of choice are Clojure and Elixir in that order. Elixir does offer some pretty great features that Clojure doesn't have (extensive pattern matching), but the syntax is imo very noisy compared to the utter simplicity of s-expressions. Either is fine for me. Ruby is fine, with some care. Python too. Vanilla Javascript can be fine, and some libraries can improve this. Anyone who has read this far and is not convinced, I urge you to follow some Elixir tutorials and reach the point of grokking it. Then if you're a web dev, Phoenix is a fantastic framework. Also, the Erlang (BEAM) VM provides so many useful structures and utilities to allow you to build big distributed things easily compared to other languages. Be warned though: once you do this, you will forever be frustrated by OOP codebases.
- yoyar 5y agoEvery complaint I’ve ever seen about OOP (and other tools) amounts to “we misused and abused the tool/language/whatever so therefore the tool itself is bad “
- EdwardDiego 5y agoBut don't worry, someone will accuse of the No True Scotsman fallacy shortly.
- fucksamsung 5y ago- phillips screw drivers are obsolete you should never use them just use torx and throw away anything that uses phillips screws because everybody is doing it. There never was any merit to using one vs the other either, just that people who are still using phillips screws need to get with the times and use torx.
- fucksamsung 5y agoMicrosoft word is the most sophisticated word processor, people who use nano and vim are just behind the times... you can do anything with microsoft word. you can do anything with microsoft excel for that matter it's turing complete https://www.infoq.com/articles/excel-lambda-turing-complete/ https://www.infoq.com/articles/excel-lambda-turing-complete/ so its realistically the only programming language you'll ever need and it's the right tool for every job because its point and click and it interfaces with the real world so that people can relate to it better and the learning curve isn't as steep.
- fdgsdfogijq 5y agoHow I've seen OOP work at big tech is the following: 1. New code base is needed 2. Some developer comes up with the master oop abstraction to solve the problem 3. Years of dev effort spent with the abstraction at the core 4. Dev on step 2 is now the expert in some overly convoluted complex system 5. Is determined a genius since new comers cant easily grasp the complexity, gets promoted to a high ranking dev job My number one rule of coding politics: He who creates the OOP abstraction rules the team
- vorpalhex 5y agoMy grading criteria for a codebase is "Can a hungover junior engineer comprehend this and work on it successfully?" When we are getting to "only a Principle engineer who is an expert in scala with a history of strong mathematics can work on this" is about when a codebase gets a fail.
- kungito 5y agoThats a broad generalization and many niche codebases cannot be high quality and still have a drunk junior become productive with it in a week. People need to accept that it's ok to require for some teams to have discussions on a level which requires serious experience and education
- catlifeonmars 5y agoIndeed. A more nuanced interpretation of the question might be: “Can the most junior (or least tenured) engineer on my team understand the code in time to deliver the feature they’re working on?” To be fair, OP’s original phrasing is still a good rule of thumb. And nowhere does the OP imply it’s an absolute.
- jim-jim-jim 5y agoThis does a massive long-term disservice to junior engineers, especially because they're most likely just out of school and still very eager to learn.
- all2 5y agoShould be marked (2020).
- WithinReason 5y agoOOP hate is evergreen
- dang 5y agoAdded. Thanks!
- ameixaseca 5y agoInteresting collection of point of views. A language like Erlang indeed seems to align more closely with the spirit of the OOP goals - especially regarding encapsulation and avoiding shared state. I would argue one of the best implementations of OOP is found in OCaml, where a nominal type system lives side-by-side with a structural type system, the latter which is used for objects and classes [1]. You still can use shared/mutable state, but functional styles are usually preferred - including a pattern known as "functional objects" [2], which allows the use of OOP but avoids shared mutability and its associated shortcomings. [1] https://en.wikipedia.org/wiki/Structural_type_system#Example https://en.wikipedia.org/wiki/Structural_type_system#Example [2] https://ocaml.org/manual/objectexamples.html#s%3Afunctional-objects https://ocaml.org/manual/objectexamples.html#s%3Afunctional-...
- nextos 5y agoYes, OO is about message passing. Erlang places a lot of emphasis on this, and in my experience one can use it to build huge systems that are easy to understand and to parallelize.
- lliamander 5y ago> A language like Erlang indeed seems to align more closely with the spirit of the OOP goals - especially regarding encapsulation and avoiding shared state. Indeed, Alan Kay himself said, to Joe Armstrong, that Erlang was closer to his idea of OOP than any contemporary language that claims to be OOP.
- Zababa 5y agoThis is one of the things I love about OCaml. Even though the objects aren't used frequently, they were designed well, and people don't mind reaching for them when there is a need. It's a good way to show the "pragmatic, but careful" approach that OCaml has for a lot of things.
- cooervo 5y ago
- hodgesrm 5y agoPretty tangled read. This seems to be an example of write-only code, but applied to essays. It appears the author is in favor of OOP but it's a little hard to tell.
- deleted 5y ago[deleted]
- giantg2 5y agoI'm currently working on an issue thats taking me longer than it should (I'm a slow). It's a change to a json structure that impacts multiple files in lines that consist of 5+ method chains that I have to track down in other classes and custom libraries to see what it's doing (Java). It could have been a single Python file using Pandas to build a DataFrame and this change would have been so much easier. And I'm saying that as someone with at least 10x more Java development than Python development.
- taurath 5y agoIn my mind, state is the real enemy impacting: comprehension, brittleness towards making changes, and the surface area exposed to potential bugs. OOP as frequently implemented, while claiming to encapsulate state, ends up creating so much more. In accordance with this view, I think project architecture should be approached with an emphasis around how much state is necessary for it to run. This is why simulations like say someone making a game or simcity with like relatively independent entities that map to something in real life use OOP. If you're writing a service doing requests, you want as minimal state as possible. Singletons are state. Initialized/non-static objects are state. The smaller amount you have the easier it is to reason about the system. As I write this however, I worry a little that my view is overly simplistic, or maybe applicable only to domains that I have worked in. If anyone wouldn't mind poking holes in this argument or offering examples I would appreciate it.
- lostcolony 5y agoI think in a lot of ways you're correct. FP and imperative code tends to makes state explicit; OOP hides state. The latter MAY make things "easy"; it never makes it simple.
- deleted 5y ago[deleted]
- zozbot234 5y ago"Hiding" state is necessary to endow it with well-defined invariants. This can be done in many FP languages, too. The semantics-side implications of "encapsulated" state w/ proper invariants have yet to be explored, though, and this is where newer PL formalisms like "homotopy types" might end up being quite helpful.
- dwohnitmok 5y agoWhat would homotopy types bring to the table?
- 5y ago
- everyone 5y agoPeople spend way too much time arguing about this.. If you're a good programmer u will be able to do excellent maintainable work in any language you're experienced with. If you're bad you will make a mess in any language. It'd be like carpenters saying "spruce is terrible if you make anything from spruce its fucked, you have to use oak." ; A good carpenter will be able to make something amazing from spruce. Like carpentry, metalworking etc. the quality of the product of programming is heavily based on the skill of the tradesman.
- ttz 5y agoYeah pretty much this. If a paradigm (whether functional, OOP, or whatever label makes you feel better) isn't working for you when it has worked for many others, maybe it's not because the paradigm sucks... it's because you might just suck at the paradigm? Obviously there are cases where things were pigeonholed into the wrong paradigm for the job. Then it's a case of the person choosing the paradigm sucking at choosing the paradigm. Whatever happened to personal responsibility?
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- solraph 5y agoAbsolutely. I really want to love FP style programming, but I just can't get it to gel in my head. I'm totally on board with the concepts of side effect free programming, minimising state, passing around functions as parameters, etc... But I struggle with reading it, and I struggle with writing it, and I struggle to build a conceptual framework of how FP style components fit together. I've been banging my head against the FP wall for _years_ now, and I still can't seem get a level of fluency that where I'm comfortable using it regularly. That doesn't mean FP sucks, it just means my brain isn't wired that way.
- contravariant 5y agoI've come around to Julia's point of view that it makes more sense for the methods to be separate from the object they're acting on. I just wish Julia had a succinct way of saying "This object needs to have implementations for functions X,Y,Z", rather than duck typing everything and just seeing if it works. Maybe it isn't too bad in practice I just don't like it when a function can fail because the implementation changed even though the type signature didn't. Anyway at the very least the approach of keeping methods separate helps to prevent objects that do not have any state and do not in fact represent any entity at all. Seriously who came up with naming a class "MyObjectHelper"? What on earth is it? It could represent literally anything. Does it even have state? And why?
- crabmusket 5y agoThis is known as "multiple dispatch" or "multimethods": https://en.wikipedia.org/wiki/Multiple_dispatch https://en.wikipedia.org/wiki/Multiple_dispatch
- memco 5y agoThere was a presentation pycon 2021 describing how protocols enables better typing in several cases: https://m.youtube.com/watch?v=kDDCKwP7QgQ&list=PL2Uw4_HvXqvYk1Y5P8kryoyd83L_0Uk5K&index=42 https://m.youtube.com/watch?v=kDDCKwP7QgQ&list=PL2Uw4_HvXqvY.... They sound similar to what you describe in that the protocol allows you to describe the features of the thing you need and the type checker can then help you determine that the thing you need has those features. Doing this kind of feature detection allows you to check ahead of time whether a call is likely to succeed but especially for a language like python you still need runtime guards of some kind to limit the impact of unexpected cases.
- mdoms 5y agoWho is Julia?
- unnouinceput 5y agohttps://en.wikipedia.org/wiki/Julia_(programming_language) https://en.wikipedia.org/wiki/Julia_(programming_language)
- waynecochran 5y agoOOP is a great fit for UI frameworks. OOP is a bad fit for many other things. They guy who hammers nails all day thinks screwdrivers are worthless.
- wrnr 5y agoOO gets you a long way, still there are interesting approaches being tried with data-driven programming through either composing lenses and ECS. I have a hard time understanding lenses, seems like a lot of work to reproduce the most strait-forward concept in OO (getters and setters). ECS do away with object and give you almost like a relational database, but it is cumbersome to encode hierarchies, but they do offer a way for non-code tools to interface with code which is important too.
- garethrowlands 5y agoLenses solve a problem you don't have in OOP. Since OOP allows mutation, to change a value within a nested structure, just mutate it. If you don't want to mutate, then getters and setters don't help and changing nested structures is awkward. Lenses solve the nested mutation problem for immutable structures but then go past what you can do with getters and setters. For example, you can compose bigger lenses out of smaller ones.
- ummonk 5y agoIf ECS' Systems are querying Entities / Components the way one would use a SQL query in a relational database, what's needed for hierarchies is the ECS equivalent of a graph database.
- akavi 5y ago> OOP is a great fit for UI frameworks. The biggest UI framework of the past decade is decisively anti-OOP in its philosophy
- FpUser 5y agoWhat it the name?
- zozbot234 5y agoThis is basically a survey of a bunch of posts, and doesn't do much to provide a consistent critique. Regardless, the true weak point of OOP is arguably implementation inheritance, which just doesn't leave you with a consistent semantics that's open to extension and changes in the basic/derived classes (that is, the well-known "fragile base class" problem is still a showstopper). But that has always been a pretty ad-hoc feature anyway. The other components of what people call "OOP", including encapsulation and interface inheritance. are all pretty well defined and not as prone to misuse.
- ctxc 5y agoI still don't understand why it's bad! Feels like spaghetti sentences tied together as a single article. Why is OOP so bad, anybody? With scenarios, code samples or alternate implementations?
- unnouinceput 5y agoOOP is not bad. Also the entire discussion is pointless. Problems require solutions. You do the solution in OOP or not, nobody's gonna care, just that the solution solves the problem. Rest is just whispers in the wind.
- hutzlibu 5y agoIn my opinion it is just the current anti-hype. A few years ago OOP was supposed the be the magic bullet for everything, which it was apparently not. And now people critizice OOP for not delivering magic bullets. At the same time everybody seems to mean different things with OOP. So no, it is not bad. Certain practices from OOP, like deep inheritance turned out to be worse in reality than expected in theory. But nothing dramatic. And by my definition of OOP - it is still a major part of every major language.
- lamontcg 5y agoI think the major problem is that base classes are really two different interfaces (public and protected) combined with a default implementation, all exposed as a public symbol that anyone can reference. So if you have a Vehicle base class with Car and Truck that inherit from it people will naturally externally do things like pass around List<Vehicle> and will extend functionality with Lorry : Vehicle and start using it. This creates a problem because you cannot change the base class of a Car or else it will no longer fit in a List<Vehicle> but if you modify Vehicle you may break people who inherit from Vehicle. If you wrote it out explicitly without using inheritence though you'd have something a bit more sane and split up into the three different concerns: class Car : IPublicVehicle { IProtectedVehicle _vehicle = new Vehicle(); public void Drive() { _vehicle.Drive() } } Now you have a public interface where you'd create List<IPublicVehicle>'s and toss them around, but you would be free to write a VehicleV2 class that could be injected into _vehicle (you could even do it dynamically and go nuts with dependency injection). Then other people using Vehicle() wouldn't have their behavior changed and everyone would still live happily inside of List<IPublicVehicles>'s next to each other. At the same time by having to write down the interface IProtectedVehicle (not shown) you'd be more likely to do actual design about the interfaces between your subclasses and your base class. This is the real problem which is that people do lazy shit design over the base class interface and just use it to shove shared code into the base and don't consider it a private interface and then go and break behavior as they mess around with more crap in there. And the "DRY" principle pushes software devs to ALWAYS push shit into their base classes, without even thinking beyond "because DRY", which is guaranteed to be bad design. With good design you may have to tolerate some level of necessary repetition in your base classes. Then you wind up realizing that you need derived classes that do not share behavior (e.g. consider adding a Boat subclass of Vehicle when previously you had taken the SinksInWater() implementation of Car(), Truck() and Lorry() and pushed that into the Vehicle() baseclass. Oops. Now your boats all SinksInWater() unless you override that. And if you override it you may be heading down the road of violating Liskov. So that's the source of the objection that OO programmers will just tell you to write interfaces everywhere for loose coupling and only depend on interfaces not types (not abstract/virtual base classes). But so far I don't know what Go or rust programmers do that is any different. And Go has a really fairly slick system for delegating interfaces to contained structs by composition which is just the same model I outlined above but where the two interfaces are the same. I'm still searching for where other programming languages produce a fundamentally better model. And as far as I've been able to ascertain Go's model is to just replace inheritance with interfaces and delegation -- which you can do in any OO model just by not using inheritance and writing interfaces and delegating. But then the complaint against OO is that proponents will just tell you to write interfaces, and for some reason that is bad. IDK if I'm missing something here...
- jiggawatts 5y agoI don't quite understand what this is trying to say. It's a summary review of some reviews? Or something. It's not even clear if the author of this post agrees or disagrees with the claim in the YC News title. It's peppered with sentences like: "That you don't understand something doesn't mean it's flawed or bad." Precisely. Many of the arguments against OO are from academics that don't write real-world, large-scale software. More arguments are from beginner programmers with a mere 2-5 years of experience that have never personally encountered the mess that programming at scale was before OO made it manageable. Even more arguments are from people that assume that "precisely what language X happens to do" is exactly what OO is or isn't, and then argues from that straw man position. Those same people then cheerfully embrace microservice or K8s, even though they are object-oriented! In case this is not clear, let me define OO for you: "Object oriented design is all about encapsulated private state with abstract interfaces that have varying implementations that clients don't need to know the specifics of -- even the type names -- ahead of time." Sounds like microservices? Or K8s? Or REST? Or service bus? Or event streams? Or any large-scale programming pattern? Yes. That's because abstract interfaces and decoupled components are critical to enabling large teams to collaborate on software too big to hold in the head of any one person. OO is not intended to solve manager-human-employee-customer categorisations of real-world entities. That's a stupid straw-man argument born of toy textbook examples that aren't representative of real-world programs to begin with. OO is intended to allow programming at the scale where simple procedural programming no longer works. I didn't understand the need for OO either until I worked at that scale myself. It seemed overcomplicated and unnecessary. This is why it cracks me up to see language designers (and random Internet bloggers) talk about how "they don't need OO". Yes... you. Singular. One person doesn't ever need OO. Many people do. You're not many people! Has anyone seen large scale development done successfully in an an "anti-OO" language like Rust? I haven't. The single largest codebase is probably Mozilla's Servo, which is still a toy compared to what's been written in C++ or Java! It was written by a few people, mostly in one building. Notably development of it slowed down and was abandoned. It was never shipped as intended. How would you even envision a Rust project working with, say, 1000 developers? What happens when there's some new functionality added? Does developer #587 have to go notify the other 999 developers to update their switch statements, pattern matching code, etc... ? Right now... generally speaking, yes. You'd have to go tell other people to go update their code. As you can imagine, 1000 developers telling 1000 developers to update things is a 1M-level organisational scaling problem. That's why automated tooling was invented to handle this problem automatically, even at runtime, let alone compile time. If you think automation is bad, then we no longer agree on the most basic concepts and this conversation is over. If you have a better method for automating this problem, then I'd love to hear about it! Just make sure it's not OO with a different name...
- quantum_state 5y agoA fool with a tool is still a fool ... to build quality software, apart from understanding the problem to solve and putting one's heart on it, there is no other way.
- sirwhinesalot 5y agoI have not read the article but I've seen other blog posts on the subject. The issue with "OOP is bad" is that OOP means different things to different people. Abstract Data Types are sort of a subset of OOP and are massively useful, I certainly don't think it's a good idea to expose the internal implementation of a data structure most of the time. Any sort of plugin system works in an OO matter. It is a useful tool, no question. Even things like Actors like in Erlang (which are much closer to the Alan Kay style OO) are massively useful in a distributed setting where state is naturally distributed. Where you get into trouble is when you go the whole "lets model a taxonomy of the world" style with inheritance hierarchies or go ham on design patterns, layers upon layers of abstraction and other nonsense like that. The saddest thing about the "object–relational impedance mismatch" is that the focus went totally to the wrong side. The relational model is a much nicer way to model relations than a graph of objects (that's the whole point after all). SQL sucks but that's a separate issue, Entity Component Systems are a form of relational modeling for example and work really well, or even better Datalog.
- almostdeadguy 5y agoThe problem with the "inheritance isn't part of OO" take is that every single one of the languages we call object-oriented that gained mass adoption have inheritance, including Alan Kay's own smalltalk. There have been entire books written about object-oriented design describing ways to use (or not use) inheritance in program design. So whether or not it was intended to be important by the author of the term is immaterial, it for all intents and purposes is a crucial part of object oriented languages. Inheritance is not the only problem w/ OO either, many things are straight up awkward to express when you must couple data and code together. Many 2+-argument function w/ disparate parameter types create confusion about which class "owns" the definition of the function. You also don't need to marry data and code to get the benefits of encapsulation. Many functional languages in the ML family have developed clever solutions to encapsulate the definition of a datatype while exposing it to module-local functions. There's no need for the datatype to carry a method around with it to support this.
- dools 5y ago"The saddest thing about the "object–relational impedance mismatch" is that the focus went totally to the wrong side. The relational model is a much nicer way to model relations than a graph of objects (that's the whole point after all)." I found the same thing. When I was using ORMs I always found them clunky for all but the simplest tasks, where I would long for an easy way to use SQL and have it "just work" for objects, so I created this: https://github.com/iaindooley/PluSQL https://github.com/iaindooley/PluSQL It's obviously not been maintained but I think it's a model that has legs: that is, simply the creation of SQL with some convenience methods, allow the use of completely arbitrary SQL, and then intuit the object mapping automatically without loading the entire result set into memory.
- ledgerdev 5y agoData Oriented Programming. In short, don't entangle your code with data, and the data should immutable. https://blog.klipse.tech/databook/2020/09/25/data-book-chap0.html https://blog.klipse.tech/databook/2020/09/25/data-book-chap0...
- FpUser 5y agoPlease allow me to decide how I structure my code. I do not need help.
- AnimalMuppet 5y agoA program with only immutable data cannot do anything interesting, almost by definition. Some data has to be mutable.
- _fullpint 5y agoOnly has to be at the root.
- sirwhinesalot 5y agoData Oriented Programming originated from video game development and is all about knowing your hardware and making sure you transform data A into data B in the most efficient way possible. This tends to have other benefits besides performance as the simplification of code that results from focusing on the right thing also tends to help with architecture (until you go ham on optimization). What it most certainly is not about is immutable data since that's counter to efficiency. It's hard to beat a big fat buffer you poke at directly. Not entangling code with data and focusing on immutable data is Functional Programming, pretty much its definition, not Data Oriented Programming.
- ummonk 5y agoThe problem with OOP is not just with poor implementations and inheritance models (e.g. Java) but that state encapsulation is actually bad and cements complexity. The real goal should be to untangle state and decouple it from computations by putting it all in global shared state (e.g. SQL, Redux, ECS frameworks, etc.) while using stateless functional computations to compute changes to the global state. Pure functions are composable in a way that objects simply aren’t.
- ferdowsi 5y agoThe opposite end of OOP is the functional purist world where "color = blue when hovering over button" becomes 10 levels of boilerplate indirection in order to update global state and receive changes using actions/reducers/containers/memoizers. It's just substituting one type of needless, brittle complexity for another.
- mountainriver 5y agoExactly and the functional way is harder for humans to grok
- ummonk 5y agoThat’s fair and as someone who has that same frustration with it I realized Redux might not be the best example precisely for this reason. I’d argue though that the problem here is the premature abstraction of encapsulating state in actions/reducers/memoizers. This sort of thing would be way more natural in an ECS framework.
- z5h 5y agoFunctional purist here (mostly Elm), and I have very few problems that arise from the paradigm. Also fewer bugs than pretty much any software I use or deal with.
- jayd16 5y agoAre you saying we should remove local state? If you aren't then why is that better organized than object state?
- thoughtFrame 5y agoSo are there any resources for simpler way of writing code but for bigger projects (specifically more complexity than toy programs or scripts) or do I only have well written codebases in a similar style as a target to study? I'm aware that you can write good OO code, that inheritance can be useful (e.g. in shallow hierarchies), etc. but I'm interested in exploring this other side of programming to improve my code
- bluepnume 5y agoClasses are fine so long as: - They're small and single-purposed - They don't inherit (or at the very least, extremely light inheritance) - There's a very clear relationship between the state and the methods (e.g. a counter class, or a future/promise) For example in JavaScript, I think you can still uses classes and end up with functional-ish code: https://bluepnume.medium.com/functional-ish-javascript-205c05d0ed08 https://bluepnume.medium.com/functional-ish-javascript-205c0...
- throwawaylinux 5y agoBack in the 90s OOP was touted as revolutionary. The next big thing, would completely change programming. If something wasn't object oriented, it was looked down upon. SQL even got on the bandwagon. It was said that very complex inheritance structures, operator overloading, and all this other stuff would (somehow) make it far easier to write and understand complex projects. Many seemed to have taken and repeated this on faith and not much else. I'd never seen any real justification for these assertions, it was never explained to me why those things would perform as claimed with sound reasoning, let alone actual data. Were there ever any real objective [hah] studies done about how much it improved software development? And did they show a significant improvement? Even if you're still pro-OOP today, you would have to admit it fell vastly short of its promises even if it does help a little bit. Today it seems like there's been very little accountability or learning from all this. Some people have sheepishly climbed down off the bandwagon, but there's been very little overall reflection. I'm not talking about witch hunts -- there will always be more snake oil salesmen -- I mean learning as individuals and an industry to demand data and reason rather than handwaving and assertions. The sad thing too is that a lot of the baseless hype came out of academia too (microkernels are another one that comes to mind). I still see this today. The new languages and language features. New database concepts like NoSQL. "AI". Blockchain. All the way down to the CPU (transactional memory, various "security" features, etc). Proponents can make extremely compelling-sounding cases for these things, and make it sound like they'll solve all the world's problems. And some may well turn out to be a net win in the end. But the only thing that actually matters is the real world results, and you can only evaluate that by studying the data. In general, if something sounds too good to be true, it usually is. Maybe the incredible trajectory of the computing industry has dulled peoples' common sense when it comes to detecting this kind of hype. It's absolutely rife in the computing industry and academia.
- HNSucksAss 5y ago
- LadyCailin 5y agoWait, what’s wrong with NoSQL? It’s not good for shoving relational paradigms into, but it’s basically infinitely horizontally scalable, which, as far as I’m aware, isn’t possible with relational DBs, not at the same performance at massive scale, anyways. A bit annoying when people shove a relational DB into a NoSQL schema though.
- deleted 5y ago[deleted]
- hgs3 5y agoBased on my own experience, OO works best for small, self contained concepts whereas procedures work best for the overall program architecture. Notice when OO is evangelized it's always done using self contained concepts, like data structures or GUI widgets rather than architecture. When you do use OO for program architecture, like in Java, you'll end up with lots of pointless indirection and brittle, over engineered design pattern soup. Procedures are simply more "fluid" because they are smaller, self contained and easily refactorable which is exactly what you want when it comes to program modifications.
- zwieback 5y agohah, is this the return of "topmind"? I miss that guy, he was the anti-OO fanatic of the 2000s on usenet and c2.com.
- joe_the_user 5y agoArticle like this miss the question of what purposes OOP serves in practice and so fail to offer alternatives to that purpose. In practice, OOP basically exists to take some horribly messy program, put an interface around it, and make it slightly less terrible to deal with. Similarly, it also involves creating an interface to a thing a programmer barely understands and letting the programmer do some things with it. Which is to say is about letting the programmer be wrong and only fail moderately - as opposed to making the programmer is right. Inheritance, one of the worst feature of OOP, has wormed it's way because it's also incredibly convenient. Everything that OOP is compared to (notably functional programming), is based on a "green fields" paradigm where everything can be controlled. And maybe those approaches work great (though you can't exhibit stuff with they replaced in OO in the trenches and maybe things great). It's got the tone of "this suspension bridge is far superior to your roll of duct tape" - yeah, maybe you're right but that won't make the duct tape go away even slightly. I wish someone would come up with a good and immediately applicable alternative to OOP but I can't this sort of critique leading there.
- keithasaurus 5y ago> In practice, OOP basically exists to take some horribly messy program, put an interface around it, and make it slightly less terrible to deal with. Similarly, it also involves creating an interface to a thing a programmer barely understands and letting the programmer do some things with it. Which is to say is about letting the programmer be wrong and only fail moderately - as opposed to making the programmer is right. I don't think any of this is unique to OOP; rather, this applies generally to the concept of abstraction.
- joe_the_user 5y agoI was referring thing like using member functions to do bounds checking and to make parameters consistent. That's not really "the right way" to do programming or something generic abstraction gets you. The calling function should just know what it's doing. The Dijkstra quote "Object oriented programs are offered as alternatives to correct ones..." is correct. If you set a wrong parameter, it's ignored and your program works, it might have a more subtle bug from what you thought your wrong parameter would accomplish. But this is still useful for programs produced by large teams where some people knowledge is limited. It's a mess but no one has put forward an alternative to the mess.
- dmz73 5y agoThat is a wall of text that I admit I could not fully read or understand. It seems to argue that OOP is bad but what I gathered from it is that it argues that complexity is bad and that we should make things simple. The problem is that complexity is unavoidable and even if we make every part individually as simple as possible the final system will still be complex and hard to understand and test. OOP was supposed to help build the simple parts and then system would be easier to understand. It failed, not because it is inherently bad but because it enabled people to build more complex systems at which point the end result became hard to understand and test. FP might help a bit by forcing certain style of development which could make current systems easier to understand but the end result will be the same - it will reach the point where the systems built with FP style are hard to understand and test. What we should be developing is software to help us understand complex systems - both software systems and real world systems - and then the style in which software is developed will become less important and we will be able to understand how the system is working as a whole and drill into how individual parts are interacting. A good version of this software would allow more complex system to be created but it should also help with understanding them regardless of the level of complexity.
- dboreham 5y agoConjecture: programming is hard, especially as the scope of the system becomes larger and the problem domain more complex. This means that all programming tools and techniques have at least some problems and downsides. It also means that any solution involves trading off various factors, e.g. code is fast or easy to read but perhaps not both. All this means that you can pretty much point to anything in our field and laugh heartily at how piss poor it is. You can do this with FP too. But FP isn't used so much for real world solutions <ducks> and therefore statistically you will find many more things to laugh about in OOP which is very commonly employed against real world problems.
- deltaonefour 5y ago>But FP isn't used so much for real world solutions It's taken over the front end. The react paradigm is FP. SQL read queries are FP.
- z5h 5y agoAnd, in fact, much of the front end ecosystem is constantly getting ideas from Elm which is pure FP… and a pleasure to use (I think).
- arrow7000 5y agoI work with Elm and yes I can confirm this
- Const-me 5y ago> The react paradigm is FP. https://reactjs.org/ https://reactjs.org/ homepage writes "Build encapsulated components that manage their own state" That's a textbook definition of OOP.
- deltaonefour 5y agoI use the term colloquially. The typical react pattern people use does not put state in the component. It uses a reactive pattern called redux and the state comes from somewhere else.
- f38zf5vdt 5y agoI don't really understand arguments for or against OOP. OOP, to me, has always been about blackboxing some data entity and interacting with it through an API. Where it got wild and wacky was inheritance, but there's nothing fundamentally bad with having a process or object with an internal state you interact with via an API, e.g. a microservice. Most computer programs have an internal state that you interact with through some API. And sometimes you need to compartmentalize a process and have it work independent of another process. There's literally no way to get away from programs with an internal state and API access since that's how computers, and electronics in general, work.
- indymike 5y agoI'm convinced the big win with OOP was more about modularity and encapsulation than OOP. The whole object.method() or object.variable model was pretty nice after spending years dealing with global soup or using naming conventions. The not-so-good part in particular happened when you inherited one too many times... very easy to write, and very hard to debug, maintain, and sometimes test. A lot of OOP's success it was timing - OO showed up right around the time that we started building large gui apps. Now we have a lot of languages that do a great job doing encapsulation at the module level, which seems to be "good enough" and functional and procedural code seems to work pretty well, and be pretty easy to maintain at the module level.
- MaxMoney 5y ago
- activitypea 5y ago"Why isn't functional programming the norm" discusses your points. If you haven't seen it, it makes a great in-depth argument for why you're right :)
- indymike 5y agoThank you for confirming my biases :-)
- deepsquirrelnet 5y agoThis is my thought as well. There are still good reasons for using inheritance. In the right use cases, overloading methods can be a life saver. But generally, I have gravitated away from using those patterns, and toward things like composition, which are simpler and seem to be much less fragile. Recently, I've enjoyed the simple utility of python's functools library. Small-inheritance-like functionality seems to find a happy medium in a lot of cases, while avoiding a lot of unnecessary abstraction and boilerplate.
- MaxMoney 5y ago
- mmphosis 5y agoWe have data and complex systems. No one, with the exception of Alan Kay, has convinced me that Object Oriented Programming is or was a good idea. “… Because the problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.“ —Joe Armstrong, creator of Erlang programming language
- nomel 5y agoBut, thats exactly the reality of the problem, and exactly what you want. I work with robots, so much of it is physical. There are no floating bananas in the world. They're all held up by something.
- rdtsc 5y agoThe key that Joe was trying to make I think was that the forest and the gorilla have to be explicit: State2 = update(State1, ArgX), State3 = update(State2, ArgY), As opposed to, say: obj.update(arg_x); obj.update(arg_y); obj holds a gorilla and the jungle, and it may be hard to know how update method works because there is a complicated diamond shaped class hierarchy, and then a thread may concurrently modify parts of it behind our back. You're just trying to add a method or fix a bug, but it's almost impossible because we don't know it affects the gorilla and the whole jungle.
- amai 5y agoThe problem is that setters are usually void functions. Instead they could return the new state/object State2 = obj.update(argx) State3 = State2.update(argy) But if you do this people will argue this is inefficient, because you are copying a lot of objects.
- rdtsc 5y ago> But if you do this people will argue this is inefficient, because you are copying a lot of objects. Syntactically it is annoying to some extent. But, just like the most important data gets saved to a database with lots of "ceremony" involved -- separate protocols, transactions, SQL statements, etc, because it's pretty important to track updates carefully. Here ,it's a bit like that, but on a smaller scale as in memory program state is also important, and has to be tracked explicitly, and for that some "ceremony" is acceptable. Implementation-wise, because of immutability, there is copying but it is often not 100% duplication. The updated version and the previous one behind the scenes (in heap) might share a lot of common structures. For example, if we have a 1000 element list L, and we updated it with a new element at the front L1 = [H | L], then L1 and is not a complete copy of L, but instead is just element H and a pointed to the shared tail L. For dictionary data structures (maps) something similar happens but there it's a O(log n) order of updates with everything else being shared. Definitely not as efficient as in-place updates in say C++ or Java but that's a price I'd happily pay.
- bedobi 5y agoAs a professional dev who has made a career out of working in oop languages and codebases, I agree, and it took me far too long to realize that when it comes to oop, the emperor has no clothes. To this day, oop advocates can't even agree on what oop even is or means. Apparently oop as envisioned by Alan Kay was supposed to work like cells in the body that pass messages between each other and take actions independently. Why? Who knows! It was never really explained why literally one of the most complex systems imaginable, one that we still really have very little idea how it even works, should be the model for what could and should probably be a lot simpler. Today's modern oop languages are probably very far from what Kay envisioned (whatever that was), but it's remains unclear why classes and objects are "better" than the alternatives. And before anyone goes and comments aksully code organization blabla like yes but code organization can be great or shit in oop or fp or procedural codebases, it has nothing to do with the "paradigm". Let alone that the entrenched, canonical, idiomatic coding styles of most modern oop languages encourage state, mutability, nulls, exceptions and god knows how many trivially preventable entire classes of errors. Granted, most have now started to come around and are adopting more fp features and ideas every year, but still. --- EDIT tacking on other old comments: --- Don't get me wrong, writing programs like cells in the body that pass messages between each other and take actions independently is an interesting idea which deserves pursuing, if nothing else but to satisfy our curiosity and seeing to what if anything it's applicable and suited. (and even if the answer turns out to be "nothing", we've still learned something!) But going from there to making strong claims about it being a more or less universally superior paradigm for computing and writing code, with little to zero evidence, that's a huge, huge stretch. To the degree Erlang and Actors work, I think that's kind of a happy coincidence, and not due to any rigorous work on Alan Kay's part. --- Just look at all the "OOP" languages where both the language developers and the user community are coming around to the facts that * immutability and absence of state is preferable to mutation and statefulness * Option/Maybe types (or "nullable types" which are a shoddy implementation of the same thing) are better than null * Either/Result types are better than exceptions * making things implement map, filter etc and sending in a function that describes what you want to do is better than manually eg looping through lists etc etc etc etc Anyone who doubts how endorsed this is, just read what Brian Goetz and Josh Bloch have to say about how to code in Java. Just imagine if these languages had been implemented with these ideas in mind from scratch instead of the current situation of trying to adopt and retrofit this style when the core libraries fundamentally don't support it. The current trend of "OOP" languages is basically inexorably heading towards FP and abandoning the old school "OOP" style. Eventually they will only be nominally "OOP", mostly in order to please people who have irrational attachments to labels like that, but be way more FP in nature and in all but name. For what it's worth, people shouldn't be irrationally attached to the "FP" label either. Labels aren't important - what matters is the code, how easy or hard it is to reason about it, how well it avoids entire categories of defects from even being possible etc etc. https://proandroiddev.com/kotlin-avoids-entire-categories-of-java-defects-89f160ba4671 https://proandroiddev.com/kotlin-avoids-entire-categories-of...
- kwertyoowiyop 5y agoYou know what is even more valuable? Good documentation outside the code, and good comments in the code.
- cryptica 5y agoThose who hate OOP have never used OOP correctly. None of these articles mention 'cohesion' or 'coupling'... It's not possible to critique OOP unless you understand the principle of loose coupling (ease of substitution) and high cohesion (clear separation of concerns/responsibilities). Without loose coupling and high cohesion, your classes will not be composable which is the whole point of OOP... These characteristics ensure that state is fully encapsulated and does not leak between multiple components (that's when it gets ugly).
- keithasaurus 5y agoAh yes, the classic "No True Scotsman" OOP defense.
- cryptica 5y agoI've provided a very specific definition of what good OOP requires so it's not fair to suggest that my argument is pointing to some vague characteristics or is evasive. I can look at any project's code and assign it a score in terms of cohesion and coupling of the classes/modules/components. Other people who are experienced with OOP can look at the same code and they will come up with a similar score.
- keithasaurus 5y agoThe point of "No True Scotsman" is that you have your own definition of high quality OOP, which is not universal. Maybe yours is the right way of doing things, IDK. But I think others would probably prefer different definitions. For a lot of people, this variation in opinion of how OOP should be used can lead toward a conclusion that OOP in and of itself is a confusing concept and difficult to get "right". Some people, myself included, just try to avoid this complication altogether, by separating data from logic.
- cryptica 5y agoFP solves some issues but simultaneously introduces a new set of issues which creates new 'No true Scotsman' debates around ways to address those new issues... It's like the joke that there were too many competing standards and so somebody decided to invent a new standard to make all the other standards redundant... The net result of this is that we end up with n + 1 competing standards. IMO, the biggest problem I often see with FP code bases is poor separations of concerns which leads to spaghetti code which is hard to read and maintain. When some state is not co-located the logic which is supposed to be operating on it, you're already throwing high cohesion out the window... And when you do that, it makes is harder to separate the responsibilities of different components because there is no clear ownership relationship between the logic and various bits of state... With FP state can end up being mutated all over the place and it's hard to know who did what.
- rcgorton 5y ago
- deleted 5y ago[deleted]
- lincpa 5y ago
- spaetzleesser 5y agoI can pretty much guarantee that whatever the "OOP is bad" guys think people should do instead will be viewed as "bad" in a few years. I was around when OOP got into the mainstream and it started out as a very nice and practical approach. Then the ideologues came in and complained loudly "this is not OOP" so suddenly you had to wrap simple functions into meaningless objects. Then you had to inherit a lot and create these huge inheritance trees. And so on. Complaints that things got too complex were squashed. The same will happen with every technique or process that becomes popular and consultants, authors and mediocre but loud people take over. Happened with OOP, Agile and will happen with other things too. When I look at the Kubernetes, microservices, "need to scale just in case we may grow by 100000% soon" monstrosities we are building to deploy simple CRUD apps I don't think we have learned much. People still take useful techniques, make them into a religion and push the techniques to the point where they are becoming a liability.
- Subsentient 5y agoHaskell gives me headaches. I write a lot of Rust, which has elements of both. I think their approach is pretty good, though sometimes regular inheritance would just be easier. I don't hate OOP. I don't love it either. I tend to write my code in a mix of procedural and diet-OOP paradigms. It tends to produce less state, less inter-dependencies, and doesn't require abandoning stuff like mutable state. Why do I want mutable state so bad? Because it's the easiest, least abstracted solution to the problem much of the time, and closer to what the compiler will actually want to generate. I think trying hard to stick to a single paradigm is folly. I like mixing and matching according to the task I'm attempting to accomplish, and I have a firm conviction that my code benefits from this ideology. Encapsulation I do value, but not as a "hard no". I use access specifiers to tell you "you probably don't want to mess with the guts of this thing, it can take care of itself better than you can." As for inheritance, I don't use it very often. I like how C++ has no base "Object" class. A lot of the time I'm basically writing structs with methods, and I think that's often the right approach.
- _9omd 5y ago>diet-OOP paradigms Ha nice, I love the idea of calling it diet-OOP. "Diet-OOP, same great productivity with 99% less inheritance!"
- zamalek 5y agoMy issue with OOP is: Design Patterns: Elements of Reusable Object-Oriented Software. I don't take issue with the authors, with their insights, or anything related to the content of the book. It's that the book exists at all: it's a book filled with solutions to imaginary problems. When using a procedural language the first thing you do is start implementing a solution. When using OOP, you first have to solve the imaginary problems created by OOP, only then can you start down the path of typing out a solution. It's significantly more difficult to refactor OOP (even with great tools) than it is procedural. If you could spend 20% less brain power, possibly 40% fewer keystrokes to describe the exact same solution, why wouldn't you?
- _pmf_ 5y ago> it's a book filled with solutions to imaginary problems. Have you even read it? I'd say it has more deep real world examples than almost any other SW engineering book I've read.
- fulafel 5y agoIME it happens often that these categories overlap, when software gets entangled in incidental compexity.
- ecshafer 5y agoDesign patterns as a concept exist without OOP. Even in procedural code or functional code you have concepts like a strategy pattern, or how do I get version X vs Y of object A. These things arise in any code you are writing a sufficient complexity.
- wackro 5y ago>solutions to imaginary problems This is a fundamental misunderstanding of what patterns are. The GOF book is used to this though. A design pattern is someting that will naturally crop up if you adhere to certain design principles. If you follow a principle of separating instantiation logic from other logic then you will start to see factories. If you combine multiple complex parts of your code into simpler ones then you will see facades. GOF is a reference book for some patterns that have been observed as being common, with examples that are essentially academic. It is not a how-to guide for OOP.
- lkrubner 5y agoFor my part, I've tried to be as overstated as possible, as you can tell from the title "Object Oriented Programming Is An Expensive Disaster Which Must End." Written in 2014, and discussed several times here on Hacker News, it remains the most popular technical essay that I've written: http://www.smashcompany.com/technology/object-oriented-programming-is-an-expensive-disaster-which-must-end http://www.smashcompany.com/technology/object-oriented-progr...
- zackees 5y ago
- kazinator 5y agoThe author of this article thinks that OOP basically means adding vtable pointers to the heads of structures, and shallowly dismisses multiple dispatch.
- emrah 5y agoHere is a different take: OOP is not evil. State is not evil. They exist for a good reason: Procedural is "linear" while OOP is "layered". One could write code either way but OOP better resembles the physical world and since brains have grown up in the physical world, layered code is easier to grok. It can hide/show pieces such that you can inspect functionality in a controlled way. Of course procedural can do the same with functions but it's coarser. State is also a property of the physical world. Things persist, stuff accumulates, that's just how it is. Since applications ultimately model things in the physical world, they also have to persist things and accumulate things. State is inevitable. OOP is a sharp tool and of course it's possible to use it well or cut one's self really badly
- ummonk 5y ago> OOP better resembles the physical world and since brains have grown up in the physical world The part about OOP which doesn't resemble the physical world though is encapsulation. Encapsulation is like pretending the world functions in passive voice, with objects doing things to themselves.
- djmetzle 5y agoMeh. Is this a hot debate still? No mention of Ruby or smalltalk in this post, which i think of as "true" OO languages, down to the runtime. The ruby object model has its merits! Sandi Metz's POODR is a fantastic intro into OO _and_ a compositional approach to design. FP vs OO is always a false dichotomy for sure. Actors and messaging appear in FP languages. Inheritance surely has nothing to do with OO. Inheritance means nothing for data, and it's almost a bug to extend Record types. In short, this post seems to rage against inheritance and blind use of design patterns, not the spirit of OO. But the post also qualifies that "that is what an OO advocate would say". Consider Typescript. The same program can be written with `class`es, or as a module of "loose" types and functions. Really, lets pick a mix that best represents the problem we're solving? I think OO can be a _useful complement_ to FP and other paradigms.
- ecshafer 5y agoI only played with Small talk in school as it was before my time but it was great. As I am working at a large Ruby shop currently, Ruby is a lovely language. Ruby really does solve many of the issues I had with Java. Its a very elegant language. I think the behavior of any object taking messages is great, though thats not used much in professional code it seems. I think more people should give ruby a shot. I do wish it were a bit faster ,but hopefully truffle ruby, sorbet, yjit, etc. can put in the work to fix that.
- shepherdjerred 5y agoI completely agree with this. I love writing functional Java. The issue is mutation, not OOP
- dopidopHN 5y agoWould you have any resource on functional Java? My experience with 8 and onward is better for sure. I find myself writing more robust filtering / map-reduce logic. But that’s kind of it. For instance I don’t feel like function are first class citizen still. ( I almost never user higher order function in Java, even if it’s possible )
- thangalin 5y agoThe PersonnelRecord isn't OOP and exhibits a widespread misunderstanding: class PersonnelRecord { public: char* employeeName() const; int employeeSocialSecurityNumber() const; char* employeeDepartment() const; protected: char name[100]; int socialSecurityNumber; char department[10]; float salary; } As written, PersonnelRecord class will inevitably lead to code duplication, tightly coupled classes, and other maintainability issues. An improvement that's still not OOP, but exposes a more flexible contract, resembles: class Employee { public: Name name() const; SocialSecurityNumber socialSecurityNumber() const; Department department() const; private: Name name; SocialSecurityNumber socialSecurityNumber; Department department; Salary salary; } OOP is more about the actionable messages that objects understand to carry out tasks on behalf of other objects. Wrapping immutable data exposed via accessors reaps few benefits. Rather, OOP strives to model behaviours that relate to the problem domain: class Employee { public: void hire(); void fire(); void kill(); void raise( float percentage ); void promote( Position position ); void transfer( Department department ); private: Name name; SocialSecurityNumber socialSecurityNumber; Department department; Salary salary; } This allows for writing the following code: employee.transfer( department ); I don't know how to "transfer" an employee given the code from the article, but it would not be nearly as elegant.
- vikingcaffiene 5y agoI dunno man... I think that giving an entity the ability to perform operations upon itself and thereby changing it, looks neat in these examples but scales poorly in a sufficiently commplex codebase. You could express exactly the same thing but get a lot more bullet proof code if you separate out the thing doing the action from the thing you are acting upon. You could have the thing doing the action return the updated version of the thing you wanted to do said operation upon and its unambiguous what has happened. So something like (psuedocode): transferredEmployee = employeeService.transfer(employee, department); IMO this forces a certain style of coding that ages better and requires keeping less stuff in your head. My two cents. Have a good one!
- 5y ago
- synergy20 5y agoI have no idea about the points that post is trying to make. OOP like everything, using it incorrectly will lead to trouble, and it has its merits when done right. plus, it's used widely in practice that is really the best evidence in that, it's not bad at all. use FP all the way IMHO will lead more spaghetti code, use it to complement OOP could be great however. Last, what's the alternative? if you don't have a better alternative, you don't solve any existing problem.
- deleted 5y ago[deleted]
- woggy 5y ago> To see where the problem is, just think about this: If int/float were separate modules that do not depend on each other, where the (int,float) and (float,int) pairs should be defined? Nowhere? Somewhere? In either one of the modules but why? I'm confused by this argument against multiple dispatch. Can't there be a third module that references both?
- leephillips 5y agoOf course there can. The objection makes little sense.
- iamwil 5y agoThere can be, though what would you call this 3rd module?
- _9omd 5y agoI never understand all the hate for certain tools. OOP is a tool, FP is a tool, and other programming paradigms are different tools. If you're bad a software architecture and you tend to write convoluted OOP software, you're probably also going to make a mess using FP as well. Applied correctly, they can both be great tools for different problem sets. Writing something that inherently has a lot of state, like a simulation, game, or user interface? OOP might be a good choice. Working on a backend API that's basically a database wrapper, a data processing pipeline, or something else with less inherent state, FP may be a better tool. Choose the rights tools, design good architectures, and stop blaming the language paradigm.
- derbOac 5y agoI generally feel the same, although I can say just as a pragmatic issue, the biggest problems I have ever faced in programming by far have been in dealing with poorly structured inheritance systems and object hierarchies in other peoples' libraries. Bugs are inevitable but problems with object hierarchies seem to screw up everything unnecessarily in a way that doesn't happen in less object-oriented functional and procedural languages. Sometimes it feels like this extra layer of ways to shoot yourself in the foot, and the feet of everyone around you. Strong typing can be a blessing and a curse, and screwing up type signatures through poor foresight can be a problem regardless. But get into elaborate object systems and it can be a different level. When they're done well it's no problem, but when they're done poorly, it's maddening.
- exdsq 5y agoI do feel OO is the default for almost all companies and that requires a lot of debate to start to change so you can use other tools though. I remember working for a C# shop where I had to do some pretty simple data ingestion and cleaning from the NHS API that would have been fantastic in F# with it’s composition patterns, pattern matching, and type system. However because it wasn’t OO I couldn’t get support and so I had to write a lot of factories instead.
- edwinyzh 5y agoCorrect. Complains against OOP is like complaining a hammer not suitable for a task which you should have picked up a wrench in the first place.
- capitalsigma 5y ago> On claims of unit testing and OOP, I'm not going to go there much more because I still don't unit test my stuff. I'm currently not against it. I just don't know about it much. I find it much easier to formally verify things correct than to test that they're correct. Ah, I see, OP has never written nontrivial code.
- Mikeb85 5y agoThere's a reason most complex software uses OOP. Functional programming is nice, sometimes, but as projects grow it ends up using patterns that do essentially the same thing as OOP. A monad is basically an OOP object. To see a language that is purely OOP but also forces you to be very explicit about accessing state, check out Pony language.
- chii 5y ago> A monad is basically an OOP object. i think it's the other way- an OOP object is a poor imitation of monadic algebra that cannot be generalized with mathematical rules to guarantee certain properties.
- galaxyLogic 5y agoTake any Object-Oriented language. Then modify its definition so that any class can have just a single method (as opposed to any number of methods). You now have a new language which you could call a procedural- or functional language based on the set of features that were present in the language you started from. But it is no longer an Object-Oriented language. To make it more concrete start with Java compiler but modify it so it only allows max one method per class. You now have NOOP-Java. (Non Object-Oriented Java). Are you happy? Is this NOOP-Java somehow better than the plain old Java? If not really then removing the OOP-ness did not really help did it?. OOP is good. You want to keep OOP, not remove it. OOP lets you have multiple functions associated with a data-structure the details of which you hide behind those functions (a.k.a. methods). I think THAT is the essence of OOP. You can have multiple functions attached to the same data-structure and only those specific functions can read and write that data-structure. Isn't that something that really is so useful that getting rid of that feature, getting rid of "OOPness", would be crazy?
- mike_ivanov 5y agoPut shackles on your feet then try to run. Now, cut off your feet completely and try to run again. See? Shackles were good for you.
- d--b 5y agoWe’re past this turf war. The original “case against oop is overstated” is an attempt to go beyond the gap. It was an article that said “sure oop has problems, but it’s not all bad, maybe we don’t need to throw it all away”. And then there is this article who just goes through more articles trying to re-ignite the debate. It’s silly.
- kgeist 5y agoI've come to like "service-oriented programming" we use at work (I don't know if there's a name for it). Basically, your code is essentially procedural, but instead of free standing functions you use stateless service classes hidden behind interfaces: it gives you very granular namespacing, implementations are swappable, composable, decoratable and testable. In this system, the models (records) in the domain model are more like classic OOP (objects like "car", "banana") and they have encapsulated state, but only to have a centralized place where you make sure object invariants are upheld whenever their state is mutated (by services), and nothing else. The hard part is interoperation/invariant validation between multiple objects (aggregates or just related data) and we haven't solved it yet in a consistent manner (everyone comes up with their own approach, for example state propagation via events).
- givehimagun 5y agoIsn't this Domain Driven Design? I think you understated how easy it is to test in your example. Tests can move from CD to CI because of your architecture. I would love to see more discussions about the tension between scale and test-ability.
- nsajko 5y agoIsn't OOP mostly just a buzzword?
- EdwardDiego 5y ago> I'm not going to go there much more because I still don't unit test my stuff. I'm currently not against it. I just don't know about it much. Ouch, not even unit tests to catch regressions? So many of the bugs that I deal with in $BIG_FOSS_PROJECT are regressions where a bug fixed in version X.Y.5 was reintroduced in X.Y+1.0 by someone's cool shiny new feature. And yes, there's a significant lack of unit tests in some of these errors, plus some hard to test code. (While I'm happy I can use Mockito to mock static methods now, the fact that I have to is a very definite code smell). Which is why I recommend never installing version A.B.0 of $BIG_FOSS_PROJECT. I always wait until everyone else finds the new bugs for you, then install A.B.1.
- dvt 5y ago> Ouch, not even unit tests to catch regressions? I also don't like unit tests and very rarely unit test. I think they provide a false sense of security and were invented by corporate software shops to better quantify "units of work" (oh, how many times I've had unit tests assigned to me in tickets!). If you can't formally prove something doesn't break (in your head or with pen & paper or via pseudocode), your code is too complex. There are a few exceptions to this, but they are highly technical (e.g. FFT, cryptographic, physics/math implementations, tricky pointer arithmetic, regular expressions, etc.) where a hard-to-see typo can actually break things in non-obvious ways. Most code is not that -- it's just written poorly (because code standards aren't enforced). Linux is a great example of a project where coding standards are annoyingly enforced (and there's no real "unit" testing) and lo and behold, the code is of exceptional quality.
- EdwardDiego 5y agoI'd rather have an existing suite of tests that I can use to verify that when working with other people's code. And more importantly, if JIRAISSUE-15295 is reproducible, then a unit test that a) reproduces it and b) verifies that the bug no longer occurs, is invaluable to prevent someone bringing JIRAISSUE-15295 back from the dead. Of course, if the unit test is too tightly coupled, and has too many insights into code it shouldn't, then it's worthless as JIRAISSUE-15295 will most likely reoccur via a different code path. But, poorly written unit tests aside, I have found significant value in unit tests when maintaining a rapidly changing code base.
- psychoslave 5y ago>I find it much easier to formally verify things correct than to test that they're correct. This rise in me the famous joke by Knuth: Beware of bugs in the above code; I have only proved it correct, not tried it. I wonder which tools he uses to prove correctness, and on which language. I know about Frama-C, Coq, and things like that. But I never had the opportunity to use them out of university. On the same topic, in a recent ACM publication, Ian Joyner compare Frama-C with a lipstick on a Pig. https://cacm.acm.org/magazines/2021/12/256941-common-ails/fulltext https://cacm.acm.org/magazines/2021/12/256941-common-ails/fu...
- kqr 5y agoIn that case I think Knuth referenced proving it by hand, e.g. with Hoare triples. You could argue that hand proof is useless, but by forcing yourself to go through it in tiny steps you can actually sort out a lot of oversights.
- edwcross 5y agoC is a pig of a language, so tools that show just how horrible it is, how many bugs are unwittingly written, and how hard it is to make its code safe, could also help pushing people towards better languages. These tools are more like putting on X-ray glasses and seeing how your fast-food nuggets are made. You will still eat them if you have to, or if you're in a hurry, but you'll be more inclined to take the time to learn cooking, so you can eat healthier food later.
- pronlover723 5y agoWhat's the pattern for implementing a cache without state? How about a command buffer? Not trolling, seriously curious.
- renox 5y agoOTOH: 1) Most of the time GUIs use OOP, and its the "other designs" which have a hard time being successful. 2) The rejection of multiple dispatch is very "hand wavy", a lot of Julia's success is linked to its multiple dispatch feature.
- Enhex 5y agopeople who hate "OOP" are usually ones that fail to understand how to use some language features. prime example is "Circle–ellipse problem" which demonstrates how people fail to realize inheritance is about code reuse and not about representing hierarchies of abstract ideas (and i wonder where they got that wrong info from, perhaps they extrapolated it from the name "inheritance"?). same goes for all the other language features.
- lysecret 5y agoSo I only do data engineering, backend APIs, Data Science and Machine Learning. And so many times i learned something about OOP, i go excited I implemented it and i ended up with a solution that was really complex and I re-implemented it using functions and procedural code. However, i do love a library like pandas with their data frames and series etc. which are two really cool and powerful abstractions / classes. I also noticed this trend in Python/ Data Developers (including myself),that they start writing mostly procedural code and at some point they feel like they "have to" move to classes to be more sophisticated. Maybe I am also just bad at finding good and easy to understand abstractions that you can re-use like a data frame. But maybe when it comes to data this is just quite hard? Would love to hear about other data-peoples perspectives about OOP. Also the thing with data engineering the state lives in a DB or a file and not really in my class (because its soo large).
- bjourne 5y agoI wholly agree with this. The problem with OOP is that software are tools that are about processes and workflows. They do things. Processes and workflows are notoriously difficult to model using OOP methods (one reason why design patterns were invented) but actually quite easy to model using imperative or functional programming. I use this software to listen to songs in mp3 format. It plays songs through my computer's audio subsystem. Trying to model this using classes and objects that interact with each other - one for the player, one for songs, one for user input events like pressing forward and pause, one for the audio subsystem, one for the playlists, one for timing events, etc - will not make the software less complex. My view is that software are like fractals. That is, self-similar and there is no difference between the micro and macro scales. What is right on the micro scale is right on the macro scale and vice versa. What is wrong on the macro scale is wrong on the micro scale and vice versa. Is it "wrong" to implement sorting algorithms using OOP? Yes. Then it is also "wrong" to implement music players using OOP.
- vanderZwan 5y ago> That is, self-similar and there is no difference between the micro and macro scales. That's quite an interesting way of framing it, I've never considered whether or not software has a "you shouldn't mix your micro- and macroeconomics" problem or not. Is your conclusion that they are the same at scale based on gut feeling/experience (which I don't mean in a dismissive way, experience is a valuable source of insight) or do you have some concrete examples to elaborate why you think that?
- bjourne 5y agoIt's just my gut feeling based on experience. I have never seen software problems that are fundamentally different on the macro scale from the micro scale. I have never met anyone who was great at debugging segfaults in C code that was not also an amazing architect. I have never met a great architect that wasn't also amazing at debugging segfaults. To me software development is like math and there is no material difference between "high-level" math and "low-level" math.
- jokoon 5y agoI was able to hold a job at a big company with a large C++ codebase, in the millions of line of code, for 2 months. I was amazed how people there were able to deal with the amount of BS that this code was. I honestly don't have the motivation to thrive with such work, it's deeply non-sensical. It really struck the confidence I had in C++. The code structure had so much technical debt and non-sense, that most developers never really dare say how awful it was. I was impressed by the blind humility of all of this, it seemed like a very elaborate game of hot-potato-passing and it-s-not-my-fault. Of course this software team was thriving, because it was in a monopolistic domain that would always rain money to write this software, even if it was bad. The manager was a highly motivated guy, very humble, but he also seemed a bit delusional, because fixing this software was going to take at least 5 or 10 more years. OOP sounds like an utopian abstraction, some kind of "smartest guy in the room" stuff. It's like pure mathematics trying to do practical physics and engineering. It just doesn't work. It's really time academics start to highlight the dangers of abstraction, and start writing some philosophical approach to software engineering and how to solve problem IN PRACTICE. Personally, I mostly use namespaces to "encapsulate" data, behavior and code. I just write functions and use data oriented programming, even in python. It's funny how people finds this inadequate and bad practice. I never share code because I'm afraid to go in an argument because of it. Code that use classes, inheritance, private/protected access, is just impossible to read and follow. It's just obfuscation to me. Unless you're writing a library that is used by many, meaning it requires well-structured inheritance, 99% of developers should not write OOP. I will never forget this hackernews comment mocking people who were presenting their project, praising how complex it was. OOP seems like it's the main method used by "hostage takers" to make their code only readable to them. In any kind of engineering, simplicity MUST PURSUED AT ALL COST. Only use complexity as a last resort, and FIRE developers who are unknowingly becoming hostage takers, and who keep innocently arguing that if they can understand their code, anyone can. Advocate of OOP will cost a lot of pain to future developers.
- jillesvangurp 5y agoThe author has a point. Yet, most mainstream languages provide OO features; especially many recent ones. Even languages like Rust and Go have some limited OO features. And many languages also add features common to functional programming languages. So, I guess the consensus among language designers is that it's not all bad. I would say early OO is very different from what is practiced today. I use Kotlin mostly. It's obviously an OO language but it puts some interesting twists on it relative to earlier languages (like Java): - classes are closed by default and you must define them as open to be even able to create a subclass. When you do, you must explicitly label things in classes that you override. This prevents, un-intential abuse of inheritance that is common in many Java frameworks. E.g. Spring has riduculously deep inheritance hierarchies. When I was still using Java I had a simple rule: any form of class extension is probably something I need to get rid off. Delegation is just preferable in my opinion. I almost always end up regretting class extension to the point where I rarely consider using it. - Speaking of delegation, the Kotlin language designers obviously agree with this and added interface and property delegation to the language. This is just syntactic sugar but it's awesome. I can take any class and pass myMap: Map<Foo,Bar> into the constructor and then add implements Map<Foo,Bar> by myMap. And just like that you have extended a class but without actually extending it. I can even override some of the methods (because it implements the interface). They basically provided syntactic sugar for a common design pattern: delegation, which you should almost always favor over inheritance IMHO. Property delegation is equally powerful and you can use it to e.g. lazily initialize a property foo: String by lazy { someFunctionThatReturnsAString() } - it encourages the use of val variables that cannot be reassigned. If you want that, you need to use var. If you define a var and don't reassign it, the compiler will warn you to use a val instead. Immutability by default is encouraged and it helps with e.g. asynchronous code and a few other things. - it has sealed classes (and interfaces) as of a few versions ago. The advantage of those is that the hierarchy is closed after compilation. So you can't add more sub classes and this benefits the compiler doing some optimizations. Likewise, value classes are now a thing. In the rare cases I do use inheritance, I use sealed classes. - it actually discourages class extension in favor of using extension functions and properties. This is much cleaner and does not suffer from a lot of the problems associated with inheritance. For example, you can't actually override anything this way. Extension functions are surprisingly useful and I use them a lot. They even work on type aliases or on nullable types. So you can call a function on a null value for e.g. a nullable generic type T and it's not going to trigger a null pointer exception when you do that. More languages should add this. This just removes a lot of use cases where you might have used inheritance or interfaces in the past. This also removes a lot of the need for multiple inheritance; which is problematic in the few languages that still support that. - having default values on parameters in functions means that you rarely have more than 1 constructor for classes. You can add more constructors, but it's just not something you'd need often and certainly not to support different combinations of properties. Constructors have no body either. All that happens is assigning properties. This enforces the sane rule that constructors must do no work. If you need to do work on class creation, you add an init function. I'm sure some language designers have plenty of nits to pick with Kotlin. But for me it's a very pragmatic language that mostly manages to nudge people to do the right things while providing them with a lot of convenience. Scala people tend to look down on it for example and that language does have some interesting features. But then I find most Scala code to be utterly unreadable because. Purity has a price, I guess. And of course many Scala coders consider its OO legacy to be somewhat of a mistake apparently.
- _ZeD_ 5y agoevery time I see this kind of posts I remember the good old "Qc Na" koan[0] > The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures." > Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress. > On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened. [0] http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/m...
- hackerfromthefu 5y agoThe truth is that neither FP or OOP is the silver bullet. Both have good techniques, that shine for certain types of problems. The more important thing is how you do it, how good you are at it. It's the same thing with e.g. Agile, some people make a mess of anything including agile, some people do it well, and the vast majority of average people get average results with Agile. So don't waste time getting stuck on one particular school of evangelism, try a range of techniques and get good enough at all so you can match the ideal technique to the specific solution you're creating.
- bergkvist 5y agoInheritance in OOP is what I like to think of as "structured patching". When you create a .patch-file with `git diff`, you are essentially creating an inheritance hierarchy. Imagine having 5 patch files that are applied to the same code file in sequence. This is analogous to an inheritance hierarchy with 5 levels. patches/inheritance is a very useful tool when you want to make some changes to third party code you depend on before using it - while minimizing the maintenance burden of these changes. Inheritance/patches is also a very useful tool for describing/representing changes to your own code, but only as a temporary measure - you want to flatten out the levels of inheritance/patching for readability. With .patch-files, this can be done automatically. With OOP/inheritance, this is more of a manual (although still straight forward) process. A git repository with 1000 commits is essentially an inheritance hierarchy with 1000 levels. Note that git will automatically flatten out these patches when you check out a certain commit - which is what makes git such a great/usable tool. Imagine if git could not do this flattening automatically. Code bases would quickly become unmaintainable if they wanted to retain their change history.
- eternityforest 5y agoWhenever I hear complaints about a popular programming method, I have some real doubts. Modern software gets better every year. There may be better ways, but what we have works. I don't know if the modern world would be possible without OOP. If the only language in the world was Haskell, C, and SQL.... would I have actually learned them, or would I have chosen a different career? Would there be enough devs to have as much software as we do now? It's hard to tell, because almost everything big is written using OOP. Few things on the scale of LibreOffice or Blink are pure functional. And Java seems to work exceptionally well for large scale projects.
- softwarebeware 5y agoThat's because what people call OOP isn't OOP. > “I invented the term object oriented, and I can tell you that C++ wasn't what I had in mind.” —Alan Kay. Read here for more info: http://xahlee.info/comp/Alan_Kay_on_object_oriented_programing.html http://xahlee.info/comp/Alan_Kay_on_object_oriented_programi...
- tomtheelder 5y agoWhat people call OOP is OOP, literally by definition. Alan Kay may have coined the term, but his version of OOP has nothing to do with what is commonly understood today, and is therefore irrelevant.
- softwarebeware 5y ago> What people call OOP is OOP That's silly and not how definitions work. definition noun def· i· ni· tion | \ ˌde-fə-ˈni-shən an explanation of the meaning of a word, phrase, etc. : a statement that defines a word, phrase, etc. In other words: words or phrases have actual meanings, regardless of what people call them. To give you an example, people use "their" instead of "they're" all the time. It doesn't mean that "their" means "they're".
- commandlinefan 5y ago> If I were smarter than I am, I might have went deeper on this regard. Can't tell if this is deliberately ironic...
- ncmncm 5y agoTl;dr: [nothing, really.] "(Anything)-oriented programming" is obviously stupid: the world doesn't conform to your (anything), whichever you choose. QED, an (anything)-oriented programming language will be the wrong thing most of the time. A general-purpose programming language needs to provide support for solving actual problems, whatever they are. Any program big enough to be interesting addresses sub-problems of different kinds, that each need their own treatment. Most problems benefit from a mix of approaches. Once in a while objects are exactly the right thing. Then, if your language has stuff for that, lucky you; otherwise you need to cobble something together. Likewise, when any other formalism matches. Almost always when people complain about OOP, it is because they want their (other-thing)-oriented language to get respect. That does not end well: the same arguments against OOP apply equally well to their thing, given trivial adjustments. So, nothing to see here.
- psd1 5y agoAwful writing. Rambling and incoherent. I do not know what the author was trying to say. > I just recently figured out myself the pieces I was missing to writing effortlessly skimmable texts. No; no, you didn't.
- TrapLord_Rhodo 5y agoThe rust book has a great section about OOP and i think solves alot of the issues discussed in these articles at length. http://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/second-edition/ch17-00-oop.html http://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/sha...