87 comments

[ 3.3 ms ] story [ 107 ms ] thread
I don't like the clickbaity title. OOP != garbage, badly done and/or unnecessary OOP == garbage.
Given that it is unnecessary in 99.99% of the cases, it is always safe to assume that it is just a garbage, period.
It's more a question of degree. It's pretty rare to find code these days that is completely OOP free, aside from machine code, so I'd argue "99.99% unnecessary" is hyperbole.
But still, it is completely, totally unnecessary everywhere it is used.

I only know one problem domain where a form of an OOP is required (although it must be built on top of asynchronous messages, i.e., none of the existing popular OO implementations would fit) - agent-based simulations. It is well below the 0.01% threshold I set so generously.

Forgive me, but "totally unnecessary everywhere" just sounds like religion to me. Are structs unnecessary? It's an awfully short walk (one pointer long) from a struct to an object.
Ok. Mind naming a single problem domain besides one I've mentioned that should be modelled the OOD way? There are none.

And please do not confuse the OOPish language features (which are just poor man modules support in most cases) with OOP-the-design-methodology. The latter is garbage, the former is just an innocent bunch of language features.

Btw., it is funny when OO zealots are calling anything else a "religion". They should look in a mirror first. OO is a religion and nothing but a religion.

You misunderstand me. I agree that OOP is also a religion. If the video had railed against functional programming, I'd be inclined to post similar comments, with the words "OOP" and "Functional" swapped.

I don't know how to go about debating the merits of OOP, aside from saying it's convenient for things that... behave like objects. And of course there are multiple ways to skin a cat, so you can reply with alternate ways to code graphical widgets etc. And then I say you're putting the horse before the cart, and you say the same to me...

The only thing I'd be dogmatic about is that programming is still a complicated mess, and it will likely remain so for decades. Nobody has any of this remotely figured out, so it's probably best to be pragmatic, rather than commit oneself to purported "magic bullets" (whether they be OOP, POP, Functional, Procedural, etc).

My guess is that the real "magic bullet" will come from AI. I doubt human beings are smart enough to reason about what good programming practices look like. So until an AI comes along to tell programmers how best to design code, it's all just a matter of personal preference.

This "magic bullet" mentality is exactly what is wrong with OOD/OOP. If it was not used to model the reality, I'd find it much more tolerable.

> I doubt human beings are smart enough to reason about what good programming practices look like.

You don't need to be smart to reason, after all, reasoning is a formal, mechanical thing. And there is always a mechanically derived best possible model for each and every problem domain. So it is in fact always very easy to prove that OOP is inadequate and another model is this many times closer to the formalism of the problem domain. For every problem domain out there. There is no place for personal preferences, it's all formal.

> There is no place for personal preferences, it's all formal.

Well, I admire your optimism, at any rate.

The problem is, we program as we have evolved. Single Threaded, solving one Problem at a time, focusing on one aspect at a time, in series.

If you want to have a paradigm that is really succesfull, it would involve using every aspect of the human mind. We are good at perceiving 3d space. We are good at instantly computing physics. We are good at perciving other human behaviour. We are good at recombining existing tools to create more sophisticated tools. If you want optimal results, without the struggle of reeducation, tailor the paradigm to the existing creature, not the inverse approach.

I've worked in projects that use OOP and projects that use procedural style and personally my brain seems to understand the OOP styled code much better than the procedural stuff. Do I then go around calling other paradigms garbage just because my brain seems to function more in an Object Oriented way than other? Of course not. Do I think OOP is then automatically better than other because I understand it easier? Of course not. I stick to OOP because my dumb brain can't figure out other paradigms as well.

Of course OOP is unnecessary since you don't need it to write good software. But one could argue that all paradigms are unnecessary since you could technically write any program using any paradigm. OOP, procedural, functional, whatever. My point is that people are different, use whatever you are most comfortable with.

EDIT: Check Bob Burrough's comment to the youtube video. He worded it much better than me.

"Unnecessary" is the mildest of the OOP issues. A more common one is "damaging and destructive", and you cannot defend this one by simply saying that "my brain understands it better" - it won't magically become less damaging because of this.

The truth is that OOP is in most cases the worst possible way to model the real world. There is always a much more adequate model (besides the single case I mentioned before). So, sticking to a paradigm that does not work at all is nothing but a religion and should be treated as such.

> A more common one is "damaging and destructive"

That's a baseless assertion. Just because you developed a distaste for a particular programming paradigm it doesn't mean that your baseless assertions are suddenly sound.

> So, sticking to a paradigm that does not work

Somehow, the software world is founded on something that you somehow claim doesn't work.

Perhaps you've taken your pet peeve a bit too far.

> That's a baseless assertion.

That's a verifiable fact. Take any OO code-base and it's very obvious how destructive the choice to use OO was, because there is always a much better model than OO.

But of course you zealots are not even competent enough to comprehend such simple things.

Previous videos

Object-Oriented Programming is Bad https://www.youtube.com/watch?v=QM1iUe6IofM

Object-Oriented Programming is Embarrassing: 4 Short Examples https://www.youtube.com/watch?v=IRTfhkiAqPw

I'm watching the 'is Bad' one, and honestly, it rings too close to my experience.

Need to think about this a bit more deeply!

Going from 10 years of strictly procedural programming to oop I can say with certainty that for most applications oop is better hands down.
The other alternative is functional programming (which is usually not the same as procedural programming).
I think that FP is a valuable addition, but not strictly better than OOP (or procedural/imperative). I think that some problems are better expressed in FP, and some are better expressed in an imperative manner and a language should let you choose.

edit: s/think/BELIEVE/

That conflict between OOP and FP is the "Expression Problem". Choosing which side to use for a given problem is an important part of software design.

http://c2.com/cgi/wiki?ExpressionProblem

What you say is sound but, IMO, not complete. There's something more to immutability vs. mutability. They both can, for instance, describe both data bases and mathematics. But there's no doubt in my mind that mutable state is better suited for the former, and immutability for the latter. It's "stuff" vs. "knowledge" that's modelled; stuff wants to change and knowledge wants to be shared.
In my experience there is another kind of expression problem. It's usually something like this

    "a:b:c".split(":").first # Ruby
vs

    String.split("a:b:c", ":") |> List.first # Elixir
The length of the two statements is telling. Luckily Elixir has the |> and I don't have to write

    List.first(String.split("a:b:c", ":"))
OO is generally more convenient to read. It's also more convenient to think into, even when I was young and I looked at C and Lisp without much priming from previous experiences.

Functional has other advantages. I quote Joe Armstrong on that: [with OO] "You wanted a banana but what you got was a gorilla holding the banana and the entire jungle." That wasn't much different with plain C though, which could do structs and be somewhat object oriented too if you coded in the right way. And you could end up with a jungle of functions as soon as you write enough modules that need each other.

IMO, the difference in readability has little to do with the difference between OOP and FP. What's important is the expressiveness of the language.

So Ruby can be very easy to read because you can simply keep appending methods to the right.

In Haskell you can do the same, only you'll prepend functions on the left, so you end up reading expressions from right to left:

    (intercalate ", " . map show . Map.elems) myMap
What I find really hard to read, are expressions where the direction of the data flow changes, something that often happens to me in Java:

    Streams.takeWhile(list.stream().map(e -> f(e)), e -> e.isNeeded())
Three completely unrelated things I guess.

1. Expressiveness is important? Expressiveness is why I don't like Perl.

2. You can certainly implement patterns analogous to OO in functional programming with closures and first-class functions.

3. Reading in the order of execution via chaining is definitely a lot more intuitive than reading from the inside out or right to left.

Don't you think this could just be attributed to you having gained experience?

I look at my code from 10 years ago and it is written with objects and late dispatch as main modeling tool and that code is terrible.

Why is it all videos?

Text is so much better for evaluating arguments. When reading you can spend variable time on different parts to skim the obvious and go deep into the more difficult stuff, you can random access it later to refresh your memory, you can quote it.

Videos are probably only better in persuading people - but that requires that they watch them (and maybe get some stockholm syndrome after wasting so much time :).

Because this is how millennials convey developer information now that they have cellphones and GoPros. Instead of essays they have videos. Instead of rationales they have footage of their talks. Instead of introductory documentation they have screencasts.

Get used to it.

I doubt I will. There are cases where videos beat textual presentations (I think https://www.youtube.com/watch?v=a9xAKttWgP4, the video about programming Conway's game of life in APL is an example) but they are very rare, and even if a few more years or decades of AI research produce a search engine that can be used to find videos answering questions I have, watching a few of the top 10 videos to apply the final human filter will still be slower than opening the top 10 search results now is.

Visually scanning well-written prose that is laid out correctly (easily recognized headers with good content, good paragraph layout) IMHO is way faster than finding the meat in well-written presentations that are presented and recorded properly.

The 'Bad' one is all about personal opinions, no real arguments beside a bunch of information already well-know about oop and that has been discussed by years. And honestly, it looks like a iluminatti conspirancy video, with the boring narration, the sensationalist tone, the black screen. ugh.
I think you're being dismissive. Where else can I read about the arguments Brian makes in the video? I've struggled to find supporting material.
You can read Peter Wegner's Concepts and Paradigms of Object-Oriented Programming (1990), to get a deep discussion of all the concepts he speaks about oop. He is not criticizing oop, but doing an analysis compared to procedural programming. (And defending why OOP can be useful, but with no sensationalism) And he even predicts that paradigms based in concurrency will be the next buzzword after oop. If you read most of the discussions that happened in those early years of OOP adoption, you'll see a lot of the things he's pointing out has being already argued. They just were done in texts, not videos, and weren't so incendiary.
Can someone provide TL;DR? Can't access YouTube from office :(
3'rd video in a series, comparing more and more complex pieces of code, trying to prove OOP is unnecessary in most real-world cases. Worth watching whether you agree with it or not - it can't be really TL;DR'd.
"Sure 90% of OOP is crap. That's because 90% of everything is crap" [1]

[1] https://en.wikipedia.org/wiki/Sturgeon%27s_law

(comment deleted)
(comment deleted)
Having just dealt with it again, I'm tempted to grumble that Java's OOP is firmly within that 90%.

What happens when something is recursively buried in 90% crap? Is its own 90% particularly crappy?

yup, i have always maintained it is a recursive/fractal/recurrence thing where 90% of the remaining 10% is crap, ad nauseum. crap all the way down.
It's more like the limit converges on some x in 0..1 with 90% being the most probable.
It was 3800 lines of code before, and it's 3800 lines of code after. Let's spend the remaining 45 minutes discussing why my personal preferences are correct, and OOP is garbage.
That was my thought as well. In order to justify the crass title, something a little more than a circular argument as evidence might have been called for.
Yes. Plus, it's somewhat arrogant to deride the legibility of someone else's code, in comparison to your own rewrite, considering:

(a) It's an order of magnitude more difficult to write original code than to port code from one domain to another.

(b) It's an order of magnitude more difficult to understand someone else's code than something you've just finished writing.

It would be a different story had he had created the rewrite, and had a third party discuss both versions.

The procedural version have less files, and less functions/methods. This indicates that many functions in the original code were called only once, so we might ask why they were broken up in the first place.

Having that many functions, that are called only once, means you have to make more non-local jumps to read said code. This is not ideal.

Moreover, such a break-up obscures the dependency graph in the code. Many nodes (functions) will have only one inbound edge (call). While collapsing the original graph to a canonical form will likely yield the same result on both code bases, the original code still show 3 times as many nodes. This makes it harder to see the real dependencies. Again, not ideal.

Finally, there's the possibility that the procedural version made genuine simplifications to the dependency graph. If it really reduced coupling while keeping the LoC count the same, that's a net win.

Granted, those measure are not nearly as definitive as the LoC count itself. Still, they do suggest the original code is not as straightforward as it could be.

Now to really know, we'd have to read the code.

> The procedural version have less files, and less functions/methods. This indicates that many functions in the original code were called only once, so we might ask why they were broken up in the first place.

Readability, testing? What seems odd is that there are now fewer functions, but the same LOC count, therefore apparently more code/statements. This looks like he had to actually add code to replace the original structure, which seems superfluous.

Spitting discrete parts of functionality into separate functions, even if called once makes the code more readable even if they only get called once. You don't clutter the would be calling functions scope with variables only needed within the would be in-lined functions body. When you read the code you the function name and return type can describe what is being done rather than trying to grok the body of the function code itself.
It might make the code more readable but it makes you jump around more and adds more complexity to the code base. Now you have to consider: under what conditions does this function get called? Does it get called more than once? In which file is it? And so on. Every time you add another node to your code base you're making it more complex, and in this instance it has very questionable gains. It makes as much sense to just say in the first line of this block of functionality what it does to what.
I guess im used to working with languages with excellent IDE support. Having more files and jumping around the code to see the detail don't seem to be a problem for me when using a good IDE. While I only got through around half the video I can see hes created 500 line functions with 5 levels of flow control, personally I find that much harder to follow than clicking though to a function or just reading he functions name and API.
Those 500 line functions include private sub-functions though.
> Spitting discrete parts of functionality into separate functions, even if called once makes the code more readable even if they only get called once.

The key point is discrete. If you fail to carve the program at its joints, and no more, you'll only make it worse. I too separate functions even if they're called only once. I just require that the interface of the function be easier to understand than its implementation. That's not always true, especially for short, impure functions.

> You don't clutter the would be calling functions scope with variables only needed within the would be in-lined functions body.

I don't need functions to do that. I'm not writing JavaScript. Here:

  {
    int   foo;
    float bar;
    baz(foo, bar);
    {
      int   wiz;
      float woo;
      wak(wiz, woo);
    }
    klo();
    // klonk(wiz); // error: wiz not in scope
  }
> When you read the code you the function name and return type can describe what is being done rather than trying to grok the body of the function code itself.

I can still put comments. They notoriously rot, but the same is true of function names. Plus, comments aren't restricted to identifiers, so I can write plain English:

  {
    // ...
    { // Waks the wiz with the woo
      int   wiz;
      float woo;
      wak(wiz, woo);
    }
    // ...
  }
Why not? If someone can provide good examples and create an interesting talk explaining why their personal preferences are correct, why not spend 45 minutes on it? That is what most of the software conferences offer after all.

You don't even need to agree with the author at the end to learn something interesting. Or even (OMG) something you didn't think about before and that will improve your super-OOP code.

OO in itself is not bad

But of course some people want to create 10 level class hierarchies, replace every 'if' with a subtype and using design patterns ate every occasion (especially the factory, so instead of writing 1 or 2 they will have a OneIntegerFactory, a TwoIntegerFactory, etc)

One advantage into Go for example is that it reduces the potential of misuse of "OO happy" people

My guess is that most "OOP-happy" people never get a chance to see beautiful procedural code so they're just afraid of it. A lot of developers nowadays are trained to smite any code that isn't following OOP principles or design.
Not necessarily afraid, possibly just unfamiliar. I can remember programming like this because C++ was the first language I knew well and I was interested in using all the available features. In my mind that was just how things were done. When I had more of an incentive to just Get Stuff Done and keep things maintainable simpler procedural code made a lot more sense.
(comment deleted)
While I'm sure the topic (and title) may be seen as hostile, this is a very nice code walkthrough and discussion.

The arguments against OOP seem to be 1) OOP obscures data structures by hiding them in too many data types, and 2) the boundaries created by these data types forces workarounds like extra fields to hold a root structure pointer even though it isn't part of the type.

OOP - in practice - does tend to encourage far too many types. A lot of these types are often represent code or design decisions, not the actual data. Instead of a "few" structs that clearly show how the data is organized, we tend to see OOP code that has the data structure spread out over various classes, interleaved with types that actually represent different actions (with the same data).

The solution I always try to keep in mind is that OOP can be useful if-and-only-if the data actually has a hierarchy. A single standalone class is equivalent to a basic struct passed to functions. The class only becomes worthwhile when are able to use polymorphism that closely model the data. The serious problems start when you try to force everything into a class; in extreme cases you end up with the Kingdom of Nouns[1]

The second argument seems to follow from the first; if you have too many types, you tend to take shortcuts like keeping a local reference to a parent or global object that is really outside your scope. This tight coupling creates maintenance problems and further confuses what the type is actually representing.

[1] http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom...

> A single standalone class is equivalent to a basic struct passed to functions.

Not exactly -- a struct is equivalent to a class with public fields. If you have a non-anemic model class then you can guarantee that the object's state is within some boundaries (defined in the mutator methods).

The solution I always try to keep in mind is that OOP can be useful if-and-only-if the data actually has a hierarchy...The class only becomes worthwhile when are able to use polymorphism that closely model the data.

You don't need a hierarchy to have polymorphism. The Observer pattern is very useful in my space game in Go. I wrote a small pair of Interfaces which makes it very easy for certain objects to register to receive notification when a ship despawns.

    type DespawnListener interface {
    	NotifyDespawnShip(Ship)
    }
    type DespawnNotifier interface {
    	SetDespawner(Ship)
    	AddDespawnListener(DespawnListener)
    	NotifyDespawn()
    }
    type basicDespawnNotifier struct {
    	ship       Ship
    	dependents map[DespawnListener]bool
    }
    func (self *basicDespawnNotifier) SetDespawner(ship Ship) {
    	self.ship = ship
    }
    func (self *basicDespawnNotifier) AddDespawnListener(dsl DespawnListener) {
    	self.dependents[dsl] = true
    }
    func (self *basicDespawnNotifier) NotifyDespawn() {
    	for key, _ := range self.dependents {
    		key.NotifyDespawnShip(self.ship)
    	}
    }
My framework sends NotifyDespawn() to any despawning ship. Now anything that has registered interest in that ship, like missile locks, tracking AI ships, or tracking missiles, will be notified when that ship despawns. Note that this makes the system extensible. Right now I have each Ship entity tracking dependents in its own map, which it can do by composing a basicDespawnNotifier into its struct. Later, I will move the implementation guts into the object that implements the game loop/instance, which will eliminate the map from despawning entities, reducing GC pressure, and allowing me to cut-off circular dependencies. Note that all of the game code using the two interfaces won't change at all.

No hierarchy is necessary in Golang or Smalltalk, because both have implicit interfaces and allow composition. (Golang is nice because its implicit Interfaces are made explicit and typesafe.)

The op is somewhat misguided. Good OO is comprised of good design, just as good computer games are comprised of good design. Expecting good OO of any programmer who just knows the "rules" of OO is like expecting the output of all game jam hackathons to be good games. Of course half of all OO projects found on Github with "obligatory" OO are going to show below average design, just as not every game from a game jam is not necessarily a masterpiece.

There is no such a thing as a "good OO". You don't need any OO for your example. Polymorphism is not an OO.
You can have good OO with just encapsulation and polymorphism.
I think you've just reinforced op's point instead of showing how he was misguided.

Saying "Good OO is comprised of good design" is meaningless - good code regardless of methodology is comprised of good design. You can't have good code unless it's been designed well. Good design is not a feature of the OO methodology, they are two independent properties of a program (design quality and methodology).

"Expecting good OO of a programmer who just knows the rules of OO" is exactly what OO was sold to us as achieving. By following the rules of OO design we were supposed to be able to automatically have better programs that were less likely to end up as spaghetti. If we wrote lots of small classes that just did one thing well and encapsulated their state properly we would magically have programs that were easy to understand and maintain, and we would be able to re-use the classes in other programs!

This was hardly ever achieved by anyone, and if it was it was independently of OO methodology not due to it. As you point out, reinforcing the op's points, it's very easy to get OO very wrong, even for experts.

I think you've just reinforced op's point instead of showing how he was misguided.

I can change the underlying implementation of this subsystem, giving it additional capabilities, modulo some find-erase and compiler-guided changes, which I can be 100% sure are done correctly. Please give your own example of code which has the above properties.

"Expecting good OO of a programmer who just knows the rules of OO" is exactly what OO was sold to us as achieving.

As someone who was around for all of that rigamarole since the 90's, I am making precisely the point that this is wrong. The same goes for functional programming as well. The same goes for playing music or designing the inside of your house. There's a little practice, iteration, and self criticism that has to happen. Otherwise, what you get is pretty mediocre.

> OOP - in practice - does tend to encourage far too many types.

Keep in mind that the concept of a class unifies the concepts of modules and types. A class can be seen both as a module (with late binding, and of which there can be several instances) and as a record (with methods to abstract over the representation and allow polymorphism). The advantage is that you don't need a second module language on top of the type system.

Consider, for example, that as of OCaml 4 - with first-class modules and generative functors –, OCaml's module language is essentially a second fully-featured OO system. Using it as such would be awkward because of all the boilerplate involved (it isn't meant to be used that way), but all the functionality is there. This is basically because first-class modules provide late binding and generative functors allow for multiple instances of the same module.

But this means that, yes, you get more types because some of these types are actually modules in disguise.

> The solution I always try to keep in mind is that OOP can be useful if-and-only-if the data actually has a hierarchy. A single standalone class is equivalent to a basic struct passed to functions.

Not really. A basic struct does not have methods that abstract over the representation and does not support polymorphism. Also, it avoids duplicating language functionality for concepts with overlapping, but not identical functionality. Note also that structural subtyping does not require a hierarchy.

I've been running into the problem of too many datatypes in a project lately. Right now, I'm stripping down what I can to the bare essentials and not even for optimization/speed, just for clarity since initially the project I was given had lots of odd recursion, guess-work methods, and the like. My partner on the project formalized some of it as classes. Now we're finding we can remove a good chunk of what we wrote for just better algorithms (less dependence on entity framework and the like).
Methodology wise this approach is problematic, because as a refactorer he gets to stand on the design discoveries made by the original programmer.
Spot on, but this is an insight whose time hasn't yet come. For one thing, it means that controlled comparison of programming approaches is even more impossible than we already know it to be, which is a bummer, which is a reason not to have the insight.

What the OP did is still a worthwhile exercise. And although it seems to have been an accident, he made a good choice of program to study in this fashion. Because it is an emulator, what it needs to do, and therefore much of its design, was predetermined before the first program was written. That makes the comparison with the second program somewhat less vulnerable to your objection, though we have no way of measuring how much.

Good insight, I actually was wondering if the choice of the object (Emulator) was a good or bad one.

You're making a good case that it reduces the effect of initial design discovery since it's based on well known hardware.

This is a stimulating argument to think about.

One possible counter-argument is that the resulting procedural code is more difficult to unit test. In the video Brian acknowledges that he doesn't think much about cyclomatic complexity, but I think if you were to try to test one of these long functions with a lot of branches, the setup required for each case you want to test would dominate the amount of code devoted to the actual test. The solution to this isn't necessarily OOP, but I would not want to maintain Brian's code as it stands without refactoring it.

The more fundamental problem to me is that Brian's code requires you to read it fully in order to understand it. No part of the code is difficult to understand, but it demands that I understand it in detail before I can have a summary of it in my head. I prefer for code to read more like a newspaper article, where the further down you read, the more detail you're given, but you can stop at any point and have a decent understanding of what's going on. To me this makes it easier to reason about the system as a collection of sub-systems, which is often the level at which the really important decisions are made. Again, OOP isn't the only "solution" for this, but I think it's a good tool. It does have the potential, as Brian points out in one of his earlier videos, of devolving into philosophical exercises, but I don't think that's necessarily a drawback if your goal is to make it easier for humans to comprehend your system. In designing your system this way, you're simply taking advantage of people's natural ability to think in abstractions.

To me, the idea of inlining functions that are otherwise called only once is complete garbage. Yes, you reduce number of functions in your program but the program doesn't get easier to read, test, develop and maintain as the functions that you leave get longer... I stopped watching when I learned that that's presenter's idea of improving the original program. And it has _nothing_ to do with OOP and its flaws, you could as well "improve" this way well written functional programs... It's just wrong. Inlining functions is something your compiler is supposed to do for the programmer, a programmer is better off breaking his problem into small functions instead.
I couldn't agree more. When I read your enormous procedures full of inlined functions, I still have to break it down into discrete, logical chunks in my brain. This is work, and there's a real chance I'll get it wrong. If you do it for me, I'm much more likely to understand your program in the way you intended.
I agree with you completely and I think this cannot be controversial. If we cannot agree that sort(my_list) is better than its inlined function, our profession truly is at square one.

The interesting part of this is that although you kind of know that positions with as little nuance as Brian's have to be wrong (because the world isn't simple), it's still important to think about why you hold your own positions instead of dismissing any challenge to them outright. I think it's good to think about why we use objects and whether we need to do it as much.

What we especially lack in programming is any evidence for our practices. The best we currently have is opinion and experience. That means a lot, but not as much as empirical evidence, and I think we tend to forget that too often.

I thought it was interesting. I've carried a "no long functions" rule in my head for so long it was really challenging to have that questioned.

I get the logic behind why he likes long functions that have the meat of the program in them. I've hit code bases before that have broken out bits of logic into separate functions that are badly named and defined and I ended up hopping around the program trying to work out wtf is going on.

As long as we keep the subroutines nice and tight and well-named they're an aid to understanding the program: I can guess what `writeTextToFile(text,filename)` does, and I'd rather see that in the main logic routine than 50 lines of the code that writes text to files.

I will carry on writing short functions, but it's good to know that I'm doing that for a reason, having challenged it.

Here's a fairly well reasoned argument to the contrary: http://number-none.com/blow/john_carmack_on_inlined_code.htm...

It boils down to the fact that it's very easy to have unexpected state dependencies/constraints in those smaller functions, that is non-obvious by just reading them. If they're called when those constraints are not met, it is a bug.

That's why one should try to make functions pure as much as possible.
3800 lines of code is an extremely small program. OO can help when you have a large business project, large team with people, some of whom are possibly not great coders.

Showing that one single person can write a small procedural program that's more structured, faster, etc. than the corresponding OO code written by someone else is not very relevant for real-world projects. I'm not saying OO is great everywhere, but devs in the industry have been writing working code on large scale using OO.

What you're talking about is just better code organisation and modularity. It's a shame it is always brought up in defence of the useless OO, as if modularity is an exclusive OO property and not a mere side effect of it.
> as if modularity is an exclusive OO property and not a mere side effect of it.

Modularity isn't a mere "site effect" of OO: it's one of the main motivation factors that have lead to OO.

In fact, the main problem with these anti-OO rants made by procedural purists is that in essence they all boil down to claiming that basic OO features that are a part of any OO language can be reimplemented in procedural languages.

> it's one of the main motivation factors that have lead to OO.

OO got no rights whatsoever to highjack the benefits of the modules. There are some very successful module systems that got absolutely nothing to do with any OO bullshit.

> OO got no rights whatsoever to highjack the benefits of the modules.

You're the only one who's trying to make that assertion. It's a strawman, and a poor one at that.

No it is you and the other zealots who are praising OO for something it got absolutely nothing to do with.

When someone is claiming that OO leads to a better maintainability of a large code base it's just a shameless lie. Modules are responsible for this, not anything OO.

I enjoyed this. Skipped through the parts about the inner NES workings, but the "embarrassing" video is more to the point and shorter. I found myself agreeing with a lot of points and disagreeing with some too.

It's interesting how many comments there are, here and on YouTube, along the lines of the examples being "bad code, regardless of OOP", "not representative of a large team/project", "unmaintainable", etc. without even a link to an example snippet or repo, let alone a narrated walkthrough of existing code and possible alternatives like the author has provided.

Without concrete examples, all of these counter-arguments are in danger of a No True Scotsman fallacy. In fact, the code in the "embarrassing" video are actual examples of respected OO programmers showing how OOP should be done, which is a high bar to refute.

The author also addresses this a little, by pointing out the often-invoked circular reasoning of "my software's a mess even though I followed OOP", "if it's a mess you must not have been doing OOP properly".

Sometimes software methodologies are a little like the stone-soup story; vaguely defined such that when it turns out bad, you can always wriggle out of it by claiming it was done wrong, and there's a better way to do it that works. When you follow up for details, the full "right way" has such a high bar, no one but a few true believers are gonna actually follow it.

I want a methodology that provides improvement on average, even with only partial uptake. Many other best-practises are independently virtuous, hence have this quality.

Got through first 5 minutes and I already see that myself and the author have very different opinions on what constitutes "good code":

1) having data structure and its methods isolated in a module is not a bad thing. Modules provide an obvious boundary between pieces of code, so when calling some code from another module you know that you should care only about inputs and outputs and not about the particular implementation of the transformation. But when you have the same pieces of code mashed together in one module – that boundary is blurred, now compiler does not tell you that they don't interact via some shared state not named explicitly.

2) defining an interface to do a type switch. Really? Even if that interface is not exported, this still leads to more fragile code. When you rely on interface compiler will yell at you if you miss a method. But when you add a new type and forget to update one of those type switches – it will blow up in your face at run time. This is less relevant for NES emulator, since it was designed long ago and unlikely to get new entities that need to be accounted for, but doing this for no good reason can establish a habit that will bite you later in other projects.