Becoming a professional Haskell and Erlang developer really shifted my view on OOP (let OOP denote class based OOP as found in Java or C++). In my view, OOP is prove a poor model for computation, and the result has been that OO code is almost always significantly more complex and error prone than an equivalent computation written in a concurrent, functional, or structured paradigm. Recent trends in language design (s…
Also for those of you doing OOP looking to try something different: Java/C++ -> Rust: It will feel familiar to you with its C style syntax and multi-statement function bodies. It takes the best parts of many different paradigms, and marries them in a very coherent way. It's performant, has incredible tooling (cargo, rustup), and the community is great. Python/Ruby -> Elixir: Elixir has the Phoenix framework, great su…
OOP Is Dead, Long Live OOP
341–350 of 357 posts
Re: OOP Is Dead, Long Live OOP
#342Took me a long time to grok OOP and OOD (was introduced to OOP in '91). At first I thought I knew it, and then realized I didn't. Plane into the side of the mountain, no survivors, call off the search. Which is when I really started to learn (around '96/97). And now I love it. Until I come across people who always start by defining an interface first and then think about what might follow. And dependency injection. H…
DI is bad, what? So how are you writing tests then.
The only time this approach is really a problem is when doing slow calls such as I/O - eg. writing to the database. In such cases you can easily switch to an in-memory database or use a factory pattern (which is kind of like a hand-rolled mock).
It's true that an error in say Component C may generate many failures in test of for other components, but in practice that's not really a problem. Just pick one of the test failures and drill down until you find the root cause - fixing that cause will magically fix the other 55 test failures.
Re: OOP Is Dead, Long Live OOP
#343Becoming a professional Haskell and Erlang developer really shifted my view on OOP (let OOP denote class based OOP as found in Java or C++). In my view, OOP is prove a poor model for computation, and the result has been that OO code is almost always significantly more complex and error prone than an equivalent computation written in a concurrent, functional, or structured paradigm. Recent trends in language design (s…
For some reason 'arguments' against OOP seem to follow a common pattern. You have said many things against OOP, but you haven't actually presented an argument for why it's bad. I'll present each of your assertions here individually to clarify. > OOP is prove a poor model for computation > OO code is almost always significantly more complex and error prone than an equivalent computation written in a concurrent, functi…
From my view, here are the concrete issues I have with some of the OO flavors out there.
1) It encourages shared mutable state.
OO creates a new layer of shared state, the object fields. In its very essence, the idea is to have methods which accesses and modifies the object state through direct access of its fields. Thus each field is mutated by the object methods which directly access them. You need to look at the method code to know what state they read and write too. You can not make the fields immutable, because that renders non read only methods useless. You must thus coordinate access of the fields between the methods using explicit locks. Over time, in practice, it also creates massive classes with too many fields and too many methods that only make use of a subset of them, degenerating into even more of a globally shared state structure.
2) It makes dependency injection trickier and thus discourages its use.
Once again, the idea of methods to have direct access to fields is the cause of this, it means that methods don't have their dependencies injected, instead they go find them themselves, through direct access. Testing becomes hard, configuration is pushed down the stack inside the methods and reuse is made harder.
3) It makes inversion of control trickier and thus discourages its use.
Because code can only be passed around wrapped inside an object, and objects are heavy constructs requiring a lot of verbosity to create: a new file is required, a class must be defined, an instance must be created, etc. It means that in OOP it is rare to see code being injected from caller to callee. Instead, conditionals creep inside the callee, and configuration parameters are passed it.
4) It handles stateless code poorly, and thus discourages its use.
Code that requires no state over time, aka stateless operations must be wrapped inside a class for no good reason. OO provides nothing to such code. OO is designed for statefull code. A class with no fields, it's not useful. Why do I need one if all my code is stateless? So people start using them like namespaces.
5) Inheritance is too easy to mess up.
Inheritance as a mechanism for code reuse appeared to be pretty smart at first. The problem is it turned out its pretty hard to do right. You soon find yourself with hidden state from parents and confusing override hierarchies, which forced us into single inehritance chains, which limited code reuse, etc. Bottom line, it just created ton of hidden coupling.
6) Objects are not extendable from the outside.
You can't add functionality or state to an object from the outside. You need to modify the source code of the class directly to do so, or rely on defining new subclasses through inheritance. This minimizes code reuse, and encourages object code to grow ever so bigger as more and more features are added.
That's all I can think of for now. Now, some flavours of OOP work differently in that some or all of these problems might not exist or have solutions to them. Which is why I agree with you, it's best to know the actual problems so you can spot them. Just saying something is OOP doesn't imply all of them will exist.
A lot of languages allow stateless subroutines to exist on their own and offer a seperate namespace system not conflated with the OO layer. Trait or mixin like systems enable open extension. Inehritance can support multiple parents, or composition is used in its place. Some allow subroutines to also be passed around, not needing to be wrapped in an object. Dependency injection frameworks were added to simplify and encourage its use. Value objects allow a bit more support for immutability. Etc.
FP doesn't suffer from these issues though. That said, it has others in its place, and different FP languages have also found different solution to them. That said, in my experience with many languages that were more OO oriented and ones that were more FP oriented, I found FP overall had less issues and had found cleaner solutions to its limitations.
Re: OOP Is Dead, Long Live OOP
#344Earlier quoted context omitted.
Did you read the stuff between the parentheses?
In fact, I did. But I think it is wrong to judge OOP based on crude implementations. That is the reason why I added the Trabant example: > The Trabant was loud, slow, poorly designed, badly built, inhospitable to drive, uncomfortable, confusing and inconvenient. (source: https://en.wikipedia.org/wiki/Trabant ) Java and C++ are both great tools for specific jobs, but from an OOP perspective, they are badly designed. S…
Re: OOP Is Dead, Long Live OOP
#345Earlier quoted context omitted.
Yeah I have a feeling that some companies don't trust their engineers at all and so they want them to use as many tools as possible to reduce the likelihood of mistakes. That's probably what functional programming, 100% code coverage and code linting trends are really about; allowing companies to not have to trust their engineers. I think this is a futile effort. If you want better code, just hire better developers w…
Where are there company executives that actually know and care about these kinds of things? Some of what you're talking about can be overdone by engineers (i.e. 100% line coverage), but a lot of what you're talking about are tools engineers have developed to make their lives easier and to improve their code quality. A linter checks for common mistakes, clarity problems, and can help ensure code is written in a consis…
I think that a lot of rules enforced by code linters are rules that are good 90% of the time, but they're bad 10% of the time.
Having 100% test coverage is great to guarantee that the software behaves like it's supposed to but it's terrible when you want to change that behavior in the near future. Most systems should be built to handle change. Having 100% test coverage disincentivizes change; especially structural changes.
Also, more advanced project management tools like Jira don't actually add value to projects; they just give dumb executives the illusion of having more visibility into the project - Unfortunately, they cannot really know what's going on unless they understand the code.
Re: OOP Is Dead, Long Live OOP
#346Earlier quoted context omitted.
I did not mention reusable anywhere in my comment. If you are writing code to be reusable, you are writing a library and in that case you better make sure that it is a separate project or module so no caller-specific details are leaking into your library.
Yeah... you mentioned >>> maintainable, testable, extendable and configurable but not reusable. I'm not blaming you, or disagreeing... C++ didn't produce reusable results for me either. I dunno what you were doing 20 years ago, but I was doing this... there wasn't any problem with the classes being unclean or the boundaries cut in the wrong place. It was simply I was almost never going to use those classes a second t…
Re: OOP Is Dead, Long Live OOP
#347Earlier quoted context omitted.
When I was doing hardware in the 80 early 90's I came to the conclusion that the 'reusable code' fans were all missing a point. You are either writing a library,a framework, or something like that. Or you are implementing some 'business logic' The point of the former is reusability. The point of the latter is utterly not and you should not waste your company's time and money or worse let schedules slip because of it.…
Yes that's basically what I found too. To practice OOP, its approach is every class should be a "library". Procedural code that doesn't have a class context is felt to be a shameful throwback to an earlier era degenerate C practices. From before some people feel they starting writing "good C++" apparently.
Compare with business logic. The problem is the spec and use case keeps moving. Moving way too fast to be a good library or a framework.
Re: OOP Is Dead, Long Live OOP
#348Earlier quoted context omitted.
You are confusing inheritance of implementation with inheritance of interface. The consensus is to use inheritance of interfaces and use composition to implement the interfaces. Hence my phrasing: "Inheritance is better achieved through composition".
> The consensus is to use inheritance of interfaces and use composition to implement the interfaces. A consensus by the "maximization of boilerplate" rule. Inheritance is the most powerful tool available at the OOP land. It's the one thing that FP languages still didn't replace with enough added advantages to make the OOP stuff look like a toy. So if you are programming in OOP while avoiding inheritance, you would be…
Assuming this is the case: why do you disagree and what do you think is the cause of this difference in opinion?
Re: OOP Is Dead, Long Live OOP
#349Earlier quoted context omitted.
Mutable internal state is problematic with or without inheritance.
There are plenty of use cases where you need internal state. Think about UI in a desktop app for example. Not everything is a data pipeline with a clear in and out.
Re: OOP Is Dead, Long Live OOP
#350Does anyone know of a good reference for idiomatic OO(P)? Like the Codd paper for Relational Algebra.
Well, the best analogue to the Codd's relational algebra is Hewitt's actor model in my professional opinion. Both are based on mathematical formalism, though the Actor Model goes a bit further in that it's also informed by physics. But, just as SQL doesn't really implement Codd's relational algebra, so it is the case that most so-called OOP languages miss the mark vis-à-vis Alan Kay's original conception. The analogy…
This comment does a nice job explaining why: https://news.ycombinator.com/item?id=2039750
I also like how in the interim Elixir addresses some of the issues surrounding gen_server verbosity.