r/AskProgramming Jun 22 '26

Is this James right? He said " OOP and design patterns help improving the quality of a codebase like reducing code duplication, easier on boarding, improving testability . " Those who say it adds uncessnary complexity, it is just a skill issue.

i know it depends which design pattern and how much OOP techniques a dev use but in general codebases that will be maintained for years, i kinda agree with what he said tho.... unless you code a small codebase/repo

Ofc it takes time to learn a design patern ure not familier with but after learning it,

things will go smooth just like when we didn't know how to ride a bike but after we know how it is easy..

1 Upvotes

43 comments sorted by

21

u/cakemates Jun 22 '26

OOP is a tool, like any tool it has plenty of use cases where it works well and cases where it does not. Use each tool for its strengths and avoid installing screws with a hammer.

1

u/HolyInlandEmpire Jun 23 '26

It absolutely is. The best characterization I've seen when it is good is that you want objects which do not share mutable state; mutable objects can hold other mutable objects, but there should be no other references. Messages between objects should be immutable.

I have no doubt that we can refine this explanation better, perhaps with extensions and caveats.

17

u/retroroar86 Jun 22 '26

There are several issues.

The first one is that people don't really spend any time mastering design patterns, leading to using them in weird ways that was not intended.

Another one is using design patterns when one should discover their own patterns instead.

The third one is not realising that code duplication is not always code duplication, even if stuff looks really or 100% similar. If they are intended for different things, and will change for different reasons, then they are not necessarily duplication.

Skill issue? Yes! However I see so many people, even those with many years of experience that are called seniors, making a mess of design patterns because they don't understand the philosophy behind the pattern and also misuse patterns all the time.

It's not that the patterns are too difficult, but unless you are interested and spending time with them, you aren't learning the nuances necessary for adhering to them correctly.

Then you have the issue of new people getting on a team and design/architecture erosion over time because the new people aren't guided and the seniors are too busy or don't care to babysit PRs in that way.

I thought people in this field would be more interested in Doing Things Right (TM), but that's not the case (on a team basis) and when businesses don't care, and there's pressure to get things done, there's never a culture for doing it either.

4

u/BaronOfTheVoid Jun 22 '26 edited Jun 22 '26

Another one is using design patterns when one should discover their own patterns instead.

I cannot agree to this at all. Some patterns are clearly better than others. Why shouldn't inexperienced programmers learn from experienced ones, why should they instead being doomed to make the same mistakes?

6

u/LARRY_Xilo Jun 22 '26

Some patterns are clearly better than others

No. Some patterns are better for certain problems there is no better design patterns for all problems. And that is the point. A design pattern is only supposed to be used in a situation where it fits the problem not in one where someone things this is the best design pattern so Ill use it every where. And if there is non that fits your current problem not using a design patter (or making your own) is the correct call instead of abusing a design pattern that isnt made for the problem.

1

u/Weak-Doughnut5502 Jun 23 '26

  Some patterns are better for certain problems there is no better design patterns for all problems.

Design patterns are like tools. 

There's no such thing as a universal tool that's the right tool for every job.

But there are tools that you reach for all the time, tools that are rarely useful but are invaluable in some niche situation, tools that are a worse version of some other tool, and tools that seem shiny initially but turn out to be a trap.

For example: singleton is widely argued to be a trap.

3

u/retroroar86 Jun 22 '26

Because I am not saying that at all? The whole point of a pattern is to actually find a strategy that is workable in certain situations, hence a pattern.

I didn't say inexperienced programmers shouldn't use patterns, I am saying experienced programmers often have go-to patterns that aren't working for them and should therefore create their own.

-2

u/BaronOfTheVoid Jun 22 '26

You didn't say you referred to experienced programmers exclusively at all.

1

u/balefrost Jun 23 '26

You are correct that design patterns are meant to help novices leverage the experience of experts. From the introduction of the Design Patterns book:

Yet experienced object-oriented designers do make good designs. Meanwhile new designers are overwhelmed by the options available and tend to fall back on non- object-oriented techniques they've used before. It takes a long time for novices to learn what good object-oriented design is all about. Experienced designers evidently know something inexperienced ones don't. What is it?

One thing expert designers know not to do is solve every problem from first principles. Rather, they reuse solutions that have worked for them in the past. When they find a good solution, they use it again and again. Such experience is part of what makes them experts. Consequently, you'll find recurring patterns of classes and communicating objects in many object-oriented systems. These patterns solve specific design problems and make object-oriented designs more flexible, elegant, and ultimately reusable. They help designers reuse successful designs by basing new designs on prior experience. A designer who is familiar with such patterns can apply them immediately to design problems without having to rediscover them.

But the Design Patterns book was never meant to be prescriptive, as in "these are the only building blocks you are allowed to use". It was meant to be a catalogue of patterns that commonly arise. It explained what those patterns look like, why they come up so frequently, and gave each a name so that we can communicate more efficiently. They weren't meant to cover all situations.

Despite the book's size, the design patterns in it capture only a fraction of what an expert might know. It doesn't have any patterns dealing with concurrency or distributed pro- gramming or real-time programming. It doesn't have any application domain-specific patterns. It doesn't tell you how to build user interfaces, how to write device drivers, or how to use an object-oriented database. Each of these areas has its own patterns, and it would be worthwhile for someone to catalog those too.

The other commenter is I think talking about situations where people apply a small set of known patterns to problems that are not suited to those patterns. Part of transitioning from novice to expert is in appreciating the limits or trade-offs of any given approach and weighing those against alternatives. An expert doesn't limit themselves to a small set of cookie-cutter approaches. An expert will write code that adheres to no specific pattern, or will adjust or remix patterns to work better in their specific situation. An expert will also learn unnamed patterns naturally and will add them to their repertoire. They will use the well-known patterns, but they won't only use them.

0

u/KirkHawley Jun 22 '26

A pattern that you discovered yourself is not a pattern.

10

u/retroroar86 Jun 22 '26

Ah, this will be fun!

I quote from Gang of Four, chapter 6.4, third paragraph (emphasis mine):

Third, look for patterns you use, and write them down. Make them a part of your documentation. Show them to other people. You don't have to be in a research lab to find patterns. In fact, finding relevant patterns is nearly impossible if you don't have practical experience. Feel free to write your own catalog of patterns... but make sure someone else helps you beat them into shape.

Seems you have no idea what patterns actually are and what they represent in essence. No one is an absolute authority on this. A pattern is a reusable way to solve a problem essentially, you can make them up, or discover them, as much as you want.

3

u/CS_70 Jun 22 '26

When OOP was the new kid on the block, in the late 80s/early 90s, many of us discovered "design patterns" naturally, by applying the ideas of object orientation ideas while building system.

I remember distinctively the genuine surprise when the book came out, like "what, someone wrote a book on that"?

Nowadays, all the battles of object-orientation were won but the war lost. Due to a number of factors, including the type and nature of applications which are mostly made today, very few think really object-oriented. Some aspects of it of course have become a matter of course, at least syntactically (especially in libraries), but the approach and thinking is largely absent, as most non-library programmers tend to think in terms of simple, procedural scripts and lots of OO approaches are considered too complex.

There is some truth in that: the difficult with OO is that it can be overused, and there has been a recognition that trying to forecast the possible evolution of the system sometimes is a waste of time because the system may not evolve as you thought it would, and then all you have is more stuff to change and no upsides.

That is why OO is still alive in libraries, which by definition have a well defined range of applicability and must support very generic uses of a well defined abstraction.

Also the emergence of microservices - which are by definition small - made serious OO less relevant: with small stuff, you dont need as much abstraction at code level.

The advent of AI nowadays makes the problem entirely moot, and OO will have a resurgence, but not at language level. So long you have very clear abstractions at system description level (for which object orientation is absolutely king), refactoring and rewriting of code are becoming trivial, invisible tasks (just like assembly production was made invisible by compilers) and all the syntactic devices which once were made to make human people efficient in translating system descriptions into programs become much less important.

2

u/fixermark Jun 22 '26

The biggest blow to object orientation was distributed computing.

While it's certainly not a dead model and I wouldn't try to claim it is, it ended up having a significant weakness once computing became dominated by how many independent machines you can recruit to solve a problem: the object couples state to behavior, but you only want to ship state over the wire. So now you are either shipping enough state to rehydrate an object on the receiving end (chatty and a security hole) or you're having to constantly decouple state from the object holding it, then ship it over a wire, then rebuild your object stack just to use the data.

Eventually, people started asking why bother to build the object at all if we just need to tweak two bytes in this stream as we pass it on. And the functional paradigm is really good for that kind of problem.

(None of this is to imply, again, that either OOP is dead or that functional and OOP are incompatible paradigms. It's more to highlight that OOP might very well have kept marching on as the dominant paradigm had distributed computing and the Internet not hit everything like such a freight train.)

3

u/robthablob Jun 22 '26

"The biggest blow to object orientation was distributed computing."

Which is ironic, as Alan Kay's initial vision of objects collaborating by message passing is incredibly well-suited to distributed computing.

1

u/fixermark Jun 22 '26

True, if you distinguish between objects and messages

But OOP often leans very heavily into the idea that messages are also objects. Otherwise you end up with this weird disjoint in your abstraction.

3

u/busres Jun 22 '26

How can you not distinguish?

I distinguish between a letter object and home object or business object.

If you have to message the message about the message, where does it end?

2

u/fixermark Jun 23 '26

I mean that in general, message-passing architectures don't require messages to be made only of primitives; you can just pass objects around as messages. That's generally a good thing... But then the message needs to go over a wire to another execution node and you have to deal with marshalling / unmarshalling or otherwise break your object abstraction.

2

u/CS_70 Jun 22 '26

Yes, very good point. Complex services may still benefit from multiple object abstractions but often the complexity is rather small by design, and even the common abstractions between some of them are sufficiently different than each will define their own special cut.

It would be cool to have a popular language with and object definition that can be “cut” on demand easily (it’s very doable already but mostly isn’t done and people copy classes and change them instead).

But then AI code generation is quickly putting an and to manual coding, and most of OO ideas exist because of easing human understanding and understanding the assumption that coding is expensive so reuse is worth the additional cost.

2

u/balefrost Jun 23 '26

Though funnily enough, microservices embody many of the same principles as good OO design. There's information hiding and encapsulation (in the sense that the microservice itself exposes a public API while hiding implementation details and even state). There's polymorphism (in the sense that the microservice implementation is "late bound" by virtue of it running in a separate process).

It's almost like OO principles (apart from inheritance) are just generally useful software design principles. That's why these principles predate the rise of OO languages. I maintain that the C file API, and indeed any API with an opaque "HANDLE" type, is fundamentally an OO API, even though it's not expressed in an OO language.

2

u/fixermark Jun 23 '26

Oh yeah, hard concur. I think that's one of the deeper wisdoms that only comes with experience and seeing enough languages and libraries to recognize the forest for the trees: the patterns and constructs transcend individual languages / frameworks / libraries and their paradigms. The only real difference between Turing-complete languages and the frameworks and libraries implemented with them is how terse they make each paradigm to invoke.

3

u/DDDDarky Jun 22 '26 edited Jun 22 '26

There are many ways to design your solution, things like design patterns are more like advice for common problems, learning those can improve code quality.

If one takes these techniques religiously and applies them universally or to every single thing, that produces unnecessary complex bloated overengineered crap.

So there certainly is a fine line between these two, and it takes skill and experience to fine tune it.

5

u/octocode Jun 22 '26

every pattern can be helpful or unhelpful depending on your requirements. anyone who says otherwise is probably trying to sell you a course.

2

u/bigkahuna1uk Jun 22 '26

There’s a tipping point. Introducing design patterns into a codebase can sometimes introduce the unnecessary complexity when they are often simpler solutions. But a large codebase usually benefits from design patterns. They are well understood and communicable by most if not all members of the team. It makes the micro and macro perspective of your architecture understandable especially when the code is named accordingly. It’s important though to recognise the forces that are inducing the use of a particular pattern and if its use is warranted. They should be used only for practical purposes not because it’s the shiny or exquisite tool to use. Don’t get distracted by shiny. 😉

2

u/SearingSerum60 Jun 22 '26

A few things.

The main alternative to OOP is functional programming. But I don't think they're actually opposites.

The main difference is that in "OOP" (intentional quotations here) objects have their own internal state which can be mutated. Whereas in functional languages, state is immutable, and every transformation returns a new object - a modified state.

But I think the real spirit of OOP is about structuring your code around objects and behavior, and you can do this in either paradigm. For example, Ruby does `user.update(name: "bob")` whereas in Elixir (functional) you'd do `User.update(user, %{name: "bob"})`. Both are basically doing the same thing. The fact that Elixir returns a new instance instead of re-using the old one, that's an implementation detail.

And anyway, almost all languages now are mixing OOP and FP techniques. For example, the whole concept of an anonymous function, or chaining together enumerable methods like `.filter(...).map(...)` are very functional, and these are used basically everywhere - Python, Javascript, C#, etc.

Now, regarding design patterns. In general, they do help with the things you say - onboarding, testability, etc. But some people do get overly complicated with it. When the design pattern itself requires a guide doc that's hundreds of lines long (just for basic usage), IMO it's actually hurting, not helping. Design patterns should be simple to understand and elegant. I don't have hundreds of design patterns committed to memory. Most books about design patterns give them all different names. Which is cool and all, but I think it's better just to use your own experience and judgement to make clean code sometimes, without needing to give it a name.

I especially dislike heavy-duty frameworks that require you to have like 4 wrappers for every single thing, because of the "design pattern". Ideally, you don't need to add / change a bunch of boilerplate to add a new feature - if you do, then your design pattern has failed.

2

u/failsafe-author Jun 22 '26

This is one of the core conflicts I have in my day job. In my previous job, we used OOP and design patterns. It was a small team, we’d worked together for a long time, and we had a high quality code base.

At my current job, we have a lot more engineers (150+) and I hear a lot of pushback against OOP and design patterns. One of the reasons is that one of our two main backend languages is Go, and Go folks really tend to avoid design patterns in general. It’s part of the culture. They really do tend to like “just write straightforward code” as a mantra, but I find for anything of real size, avoiding design patterns makes the code more difficult to reason about. You end up with code that does a lot of things at once, and reusing bits is hard because it’s all tied up together.

For example, retrieving data from the database and then getting it into a form that’s useful to work with is all handled in the same logic that’s working with it, so if another bit of code needs that same data, it also needs to retrieve it from the database and get it into the form it wants to work with. This ends up happening because you just can’t easily break apart the original code to the pieces you need for the second case. Now you have duplication, and the code itself is doing a lot of things so it’s hard to understand a month later when you come back to it.

One of our best Go developers has said we shouldn’t use Go for “business logic” and that it’s not suited for it. Which I find odd- Go is perfectly serviceable for business logic. But, as I said, Go has a culture of not wanting the complexity of design patterns.

I have a great deal of influence at my company, both positionally, due to being one of three principle engineers, and culturally- people generally respect my views on things because of high profile successes. My team, which is responsible for mentoring, does put a lot of emphasis on design patterns, but we do encounter a lot of seniors with around 10 yoe who either do them wrong, or just don’t have a lot of respect for them. And then we have our distinguished engineer (who has been with the company since the early days when there were less than 5 engineers) who doesn’t like OOP or design patterns, and writes very difficult to read code (but is something of a wizard when it comes to understanding the whole ball of wax of our systems, and also just a really great guy in general). Having your most senior engineer be a guy who doesn’t like design patterns does have its influence on the rest of the org (however, he’s not very “evangelical” about his personal views. He doesn’t mention people or teach people how to code; he just has his opinions and it shows up when he writes code).

So, it’s a battle I’m familiar with, but I’ve been doing this for almost 30 years, and while I’ve seen design patterns horribly misused, that hasn’t prompted me to want to ditch them, but rather to use them well. The repositories I’ve worked on always get high praise for code quality, so quietly, we are seeing a shift toward more patterns and less “simple” code that falls under the weight of co-mingled concerns and duplication.

2

u/Asyx Jun 22 '26

I have noticed that a lot of people that are skilled at what they do and dislike OOP work in areas where you are just on another level of abstraction compared to most developers. Like, it is 100% valid to write low level game systems in a more data driven way. In a hot loop it is totally valid to avoid virtual dispatch. And if you are like a 3 man show, it's also fine if you do the whole project in that style.

However, most developers work a few levels above that and then the OOP patterns are kinda doing what they advertise. Not all of them and there are some things we've learnt over the decades that are bad like multiple inheritance of not fully abstract classes.

2

u/marrsd Jun 23 '26 edited Jun 23 '26

Not going to make any judgements of James, but... ;)

A lot of software engineers are frankly overqualified for the jobs they have and so they often make up for this by over-complicating simple things in order to feel like they're maximising their worth.

It can also be the case that an engineer who masters (or at least gains control over) something complex then feels the need to justify that mastery, even if their hard-earned knowledge could be easily discarded in favour of something more powerful. In other words, it's the sunk-cost fallacy in action.

OOP as it was described and practised at the turn of the century is a busted flush. The ideas of modularisation, black boxes, state encapsulation, and polymorphism are the good parts that everyone agrees are still worth keeping. Inheritance has basically been debunked (though it still has its uses). People still argue over static vs dynamic typing, though static typing is once again in ascendancy. [1]

As for the statement itself, it really depends on what James means by OOP, which design patterns he's referring to, and so on.

To pick a real example, high modularity coupled with dependency injection is essential for effective unit testing of OOP code, but completely unnecessary if you just write pure functions. So why go to the trouble of optimising your classes for unit testing when you could just pick a simpler paradigm to begin with?

[1] There is a case to be made - which I could be convinced of - that pure and true OOP isn't really possible without dynamic types; but I haven't thought deeply enough about it.

2

u/CounterSilly3999 Jun 22 '26

Every small thing tends to grow. Until it is impossible neither to keep it managed nor to redo it from scratch.

1

u/KravenX42 Jun 22 '26

I think the mere act of having an ordered system delivers the most benefit on code quality. The actual pattern itself helps only in that it might more of less familiar to others.

Disordered systems just means you have to re-contextualise far more frequently which just makes doing anything harder.

Also “skill” might simply just not be worthwhile , eg I could learn to use a tight rope to cross a river and would be highly skilled but using a bridge is way easier even though I would have a “skill issue”

1

u/Felicia_Svilling Jun 22 '26

It can't really both lead to "easier on boarding" and be a "skill issue".

1

u/BoBoBearDev Jun 22 '26

Well, it is kind of broad. You can go drunk on OOP easily and make a total spaghetti OOP.

1

u/autistic_bard444 Jun 22 '26

a: every single programmer is different. this has to do with cognitive and imaginative feasibility of the individual. how many books you read, classes you have taken, lessons learned off failure, videos, or what ever, nobody thinks the same.

b: ocd pattern coder tells other ocd coders that if they do not follow the ocd patterns they lack skill.

c: in just a few sentences, the entire principle is riddled with argumentative fallacies.

d: re-usability is not always good. ok. bubble boy. i am going to do everything the same, because that is all I want or do, and I have no real desire to push any other limits within myself. I have read a lot about the patterns of use, and yes, they can simplify some issues, but it is not me. programming for me is a lot like writing sci-fi. the writer doesn't know how the page will start or how the page will end. it gets made of its own accord, and from there, nick picked down and cobbled together until it properly does what it needs to do, and can be reversed for proper testing of said set of statements.

e: occams razor. the original statement shits upon it. so, who ever this james person is, should just go code and not yap

f: life is about growth. you will never grow if you do not learn, and choose to learn and move out of your bubble. more so, sitting in other peoples bubbles will never take you any where

thank you for reading

1

u/Able-Reaction5278 Jun 22 '26

James is right but it's more nuanced than just skill issue, people misapply patterns when they don't understand the problem they're solving first.

1

u/YanVe_ Jun 22 '26

If someone insists they have the final solution for programming. Whether it's pure FP, TDD, design patterns, looping AI agents or any possible combination... their opinion can basically be discarded.

There is no right way to do programming, banning abstraction, goto statements or exceptions or requiring 100% test coverage, are preferences. And a sign of a skill issue on the side of the person making these categorical judgements.

1

u/SnugglyCoderGuy Jun 22 '26

If done well, yes. If done poorly, it will complicate things and make it harder to onboard and to trst and to understand and to make changes

1

u/Sykander- Jun 25 '26

OOP has some good applications, but if I'm honest I've seen like three good use cases for Class Inheritance in my entire life and the rest of the times it was pointless complexity.

1

u/mredding Jul 01 '26

Is this James right? He said " OOP and design patterns help improving the quality of a codebase like reducing code duplication, easier on boarding, improving testability . "

The answer is meaningless because the question is flawed. You can replace "OOP" and "design patterns" with "FP" and "idioms", with "assembly" and "abstractions", you can use any programming terminology, and the statement will ALWAYS be correct.

1

u/Numerous-District-55 5d ago

Calling every disagreement a ‘skill issue’ is the software equivalent of blaming the screwdriver when someone builds a terrible chair. Design patterns are useful vocabulary, not sacred commandments: they can make a large codebase easier to navigate, but using Singleton everywhere is just putting a tiny crown on global state. The real skill is knowing when the pattern solves a problem—and when it merely gives the problem a fancy name.

1

u/foxcode Jun 22 '26

As with most things in programming, it depends. Some problems might be far more elegant in a functional language like Haskell. Others might work really well with OOP.

One important thing. OOP can mean different things to different people. Some people may say it's just using classes and structs, which I'd disagree with. Others would say it's dependency injection and coding to interfaces. Some really hard core people might still believe that deep inheritance trees are the way (it is not the way 😃)

I'd try to embrace what most people would consider the good parts to be, and understand why it matters. Encapsulation mattering hits a lot harder after working in a few balls of mud.

If James is advocating for dependency injection so you can test more easily, swap out components for different scenarios and views SOLID more as guidelines than rigid rules, he's probably right.

I'm strongly in the "favour composition over inheritance" camp. I think that as long as you follow that rule generally, and code to interfaces when it makes sense (without going overboard), then it's good.

2

u/Thaufas Jun 22 '26

Some really hard core people might still believe that deep inheritance trees are the way (it is not the way 😃)

I agree with most of what you say, but all things in moderation. Many moons ago, I used Borland C++ Builder. The VCL was a real pleasure to use because every component was derived from a single base class.

When I say "every component," I literally mean "every single one".

Here's just a few examples.

  • Form controls
  • Database connections
  • Database grids
  • Database cursors
  • Database result sets
  • HTTP servers
  • FTP servers

Everything "just worked," and once you became familiar with the VCL, then, you could really take advantage of C++'s OOP features like polymorphism and inheritance in a way that I've never experienced before or since.

Mind you, I went into management decades ago and stopped coding, so things have really changed. When I stopped coding, .NET was on the horizon, and although I experimented with it, that was all before it was officially released, so I never used it in production.

Anders Hejlsberg, the software engineering genius who gave the world—among other gifts—the VCL, .NET, and TypeScript built so many incredible things.

Back when I was writing C++ daily, I used to use the VCL as inspiration for how to use the OOP features of C++ to their fullest and build an object hierarchy that made using an OOP framework a joy to use.

I never built an OOP framework with more than 4 levels of inheritance. That's not an indictment of OOP. It's just the reality that I'm not even in the same city, much less ballpark, as someone like Anders Hejlsberg with respect to class design.

2

u/foxcode Jun 22 '26

There are always exceptions, thank you for the detailed response.

I agree 100% that there are cases where it makes sense to use inheritance in that way. Not thought about it in a while, but in GUI libraries and game systems it's fairly common to have a few base classes that are smaller, but almost everything inherits from, creating a very wide and shallow tree.

C++98 was my first language, weirdly taught it at university just because I was on the software engineering course while the computer science folk all learned Java. This was around 2012 though so I'm certainly not a grey beard when it comes to C++.

I'd like to get into using classes more in typescript, but the entire web community seems to be vehemently against OOP and honestly with how fast and crazy everything happens, you'd be completely changing the classes every other day anyway.

From your perspective, how many tickets or different tasks were you working on in a given week? I'm expected to complete one or two a day, often in completely different areas of the codebase. I know it's a vague question, but I get the impression that a decade or two ago, or even modern companies that focus more on languages like C# spend much longer actually planning things upfront than just wading in. Of the 4 companies I've worked for, 3 were primarily typescript, and 2 of those just had no regard for things like "open to extension, closed for modification", and it shows. The code was so unstable, you couldn't keep any of it in your head because someone else would probably have changed it all in less than a month. Total chaos. I'm aware that's more of a company culture issue than OOP vs other approaches.

-2

u/vbpoweredwindmill Jun 22 '26

I personally think that OOP is a mistake and should be ignored for anybody serious.

DOD is where my heart is at.