惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
L
LangChain Blog
博客园_首页
量子位
Stack Overflow Blog
Stack Overflow Blog
F
Fortinet All Blogs
S
Secure Thoughts
P
Privacy & Cybersecurity Law Blog
H
Help Net Security
T
Threatpost
N
Netflix TechBlog - Medium
Cyberwarzone
Cyberwarzone
P
Proofpoint News Feed
C
Cisco Blogs
G
Google Developers Blog
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
InfoQ
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
U
Unit 42
博客园 - 三生石上(FineUI控件)
Recent Commits to openclaw:main
Recent Commits to openclaw:main
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
WordPress大学
WordPress大学
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
C
Check Point Blog
TaoSecurity Blog
TaoSecurity Blog
Project Zero
Project Zero
www.infosecurity-magazine.com
www.infosecurity-magazine.com
SecWiki News
SecWiki News
F
Full Disclosure
S
Security @ Cisco Blogs
T
Tor Project blog
V
V2EX
Y
Y Combinator Blog
S
SegmentFault 最新的问题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
GbyAI
GbyAI
B
Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell

Lobsters

CIFSwitch: a non-universal Linux local root vulnerability RIPE NCC session fixation: poaching logins with an Atlas probe GNOME 2.20 but its Web Components Agentic Search for Context Engineering – Leonie Monigatti Garnix is shutting down [not OC] akashina.tngl.sh/jjc Concerning Emacs (and Jazz) Nitpicking the shell history scene in ‘Tron: Legacy’ What's cooking on SourceHut? Q2 2026 The tenth OpenPGP email summit Package managers that package package managers Clojure on Fennel part three: parsing WordPress at 23 Finding Miscompiles for Fun, Not Profit GitHub - creusot-rs/creusot: Creusot helps you prove your Rust code is correct. Announcing Rust 1.96.0 | Rust Blog A Love Letter to Neovim sqlite AGENTS.md Am I a Bad Friend? CSS vs. JavaScript • Josh W. Comeau Erlang Ecosystem Foundation - Supporting the BEAM community A brief note about slot access cost in Common Lisp Keyboard latency probe Rethinking the GNOME clipboard issues Back to the Building Blocks’ Building Blocks Tech Notes: Theseus: translating win32 to wasm Fast is better than slow Content-addressed Rust builds (or, what kache actually caches) Intent to Prototype: Embedding API Canada’s Bill C-22 and the security cost of collecting more data 5 PostgreSQL locking behaviors that trip people up okmij.org Stop advertising in your commits! | AksDev GitHub - mplsllc/macsurf: A modern web browser for Classic Mac OS 9 PowerPC. Real CSS3, ES5 JavaScript, native HTTPS — built with CodeWarrior on the Carbon API. Introducing DoomBench - Can Your Data Stack Run DOOM? What are some of your favourite developer tools? Building a Scalable Ingestion Pipeline with Temporal (Part 1) Converting shallow Git bundles into normal repositories Are you a member of any professional associations? What is a harmonic? An interactive comic about additive synthesis How Virtual Tables Work in the Itanium C++ ABI Using SwiftUI to Build a Mac-assed App in 2026 Rust (and Slint) on a jailbroken Kindle. ~jack/lambda-on-lambda - Serverless Haskell on AWS - sourcehut git Human proof for FOSS contributions Extremely simple internet radio controlled via IRC Announcing BABLR Splitting Konsole views from Helix to run tools | AksDev GitHub - yugr/rust-slides Serving files over HTTP three ways: synchronous, epoll, and io_uring update docs with information about building with build.py (#979) · astral-sh/python-build-standalone@c9c40c5 A Simple Makefile Tutorial On C extensions, portability, and alternative compilers Switching to Colemak | Pedro Alves Just How Bad Was The Intel IAPX432? Nix's Substituter List Is Not a Routing Table Accelerating copy_if using SIMD Lambda on Lambda: Serverless Haskell on AWS | Blog Announcing feed-repeat v1.0 Scaling Akvorado BMP RIB with sharding EYG news: A host of CLI improvements, new guides and new effects The social contract of writing JS Crossword C array types are weird; and related topics Flatpak will depend on systemd – OSnews Migrating from Go to Rust | corrode Rust Consulting A portentous reunion Vivado Licensing Options How my minimal, memory-safe Go rsync steers clear of vulnerabilities the entropy layer of a wavelet codec, on its own GitHub - nferhat/fht-compositor: A dynamic tiling Wayland compositor. Debian SE Linux and PinTheft Does bulk memmove speed up std::remove_if? (No.) 声明式部分更新 | Blog | Chrome for Developers Fully in-browser container builds Dianne Skoll's Web Site - Remind The Architecture of Open Source Applications (Volume 1)Berkeley DB Pardon MIE? - ironPeak Blog “Long-Term Support” doesn’t mean what you think Jira IS Turing-Complete May I recommend thinking of Emacs as your Fortress of Solitude hershey Floodgap Gopher-HTTP gateway gopher://thelambdalab.xyz/1cuneiforth/ HP QuickWeb, Singular And Pointless That one time I used Go panics for flow control A new suite of modern tools coming for editing and publishing RFCs From the Tabletop… The Digital Antiquarian Building a Host-Tuned GCC to Make GCC Compile Faster Are we self-sovereign PKI yet? Claw Patrol: an open-source security firewall for agents | Deno Revised^7 Report on Scheme, Large: Procedural Fascicle Draft is now public A Network Allow-List Won't Stop Exfiltration — André Graf From AFSK to Goertzel – µArt.cz Software For My New Home Server Introducing Neptune: Direct3D virtualization for QEMU AI Agent Bankrupted Their Operator While Trying to Scan DN42 - Lan Tian @ Blog mimalloc: A new, high-performance, scalable memory allocator for the modern era Making wl_shm fast The Soul of Maintaining a New Machine - Third Draft | Books in Progress What is Git made of?
Design Patterns Suck
Kirill Bobrov · 2026-06-26 · via Lobsters

In software engineering, the term "design pattern" (which, honestly, is kind of redundant — aren't all patterns designs?) gets thrown around a lot. It originally came from architecture — actual architecture, with buildings and floorplans — not software.

But in 1994, the software world got its own version when the now-infamous book"Design Patterns" was published by Gamma, Helm, Johnson, and Vlissides — aka the "Gang of Four" (GoF). They introduced 23 canonical patterns as higher-level abstractions than function calls. These patterns were meant to be language-agnostic, reusable templates for solving recurring software design problems.

Sounds nice, right? Almost too nice...

The problem is that design patterns have been elevated from useful vocabulary into something closer to dogma. They're taught as universal solutions, applied where they aren't needed, and treated as a mark of good engineering.

The reality is: Design patterns suck.

Yeah, I said it.

Design patterns are overrated, overused, and often flat-out unnecessary.

That might sound harsh, especially those of you who keep their Gang of Four books near their bedsides, but hear me out. Most of the time, design patterns are nothing but ugly workarounds for the fact that our programming languages aren't powerful enough or flexible enough to express what we actually want.

Java and Its Love Affair with Boilerplate

Take Java, for example (I'll be bashing Java quite a bit today, so get comfortable). Where do we even start? Java is the poster child for "design-pattern-mania". Every single project looks like a carbon copy of itself because Java developers are taught to just dump in as many patterns as possible.

It's the language that practically forced design patterns into mainstream use. Why? Because Java is verbose, stiff, and lacks expressiveness. It's like writing a novel where you're only allowed to use three-syllable words — every problem feels ten times harder than it has to be.

Oh, you're working on a simple CRUD app? Better throw in a Factory, maybe an Observer for that database change notification, and don't forget the Singleton — because, y'know, we all need a global logger, right?

Pattern vs Language Feature

The crux of why design patterns are often garbage is that most of the time they exist only because the language itself is missing some capability. You're basically doing workarounds for language limitations.

Take the Singleton pattern as an example. You've seen this a thousand times:

public class Logger {

    private static Logger instance;

    private Logger() {}

    public static Logger getInstance() {
        if (instance == null) {
            instance = new Logger();
        }
        return instance;
    }
}

That's like 15 lines of code just to say, "I want only one instance of this thing". What are we, cavemen? We shouldn't need to hand-write this kind of thing. A modern language should provide constructs to handle this elegantly, but nope, not Java. Instead, we get tons of boilerplate and complexity masquerading as "best practices".

Want to see how Scala handles it?

object Logger

That's it. That's the entire Singleton pattern. Done.

No need to mess around with static blocks, thread safety, or lazy instantiation nonsense. Scala does what Java should have done in the first place: treat this as a basic language feature, not a pattern you need to manually enforce. Java forces you into this mess because it doesn't have first-class functions. It's the language's fault, not yours, that you're writing a Strategy pattern.

Design patterns aren't solving problems with your code; they're solving problems with your language.

A Factory pattern? That's just Java's refusal to give you proper constructors or a way to handle complex object creation natively. In languages like Python, Ruby, or Scala, you rarely need a Factory. In fact, most of the design patterns Java developers go on about just vanish in more flexible, expressive languages.

Take Python for example:

  • Need a Factory? Just pass a function or use __init__ smartly.
  • Want a Singleton? Throw in a module or a class that you initialize once, and call it a day.
  • Observer? Well, functions are first-class citizens. Just pass them around.

The fact is, in a language that's expressive enough, patterns either become trivial or, better yet, they just don't exist. You handle the problems directly, not by wrapping them in abstractions that someone else cooked up 20 years ago in a language that hasn't aged well.

The Cult of Overengineering

The Cult of Overengineering

Design patterns also feed into a deeper problem in the software world: overengineering. I've seen junior engineers (and some senior ones, unfortunately) who get this wide-eyed look when they hear "design patterns" and immediately try to shoehorn as many as possible into their project.

They're solving imaginary problems.

When this happens, the codebase goes from something understandable to something unreadable, fragile, and overly abstracted. It becomes a labyrinth of interfaces, factory methods, and weird naming conventions that make you feel like you're trying to interpret ancient texts.

"Good" design patterns tend to be over-engineered because they are required to cater to as many use cases as possible. Over-engineered code has a cost though: you have to read it, understand what it does, and understand how it works within the context of the entire software system. Consequently, as with any other software development technique, you have to evaluate the technique against the cost of using the technique, and decide if the benefits exceed the cost.

Not every problem needs a design pattern. In fact, most problems don't. Often the simplest, most straightforward solution is the right one. As a rule of thumb, if your solution needs a diagram to explain it, you've gone too far.

Where Patterns are Actually Useful

The most honest value of patterns: giving a short name to a big idea. In a team, it's easier to say "that's a facade" than to explain every time why we're hiding three classes behind one wrapper.

That's it. That's the real use case.

Patterns aren't for teaching you to write good code. They're for talking about code that's already written. So you can ask "what's this class?" and hear "oh, that's part of the mediator". Not for frantically comparing your code to UML diagrams going "which pattern do I apply here?!"

A developer who understands the underlying concepts — separation of concerns, encapsulation, composition over inheritance — will write clean code naturally, even if they've never heard the word "Singleton". The patterns are just labels for what good developers already know how to do.

I've worked at several of the biggest tech companies. Nobody uses these terms day to day, and I've never once been asked about them in an interview (it would be a red flag for me).

The Gosling Philosophy vs The Guido Philosophy

There's a great bit from DHH that nails why Java ended up this way.

James Gosling, the designer of Java, had a dark view of programmers. His premise: the average developer is going to shoot themselves in the foot if you give them too much power. So Java was built as a sandbox — keep it rigid, keep it safe, don't let them hurt themselves. Great for a mid-tier insurance company writing code that has to last 20 years. Not so great for expressiveness.

Guido van Rossum went the opposite direction with Python. His premise: code is read more than it's written, so optimize for clarity and give programmers real tools. First-class functions, decorators, context managers, duck typing — Python gives you the building blocks to solve problems directly instead of routing everything through class hierarchies and interface ceremonies.

Design patterns are a Gosling-world solution. They exist because the language doesn't trust you to solve the problem directly. In a Guido-world language, you just... solve it.

Design patterns are relics of a time when languages weren't expressive enough. The fact that half of the GoF patterns disappear in Python, Ruby, or Scala tells you everything — they were never about design. They were about the language getting out of your way.