A Love Letter to Over-Engineered Object-Oriented Programming
Why is this DesignPatterns Architecture meme funny?
Level 1: Why So Complicated?
Imagine you want to do something simple, like pour yourself a glass of water. Now picture doing it the really hard way: You build a big machine with five doors in a row, one behind the other. Each door has a special key, and you need to unlock them one by one to finally get to the faucet. And because the machine is so shaky, you have to check at every step that nothing broke (like, “Is door 1 still okay? Yes. Open it. Is door 2 still okay? Yes. Open it...”). That’s pretty silly, right? You could have just walked up to the faucet and poured the water directly.
The tweet is joking about a similar idea in coding. Functional programming is like just pouring the water straight – it’s a simpler way to get things done using straightforward steps (functions). The super complicated thing with “5 levels of inheritance” and a “FactoriesFactoryManagerSingleton” is like the five-door machine – an overly complex way to do something that probably could be done more simply. Checking for “null” every few lines is like checking that those doors aren’t broken every few seconds.
It’s funny because nobody would actually prefer the complicated way on purpose. The tweet pretends that someone says “No thanks” to the easy way and loves the complicated way, which is an obvious joke. It highlights how absurd it would be to choose a tangled, breakable solution over a simple, reliable one. In simple terms, the meme is laughing at making things harder than they have to be. It reminds us that sometimes the simple approach is the smarter choice, no matter how “cool” the complicated machine might sound.
Level 2: Design Pattern Soup
Let’s unpack the jargon and concepts in that tweet one by one, in a more straightforward way. The tweet pits functional programming against an exaggerated form of object-oriented programming (OOP), specifically highlighting some OOP concepts taken to extremes. Here’s what those terms mean and why they’re mentioned:
Functional programming (FP): This is a programming style where you build your program using pure functions (functions that, given the same input, always return the same output and don’t cause side effects). In FP, you avoid changing state and avoid things like global variables. Code tends to be written as a set of small, reusable functions. For example, instead of objects with methods, you might have a function
processOrder(order)that returns a new processed order, without modifying the original. One result of this approach is usually simpler dependency management – you just call functions and get results, rather than constructing a lot of objects that manage other objects.Object-oriented programming (OOP): This is a programming style where you organize code into classes (blueprints for objects) and objects (instances of those classes). Objects encapsulate data and behavior together. A key feature of OOP is inheritance – a way for one class to extend another, inheriting its traits and possibly adding new ones or overriding behavior. The idea is to model real-world hierarchies (like a
Carclass inheriting from aVehicleclass might inherit properties like wheels, and then add its own specifics). In moderation, inheritance can avoid code duplication. But deep inheritance (where Class E inherits D which inherits C which inherits B which inherits A) becomes hard to follow. Each “level” is a new class layered on top of another. The tweet mentions 5 levels of inheritance, which means you’d have to understand five different classes to know what’s really happening in the bottom-most one. Imagine a story that’s been retold and modified by five different people in a line – by the end, it’s pretty confusing! That’s what working with too many inherited layers can feel like.Factory: In programming, especially OOP, a Factory is something that creates objects for you, usually so you don’t have to know the exact class or details of how to create them. For example, instead of calling
new Button()directly in code, you might callUIElementFactory.createButton()and it gives you a Button. Why do this? Perhaps your code wants an interface and doesn’t care about the concrete type, or you might decide later to return a different kind of Button (say aRoundButtonvsSquareButton) without changing the code that asked for it. A FactoriesFactory as jokingly mentioned would be a factory that produces other factories. This is actually a known concept called an Abstract Factory – basically, depending on some configuration, you get one factory or another. It’s a level of indirection: instead of directly making aButtonFactory, you ask a higher-level thing to give you the rightButtonFactoryfor the job. You can see how these layers start adding up. In plain terms, it’s like having a factory that manufactures other factories – pretty wild, but sometimes used in complex systems.Manager: This is a very common term in class names that usually implies “this class oversees or coordinates a set of tasks or objects.” For instance, a
DatabaseManagermight handle connecting to the database, running queries, etc. AFactoriesFactoryManager(as per the tweet’s absurd example) suggests an object that manages a bunch of factories (which themselves might be making other objects). When you see “Manager” in code, it’s often a hint that the class might be doing a lot of work or is a central control point. If overused, “manager” classes can become catch-alls for functionality that didn’t have a clear place – leading to very bloated classes. It’s often better to have more specific classes or functions rather than one manager that does everything.Singleton: The Singleton pattern restricts a class so that only one instance of that class can ever exist at a time (and it often provides a global way to access that instance). Typically, you make the constructor private and have a static method like
getInstance()that either creates the single instance or returns the existing one. For example, you might use a Singleton for aConfigurationclass to ensure all parts of your program use the same configuration object. The downside is that singletons act a bit like global variables. If many parts of code use that single instance, it can introduce hidden dependencies — suddenly, functions that didn’t explicitly take that object still rely on it being there. It also can make testing harder because you can’t easily have two configurations or a fresh one for a test. In many modern languages and frameworks, singletons are seen as a necessary evil at best, and an anti-pattern at worst, unless carefully used.
Now, imagine rolling all those things into one class. That’s what FactoriesFactoryManagerSingleton is humorously describing:
- It likely is a Singleton (only one instance, globally used).
- It manages something (likely a bunch of factories).
- Those factories it manages… create other objects, and possibly the factories themselves are produced by some meta-factory (hence the double “FactoriesFactory” in the name).
It’s a mouthful, and intentionally so – it’s poking fun at the kind of excessively complex naming that comes from overly convoluted architecture. Each term in that name is a hint at a code smell (a symptom of poor design):
- Too deep inheritance (implied by such elaborate roles – these patterns often come with layers of classes).
- Overuse of patterns (factory of factory, manager, singleton – it’s like someone tried to use every pattern they learned in a single design).
- Global state / tight coupling (singleton usage).
- Possibly unclear responsibilities (if it’s a manager of factories, is it doing more than one job? Likely yes).
Finally, the tweet jokes about null checks:
- Null checks every 3-4 lines: In languages like Java, C#, or C++, accessing something that’s
null(ornullptr) that shouldn’t be can crash your program (or throw an exception). So developers defensively check if things are null before using them. For example:
If you see code that has a null check almost every few lines, it hints that lots of things can be null or come back as null. This is often a sign of poor design because ideally, you’d structure your code to avoid having to constantly worry about missing values. For instance, you might ensure a variable is initialized to a default value, or use optional types that force you to handle the absence of a value in a clearer way. In functional programming, one might use anif (user != null) { String name = user.getName(); // ... }Optiontype or similar, which makes the possibility of “no value” part of the type system (you can’t forget to handle it because the code won’t compile otherwise). In a simpler design, you’d not have objects floating around in an uninitialized state so often. The tweet’s author is clearly poking fun at a style of programming where nulls are so prevalent that checks litter the codebase – it’s both tedious and error-prone.
In summary (for this level): The tweet humorously contrasts two approaches:
- Functional programming (FP): “No thanks” is said sarcastically, implying FP offers a simpler, cleaner way (fewer classes, likely less need for null checks, more straightforward code flow).
- Over-the-top OOP with deep inheritance and multiple patterns: Embraced ironically – the author doesn’t actually think this is good, they are highlighting its complexity.
For a newer developer, the takeaway is: the meme jokes that someone claims to prefer the complicated solution (lots of layers and checks) over a simpler one. It’s funny because in reality, we usually want the opposite. This tweet is a reminder of what happens when code architecture goes overboard. It’s as if a chef was trying to use every single spice in the kitchen for one soup – you end up with a confusing flavor. In coding terms, simpler solutions (like those in functional programming, or just well-designed OOP with composition and clear structure) are often easier to work with than an over-engineered tangle of classes contingent on numerous patterns and null checks. The humor is a bit self-deprecating for the software industry: we sometimes make things far more complex than they need to be.
Level 3: Factory-Factory Folly
This tweet drips with senior developer sarcasm, and every experienced engineer reading it is probably smirking (or cringing) in recognition. It’s mocking the tendency to over-engineer using object-oriented design patterns to an absurd extent. Let’s break down the humor:
“5 levels of inheritance” – In real-world code, an inheritance depth of five is a maintenance nightmare. This means you have class
Einheriting fromD, which inherits fromC(and so on up toA). By the time you’re in classE, you need a whiteboard and a lot of caffeine to figure out which ancestor defines the method or behavior you’re seeing. Experienced devs know that deep inheritance often signals trouble: fragile designs, hidden dependencies, and a violation of the “prefer composition over inheritance” guideline that we hear in Clean Code circles. The tweet exaggerates to five layers to lampoon that architecture astronaut style where someone, somewhere said “Hey, three layers of abstract classes is not enough, let’s add two more!”“FactoriesFactoryManagerSingleton” – This monstrous class name is a cocktail of classic Design Patterns all muddled together, effectively a big anti-pattern flag. Each part of the name hints at a pattern or role:
- Factory: In software, a Factory is an object whose job is to create other objects. It’s a useful pattern (the Factory Pattern) when you need flexibility in what concrete classes you’re instantiating or to encapsulate complex creation logic. But here we have FactoriesFactory – implying a factory that makes factories. That’s actually a thing in formal terms (an Abstract Factory creates families of factories), but saying it so bluntly (“FactoriesFactory”) highlights how ridiculous it sounds. It evokes that enterprise code smell where you might have an
AbstractWidgetFactoryFactorysomewhere in a legacy codebase. This is the kind of design that might emerge in a big corporate project where every little operation has an object and every object has a factory… and then someone made a factory to configure which factory to use. It’s both grandiose and comical. - Manager: The word “Manager” in a class name often signals a God Object or at least a do-it-all class that orchestrates many things. It’s one of those vague terms (like “Utils” or “Helper”) that can mean almost anything. When a class is called
SomethingManager, it often ends up growing tentacles into various parts of the system, managing so many aspects that it becomes hard to maintain. Seeing “Manager” tacked onto “FactoriesFactory” suggests this class not only creates factories, it manages them too – as if having factories of factories wasn’t enough, we need an overseer coordinating the madness. It’s a wink to those who have seen an over-engineered architecture where there’s an object for everything under the sun. - Singleton: Ah, the Singleton Pattern – ensuring only one instance of a class exists globally. It’s often taught as a basic pattern (maybe too early in one’s education), and it has legitimate uses (like a single configuration or logging object). But singletons are also notorious for fostering global state and hidden couplings. Many seasoned devs groan when they see a singleton because it can act like a global variable in disguise, making testing harder and causing weird side-effects if not careful. By appending “Singleton” to that already overstuffed class name, the tweet hints that this class is a globally accessed, one-of-a-kind monstrosity. In practice, combining “Manager” and “Singleton” often means you have a global god object—the exact opposite of modular, clean design.
Put together,
FactoriesFactoryManagerSingletonsounds exactly like a class you’d find in a “enterprisey” codebase that tried to implement every GoF design pattern at once. It’s like someone read the entire Design Patterns book and decided to use all the patterns in one class for good measure. In fact, Java developers might recall humorous references or real examples likeAbstractSingletonProxyFactoryBean(an actual class name in the Spring framework) – these overly descriptive names arise when patterns get layered ad absurdum. The meme exaggerates, but not by much; some of us have debugged something not far off from this, late at night, cursing whoever designed it.- Factory: In software, a Factory is an object whose job is to create other objects. It’s a useful pattern (the Factory Pattern) when you need flexibility in what concrete classes you’re instantiating or to encapsulate complex creation logic. But here we have FactoriesFactory – implying a factory that makes factories. That’s actually a thing in formal terms (an Abstract Factory creates families of factories), but saying it so bluntly (“FactoriesFactory”) highlights how ridiculous it sounds. It evokes that enterprise code smell where you might have an
“a couple null checks every 3-4 lines” – This is the cherry on top. Frequent
nullchecks in code are usually a sign of either a language without null-safety or a design that isn’t handling optional/absent values in a clear way. It implies the code constantly has to ask “Is this thing here? No? Okay, do something else” repeatedly. This is a hallmark of defensive programming in brittle systems where things aren’t initialized when you expect, or perhaps global objects might benullbecause of initialization order issues (common with singletons and complex startup logic). Seasoned devs recognize this as “null-check hell.” It’s both tedious to write and easy to mess up (miss one check and boom – NullPointerException at runtime). The tweet sarcastically touts this as a feature! Why would you want null checks peppered everywhere? You wouldn’t – it’s laborious and error-prone. Modern Clean Code principles suggest using clearer approaches: if something can be absent, maybe use an Optional type or default value, or better yet design the code so you don’t pass nulls around. But in the kind of legacy mess being caricatured, developers often plasterif (x != null)all over the place just to keep the app from crashing. It’s like duct tape on a leaky pipe. The dark humor here: the author pretends this is desirable, highlighting by contrast how much nicer it is when you don’t need these checks (as is often the case in well-designed or more functional-style code).
Why is this so funny (or painful) to experienced devs? Because we’ve all seen something like this. The tweet is basically saying, “Who needs those fancy modern paradigms (functional programming) that might simplify things, when I can enjoy the masochistic pleasure of ultra-complex OOP?” It’s tongue-in-cheek. No one actually prefers a five-layer inheritance deep-dive with a side of NullPointerExceptions — that’s exactly the point. It’s mocking the absurdity of over-engineering.
In real organizations, this happens more than we’d like to admit. Sometimes it’s due to cargo cult programming – developers implementing every pattern they read about, whether it’s needed or not. Other times it’s the result of overly general framework-building. For example, you start with a simple idea, but someone says “We might have different types of objects to create, so let’s add a factory. Oh, we might switch factories at runtime, so how about a factory that produces factories? Also, we only ever want one factory manager instance – bingo, make it a singleton! And while we’re at it, let’s add layers of abstract classes so we can swap out any part of the process.” Before you know it, a simple task is buried under an avalanche of abstractions. Each layer feels logical in isolation, but the end result is a towering Jenga stack of code that barely does the job and is scary to touch.
This tweet resonates with developers who have suffered that complexity. It implicitly advocates for the opposite approach through sarcasm: maybe consider functional programming or simpler design next time. In functional programming (or just cleaner OOP), you might handle this scenario with, say, a straightforward function or two, maybe a simple factory function and no global state, and strong types that avoid nulls. The difference in code quality and maintainability is night and day. So reading the tweet, experienced devs laugh (or groan) because it satirizes a truth: too often we see codebases that chose the convoluted path, and dealing with them is a form of cruel and unusual punishment. The humor is a coping mechanism – if we didn’t laugh, we’d cry about the hours lost in FactoriesFactoryManagerSingleton.java.
Level 4: Lambda vs Layers
At the core of computer science, this meme highlights a clash between two paradigms with very different philosophies: functional programming and deep object-oriented programming with heavy use of inheritance. Functional programming has roots in lambda calculus – a formal system developed by Alonzo Church that treats computation as evaluation of mathematical functions. In lambda calculus, there’s no concept of objects or mutable state; everything is about composing pure functions. This leads to immutable data structures and reliance on function composition (e.g. f(g(x))) as the primary way to build complex behavior. The result? Code that avoids side effects and often doesn’t even have a null concept – many functional languages use an Option/Maybe type instead of a null reference, eliminating a whole class of errors. (Tony Hoare, who invented the null reference in 1965, infamously called it his “billion-dollar mistake” for all the bugs it caused!)
Object-oriented programming, on the other hand, emerged from simulations (Simula, Smalltalk) aiming to model the world as objects. It introduced classes, inheritance (a way for classes to derive from and extend other classes), and often encourages structuring code in taxonomies of types. In theory, inheritance lets you reuse code and represent “is-a” relationships (a Car is a Vehicle). But a deep inheritance chain (5 levels in this case) means you have layers upon layers of abstraction. Each layer can override or extend behavior, which makes reasoning about the program like tracing through a multi-layered maze. In formal terms, deep inheritance can violate the Liskov Substitution Principle (one of the SOLID principles) if a subclass isn’t fully substitutable for its parent, leading to fragile designs. The more layers, the more the subclasses must intricately understand the parent classes – a recipe for complexity explosion.
The tweet’s absurd class name FactoriesFactoryManagerSingleton strings together multiple design patterns (Factory, Manager, Singleton) into one mega-object. From a theoretical perspective, each of these patterns addresses a limitation in simpler languages: A Factory is basically a function that creates objects (something functional programming handles by passing around functions easily), and a Singleton is essentially a globally accessible object (which a functional approach might avoid by using function parameters or closures to carry needed state). In fact, many classic OOP design patterns can be seen as workarounds for missing language features. As the influential computer scientist Peter Norvig pointed out, design patterns in OOP are often things that dynamic or functional languages do out of the box. A Factory is just a first-class function. A Singleton is often just a module or a closure capturing state. When you pile these patterns up (a factory that makes factories that you access via a singleton…), you’re compensating for constraints of the paradigm.
So the humorous contrast here has deep roots: it’s poking fun at how an over-engineered OOP solution (born from the layers-upon-layers mindset) stands against the minimalism of functional solutions. It’s like comparing a hierarchical bureaucracy of objects to a mathematical function that just takes input to output directly. One leverages the composition of functions (a concept so pure it’s studied in category theory) while the other nests objects within objects, managers managing managers – a structure that satisfies an OOP worldview but can become unwieldy. At a paradigmatic level, the meme is a mini commentary on composition vs. inheritance: functional programming prefers composing simple pieces (like monoids composing or monads chaining operations) rather than building tall class hierarchies. The result? With functional code you often get fewer null checks (sometimes none at all) and more predictable behavior, whereas deep OOP designs can devolve into checking for null everywhere and juggling complex object lifecycles. The tweet sarcastically chooses the latter, highlighting the irony that the theoretically “clever” OOP patterns often create practical headaches, whereas the theoretically “academic” functional approach can yield elegant simplicity.
Description
A screenshot of a tweet from user Aron Adler (@Aron_Adler). The tweet is displayed in white text on a black background. It sarcastically rejects functional programming in favor of overly complex object-oriented practices. The full text reads: "'functional programming? no thanks I prefer 5 levels of inheritance for my FactoriesFactoryManagerSingleton with a couple null checks every 3-4 lines'. The humor is derived from its sharp critique of common software development anti-patterns, particularly those associated with older, enterprise-style Java or C# codebases. It mocks deep and brittle inheritance hierarchies, ridiculously verbose class names that shoehorn multiple design patterns (Factory, Singleton) together, and the resulting fragile code that requires constant null-checking. It's a relatable joke for any senior developer who has had to maintain such a codebase
Comments
26Comment deleted
The original architect of the FactoriesFactoryManagerSingleton is a legend. They say he could abstract an abstraction, wrap it in a proxy, and still have it pass the daily build, leaving the problem of what it actually does as an exercise for the maintenance team
Why pass a pure function when you can pass the trauma? Our codebase extends AbstractChainedFactoryManagerSingletonProvider<T> all the way back to SVN history - by the time a null sneaks through, it’s practically an heirloom
The only thing deeper than that inheritance hierarchy is the stack trace when your FactoriesFactoryManagerSingleton throws a NullPointerException in production at 3am, requiring you to traverse through AbstractBaseFactoryImpl, FactoryProviderInterface, and three proxy layers just to find out someone forgot to initialize the config bean
Ah yes, the classic FactoriesFactoryManagerSingleton - because why use a simple function when you can architect a monument to enterprise complexity? Five inheritance levels deep ensures that when something breaks at 3 AM, you'll need to traverse an entire genealogical tree just to understand what's happening. And those null checks every few lines? That's not defensive programming, that's Stockholm syndrome from languages that never heard of Option types. Meanwhile, functional programmers are over here composing pure functions like it's 1958 and Lisp just dropped, wondering why we're still manually checking if objects exist before calling methods on them. But hey, at least your UML diagrams look impressive in architecture reviews - right before someone asks 'couldn't this just be a function?'
Five layers of inheritance and a Singleton - congrats, you’ve reinvented a global service locator where the null checks moonlight as your runtime-only type system
FP purity? Nah, real architects nest factories until nulls echo through the inheritance abyss like a bad design pattern symphony
Nothing like a 5-deep inheritance chain and a FactoriesFactoryManagerSingleton to turn null handling into your type system - NPE-driven architecture at enterprise scale
don't qq Comment deleted
my refactoring ass: 🤭 Comment deleted
google golden ratio Comment deleted
Still better than "functional" programming. Comment deleted
What do they actually mean by the term "functional"? Comment deleted
functioning Comment deleted
Not sure considering most languages support FP features Comment deleted
Who implemented these 5 levels of inheritance? Comment deleted
ItemsFactoryFactoryImpl is much better than CoproFunctors and IOMonad Comment deleted
Can somebody explain what singleton is? Comment deleted
Is that some high level programming style? Comment deleted
Bruh wtf why? Comment deleted
can be used for global conf eg database connection Comment deleted
Okay I am not very used to dbs so I can’t really say much with confidence but sounds interesting Comment deleted
Imagine you have an app that needs a threadpool to run REST requests in a background. If it's a client app, usually one threadpool is sufficient, so it's easier to write client code with one global threadpool in mind Comment deleted
Okay but whats the benefit of singleton? Comment deleted
You can access it from everywhere through class interface without knowing where it was instantiated Comment deleted
https://wiki.c2.com/?SingletonPattern https://en.m.wikipedia.org/wiki/Singleton_pattern Comment deleted
Me doing procedural programming mainly be like 😀 Comment deleted