Are design patterns really language weaknesses?

Some canonized design patterns — Adapter, Factory, Command, Visitor, etc — are approximations of features which are baked into other languages. Off the top of my head:

  • Event-handlers in C# are baked-in versions of the observer pattern. Think about how you’d wire up events in C# if you had to roll your own observer each time.

  • Visitor pattern is a verbose approximation of multimethods, message forwarding, or a really weak form of pattern matching.

  • Command pattern wraps up a particular behavior so you can pass the object between methods, which more or less approximates first-class functions.

  • Strategy pattern allows you to dynamically insert a behavior into an object, so that at any time you can modify the object by swapping out one behavior with another. In the functional programming world, we call this function composition.

  • Abstract factory pattern accepts an argument and returns a factory as a result. In general, you can think of factories as basically wrappers around a function (more specifically, wrappers around a constructor). So, you pass arguments to a function and get a function as a result, making this pattern pretty analogous to currying.

  • Decorator pattern allows you to attach or remove behaviors to an object at runtime. In JavaScript, you can add or remove functions without explicitly implementing the decorator pattern thanks to the “prototype” OO model.

So, we have a bunch of design patterns which emulate features intrinsic to other languages. Feature envy doesn’t necessarily indicate a weakness in the language — it’s the boilerplate code that you need to write over and over and over which indicates the language weakness.

Leave a Comment