54 comments

[ 3.0 ms ] story [ 109 ms ] thread
Random quote from the article:

> I will eat a week's pay if OOP is still in vogue in 2015.

So, is it time to make the OP eat a week's pay or not? I'd say no.

I'd say yes. Pony up.
Most of the "OOP" code I've seen recently is made mainly of static functions organized in classes with little or no state, instantiated and injected by a DI container in the name of flexibility. So I'd say that, in some sense, it's much less in vogue than it was fifteen years ago.
I'd say yes. Even though I agree with many of the points the article makes, OOP is still very pervasive, and I'm pretty sure it's still by far the most used development paradigm for most types of software. OOP may not be ideal or perfect, but OOP languages can be used to shoehorn almost any kind of problem into, which is exactly what people are still doing today. Often times producing a terrible mess that hardly works, but that's besides the point for his challenge ;-)

Anyway, he makes many valid points, like other articles about the disadvantages of OOP, but none of these every draws any convincing conclusions why OOP is 'bad' and why something else would be 'better'. In programming there is no paradigm that fits every application, OOP is just one of many ways to solve problems, and one that has proven that (if used pragmatically) works very well for a very broad range of problems.

Yes, I'm going to have to agree with this. OOP is just one paradigm.

But what has changed from the years this article was written is that OOP is not touted a panacea. Back when I learned to code, OOP was a synonym for "good".

That's why I'm saying no. OOP is no longer the hyped as it once was.

(comment deleted)
I like the "split ends" analogy. A lot of developers seem to worry too much about issues that aren't actual problems, other than that something is "not OO".

An actual example of this I saw recently, was when I got into an argument with someone over the use of standalone functions in C++. Apparently, these are evil, and functions should always be part of a class.

Of course, a class with only static functions is basically a namespace. No problem, apparently statics are also evil. So let's not make these functions static, even though they're not accessing any member data.

But now, when we want to use these functions, we need to instantiate an object, which is a bit silly. No problem, we'll just make it a singleton.

I shit you not, this actually happened.

Once, I was using a struct for some simple data. I added a very simple member function to sanely format the data. I thought I was going to be hung in the code review for not using a "proper" class.
Singleton? No no, those are ALSO evil. No, we need to use a dependency injection container to provide that object instance.
Funny anecdote: I was recently contracting at a company that was OOP gone amuck. Everything written in Java ca. 2001 style. Lot's of message wrapping and unwrapping. Lots of dependency injection fun and games.

At some point, their lead developer tells me about some guy they had for a job interview a while back, and as the story goes they had him through a code review where he was berated for using a static helper class. Apparently his reply was something like "You're using static classes for view helpers? But that's insane!". The morale of the story as told, was that clearly he didn't know right from wrong and was passed over. I didn't know what to reply to that.

"Java ca. 2001 style" also seemed to include using every feature of J2EE even if it wasn't remotely relevant.

Crazy files of constants seemed to feature a lot as well:

   public final static string HTTP = "HTTP";
   public final static string COLON = ":";
   public final static string SLASH = "/";
and then the inevitable:

   string url = HTTP + COLON + SLASH + SLASH....;
[I did think about posting it to the DailyWTF at the time but thought that might be bad form when you are the lone contractor trying to rescue the project.]
Now you just need to reintroduce the original function, and call it a performance and memory "optimization", because you no longer have a singleton or its construction to worry about....
My theory is that we focus too much on the final points of "best practice advice" and very little on the reasoning behind it.

As programmers, we need to start demanding that logical explanations always accompany best practices or dismiss them as bullshit.

I tried this for over two years at a job, which inevitably resulted in "well, John has 25 years of experience, and you have 5".
You might be able to reframe it as a "why" question. Then you're no longer questioning the experience, but the ability to impart that knowledge to others.
When someone quotes something as a "best practice" I usually take it that they aren't actually interested in the "why" and probably have no idea of what the underlying justification is.
What's wrong with quoting best practice and pointing the why in your framework of choice documentation that explains the best practice and the why?
Functions are evil in some languages (C++, Java) because they can't be overridden or customized with virtual methods. In functional languages that don't need polymorphism as much, it's because you can accomplish similar effect with heavy use of higher order functions, which is something that is impractical to do in many OO languages. Functional languages also have their own set of rough edges, FP langauges force an OO programmer to look at a lot of concepts (objects, polymorphism, mutability, encapsulation) in a new light, as they are applied quite differently when you start leaning on functions so heavily. I think if one is in an OO language like Java and starts using static methods everywhere, you end up in a half-way danger zone which can be extremely painful down the road.

Anyway, beware challenging conventional wisdom, it evolved due to past pain and gets passed down generations to avoid that pain, even if the reason is not well understood anymore.

For the 'best practice' to work, you'd have to make your object accept an interface, in order to be able to accept one with the overridden function that you want, correct?

I think this is the problem with the received-but-not-understood wisdom -- the implementers don't actually use an interface but hard-code the class that has the method, so it's not any more over-rideable than a regular function call.

Functions with closures are as powerful as OOP and can be used analogously.

Also, singletons aren't portable.

It reasons like this Uncle Bob pisses me off.
The article is pretty bad.
Remember, you can only say nice things on HN. Blind agreement is ok, blind disagreement isn't.
The section on "Cult Oriented Programming" is also still very relevant today. You could substitute "Smalltalk" for "React" and it still mostly makes sense.

> ...a programmer's personal preference is more important to getting results than the language or paradigm itself. In other-words, if a programmer can work with the tools and languages that he or she most prefers, then productivity and quality may be much higher than from passing down edicts based on a blanket choice of tool, language, or paradigm.

This backs up a lot of what I've seen over the years and I consider it wasteful in the extreme. Maintainable, functional applications are constantly thrown out because programmers don't want to use things they consider "dirty". "Eww, I don't want to go anywhere near that. It's (procedural|PHP|got 'goto' statements|VBA|not the cool thing that everyone's talking about)."

Yeah, but this thing works just fine as it is. Your job is to improve it without making it worse for the next person, not Reactify it until you've exhausted somebody else's supply of money on a hunt for unicorns.

I'd codify this further with the view that subsituting one set of technical debt with another that fits with local trends and personal opinions is bad. The reasons to program in a particular fashion are as weak as "look how elegant that code is" appealing to the asthetic of the text and layout rather than any actual metric of clarity, reusability, interpribility or whatever.

Goto considered evil is folk law when it comes down to it, I think it's almost universally believed but the fact that I don't immediately think of a crystal clear quantitative result to underpin the view that jumps in code are bad is telling.

I think that some of what is going on here is economics though, coding in the new way gives a good line of patter for the next gig, and we all need to think about the next gig.

Funny how GOTO is bad, but "break"ing out of a FOR loop is acceptable. The break is a very specific case of a GOTO.
Any kind of loop is just syntactic sugar over a goto. Having looping semantics in the language makes it clear when that particular pattern is being used, and it can prevent bugs that might pop up if everyone was writing their own ad hoc loops. Same thing with break. It makes the intent clear and makes it harder to accidentally stray from that intent.

Of course, there's a problem when sometimes you want to stray from the patterns encouraged by the language, but it doesn't provide adequate means to do so.

The essence of badness of GOTO is precisely that it is not "specific". When a higher level language restricts it, it is no longer the "bad goto" that structured programmers warned against. The problem isn't "transferring control flow", it was the ability to do it completely unrestricted.
Bad GOTO is jumping into a FOR loop in the middle of an entirely unrelated piece of code.
Fortran IV would let you GO TO out of a DO loop into a whole different procedure's DO loop. (It didn't have FOR.)

But why limit yourself to GO TO to fixed places??? Fortran IV also let you GO TO an arbitrary statement that would only be chosen at run-time "assigned goto".

Fortran 77 still has that capability but you can limit it to specifically selected statements and it won't GO TO outside of the current unit (a concept Fortran IV lacked.)

Dijkstra's remarks were contemporary of Fortran IV.

Funny you should write that. One company I looked at was on their fourth rewrite of the system powering their main revenue stream. Every rewrite (by the usual suspects, proponents of some technology with a good babble but less than stellar tech chops) led to a reduction of that income stream, users leaving and so on.

My first piece of advice was to ditch the current system and revert to the old. This had been purposefully sabotaged by the suppliers of the new system. The only way out was then to go forward and this nearly killed the company.

A previous employer had an application that was very successful (from a business perspective) because it wasn't flexible - they did a lot of acquisitions (one a month at one stage) and if there were any questions around their internal systems they got this application inflicted on them. At first I was horrified (it was ancient, user hostile, completely inflexible) but I actually saw that it worked - the companies being acquired were all in the same industry and their core processes were all pretty much identical (even if the terminology was all different) - so they could all adapt to the new application and it actually ended up working pretty well.

More "modern" flexible applications ended up having multi-month/multi-year "implementation" phases as teams tried to change their new application to their existing processes when it was actually easier to standardise the processes around a fixed application.

Airline companies typically have ancient stuff running but from a productivity point of view that old stuff beats the 'new' stuff hands down. It just works, has 0 overhead in terms of eye candy and so on. Ok, you can't play minecraft or solitaire on those machines but that's probably a benefit.
Also, on those old systems running IBM RPG and other "green-screen" UIs, it's really impressive how fast users can navigate the system via keyboard commands when they are forced to not have a mouse.
I remember working in a bank in late 90s and while GUI apps were starting to replace the 3270s, completely non-technical "lifers" had just fully assimilated the old mainframe app.

Getting an account balance for example was a "Question 8" if I remember right, that is, the PF8 key on the keyboard. Routine banking operations were maybe a couple dozen keystrokes and mostly all the same pattern but different function key with paper overlays taped to keyboards to "name" the PF keys.

It wasn't pretty and the learning slope was steep but the same people who wrote their emails in Lotus Notes in All Caps and scanned word doc printouts into new word docs had no problem memorizing all the obscure operations they had to do every day.

One person I knew had a particular system down so well that they could fill the type-ahead buffer for several screens ahead of the mainframes response, the screens flashed by too fast to read.
That's amazing that they purposefully sabotaged it! How did they go about doing so?
Well, given that it is much easier to destroy a system than it is to build one in the first place the actual method doesn't really matter much. Take your pick. How would you sabotage a system?

In this case they canceled the contracts on a bunch of facilities that were crucial to operating the old system and that would take a very long time to set up again.

But the whole idea of a non-revertible change-over without at least a period of having the old system on stand-by just in case all by itself is totally reprehensible, especially since their testing regime was comprised mostly of 'let's go live and see if it works'. Of course they didn't mention that little fact beforehand, only afterwards was it made clear that any attempt to move back to the old setup was going to be fruitless because they'd 'closed the door behind them'.

I suspect that they knew full well the new system wouldn't work properly and that if a revert would have been done this would likely trigger some serious backlash so by saddling the client up with the new system and making sure they could not go back they forced them to accept the new situation no matter what. Job security by any means.

Only that part ended up not working.

I've never seen a clusterfuck like this before and I really hope I won't ever see one again.

"How would you sabotage a system?"

Just to provide another example, "write a stub prototype of the new system, discover $CRAPPY_ORM in my new hotness language doesn't like a couple of the database constructs, migrate production database to work better with the prototype, new system fails to generate some data the old system needed (history, audit logs, tons of options here)". Back migration now effectively impossible.

There is absolutely no reason why you couldn't pair those strategies ;)

Especially not if there is financial information involved.

Let's imagine that YOU were doing the rewrite, and for all the best reasons. Totally different situation. Would you write your code to continue saving some bizarre unnecessary data in the database, or would you get the job done with a sensible scheme? As for the other comment, were they supposed to continue renting out completely unused facilities in case someone came along who thought the old system was better?
There are proper ways of doing this: you run the old system in parallel with the new system and you outfit both systems in such a way that all writes are done on both systems. That way the DBs stay in sync.

So you won't have to 'write your code to continue saving some bizarre unnecessary data in the database' and you can have your 'sensible scheme'. It just takes a little bit more care and planning.

> As for the other comment, were they supposed to continue renting out completely unused facilities in case someone came along who thought the old system was better?

They ended up renting a good part of those facilities anyway, the problem was not the money but the fact that certain comms lines had been torn up.

Playing cowboy with critical company data is not a winning strategy.

> Maintainable, functional applications are constantly thrown out because programmers don't want to use things they consider "dirty". "Eww, I don't want to go anywhere near that. It's (procedural|PHP|got 'goto' statements|VBA|not the cool thing that everyone's talking about)."

Personally, I really, really don't like Visual Basic. I don't even claim to have anything resembling a rational reason for this attitude. It's deeply ingrained prejudice. And if I have a reasonable alternative to touching VB code, I'll take it gladly.

But I've had to touch a few VBA/Excel based "applications" over the last year or two, and I did it. It was no fun at all, but it was still better than rebuilding those things from scratch. In one case, we replaced an Excel sheet crawling with VBA by a PivotTable which does the same job, is more maintainable, the file is a lot smaller and it appears to run slightly faster.

There is also a part of me that loves picking up some old code written by somebody who has long since left the company, possibly to solve a problem I do not fully comprehend, and fix some obscure bug or add some minor feature. So far, I'll admit I was quite lucky in that those programs I had to touch were reasonably well written, or at least readable and structured in a sanity-preserving way. But still, it's fun, in a way, and the "dirtier", the funnier; at least as long I have a clearly defined task and get to walk away from it when I'm done.

Using the hot new toy that all the cool kinds are using is probably fun, too. But working on a 10-20 year old application that only a handful of people have ever touched, has an appeal that outweighs the distinct lack of sex appeal. Plus, you get to tell some interesting stories about the things you've seen. =)

I like OOP, basically. But as with all things in life, if one takes it too far, it quickly stops being fun.

To think that a) all problems can and should be solved via OOP and that b) it is superior to other techniques (as if it was a competition or a fight) is foolish. To think that some program, that is designed in an object-oriented way, is inherently better than some other program that isn't, is - to a degree - like saying some athlete is better than another one because one wears yellow shoes and the other wears green shoes.

How is this article front page HN news??

The GUI Link

People think of gui elements as seperate objects (scrollbar, list, tree, textbox etc), so why is it a bad thing that the software also reasons about them as objects? Author just seems to want to hate OOP but offers no alternative: "There is more proof to the existence of UFO's than to OOP being the best way to do GUI's or any other programming topic." ???

Bait-and-Switch

Author says here that training examples lure people into this idea of a perfect world that can be modeled easily with separate objects, but in real life projects this is not the case. But how is this any different from any language / paradigm we have today? Angular is often berated for example for being easy to get going with, but a PITA once the project becomes too big. It's a good thing examples introduce you to the strengths of the language, and then later you try to to fit the problem to those strengths.

Land of Confusion

"It has almost become like Particle Physics, in which only a small elite group appears to understand it properly, and everybody else needs years of meditation and practice." This is silly. Everything has a learning curve, but once you understand that everything exists inside an object you are good to go. The rest is just design patterns that are proven to make your life easier!

Not Table-Friendly

"OOP often does not map well to relational databases"

Entity Framework for C# is used by businesses all over and shows this is possible, and easy to do. There are many other solutions to this as well.

Melding Can Be Hazardous

"How many times do different programming languages and systems have to share data? Very often in the real world. Thus, it is usually safer to keep large data pools separate from methods"

What?? This makes no sense. If you need to share your data structures, then serialize your data to a text format and document it, for the next program to read. You could even provide an API.

IDE support

Well I've stopped reading by this point, but the author doesn't mention any advantages gained in the IDE. Specifically by using objects, the computer has more understanding of what I am doing, and can provide me: contextual autocomplete of members, and contextual documentation. Both invaluable for quickly getting up to speed with a new API, and making programming fun.

"This is silly. Everything has a learning curve, but once you understand that everything exists inside an object you are good to go. The rest is just design patterns that are proven to make your life easier!"

Maybe it's just me but this is my main gripe with OO. I sometimes need to write involved data processing tasks and it's much simpler if I first think in graphs or through a relational model. The objects are light and either a way to encapsulate state (as in parser), a simple structure (as in a vector xyz) or a container.

Complex data lives in relationships between the data - as opposed to 'encapsulating into an object' - this keeps the system small, easy to understand and modify.

Sure, objects are a nice way to offer an interface to something but I've found the statement 'objects all the way down' usually means poor design.

This gripe is of course mainly pedagogical - students (like I was, once) are exposed to a subotimal abstraction of software composition when objects are introduced as the way to design and implement software.

Sure, they are nice in some places, I don't deny that.

How does an article like this end up here now. Was someone browsing the way back machine?
I paraphrased one of his statements under the "Split Ends" heading: Advertisers take a small or imagined problem and magnify them to the point of irrational paranoia.

Well said. And that is what is happening today in many forms. I'm under the impression that hiring managers (kids in their 30's) are totally irrational about skillsets because others don't know exactly what they think they should. There is paranoia about making a wrong hire to such a degree that they will most likely make the wrong hire!

What you stare at, you steer for - Bob Goodnough

I like to tell people about the UCO or "Unencapsulated Composite Operation". It tends to win arguments over "global functions are evil".

Say you have two classes, A and B. You have an operation that uses both of them. You can declare A::func(B) or B::func(A) but this couples the classes together. Yuckko.

So you just make a global function, func(A, B). The function gets its job done using public methods, and the classes remain unaware of each other.

That's the foot in the door. Then you whip multidispatch and CLOS on 'em and watch their eyes get real wide :-)

Move onto :before :round and :after methods - then finish with the joys of writing your own custom dispatch code.

Leave a copy of AMOP as a going away present.

Isn't coupling both A and B to the global func(A, B) just as bad as coupling B to A in A::func(B) or A to B B::func(A)?

The thing you're trying to avoid with coupling is that when the dependency changes you might have to change the thing that depends on it, right? Isn't global func going to change with the same likelihood as A::func or B::func?

I'm not sure if this is a relevant or not, (but since it relates to your post,) I do often find myself wishing I had multiple dispatch and/or some way to extend interfaces to existing types when programming in a language without those features.

Not the same; you can use A independent of B, they are not coupled and you don't even need them both in the product. You're free to change the global func independent of the classes.
Thankfully the pendulum has swung back since the 90s.

Stepanov, the inventor of STL (The C++ Standard Template Library) was the pioneer in avoidance of OO. It was truly revolutionary, and had such a huge influence on library design that today most modern C++ libraries are designed the same way.

"STL is not object oriented. I think that object orientedness is [...] a hoax. I have yet to see an interesting piece of code that comes from these OO people. [...] I find OOP technically unsound. [...] I find OOP philosophically unsound. "

http://www.stlport.org/resources/StepanovUSA.html