Design Patterns – How Do OOP Practices Change in Dynamic and Weakly-Typed Languages?

design-patternsdynamic-typingobject-orientedsolidweak-typing

There is a fairly helpful question already along these lines ("Non-OOP Design Patterns?"), but I am more curious about a transitional point of view for someone just getting started with dynamic and weakly-typed languages.

That is: let's say I've been programming in C++, C#, or Java for many years, and absorbed lots of wisdom along the lines of the GoF design patterns, Fowler's Patterns of Enterprise Application Architecture, SOLID principles, etc. Now I'm dabbling in Ruby, Python, JavaScript, etc., and wondering how my knowledge applies. Presumably I could do direct translations in many cases, but almost certainly that wouldn't be taking full advantage of my new setting. Duck typing alone turns a lot of my interface-based thinking on its head.

What stays the same? What changes? Are there guiding principles like SOLID, or canonical patterns (perhaps entirely new ones) that a dynamic language newbie should know?

Best Answer

What stays the same? What changes?

The patterns are the same. The language techniques change.

Are there guiding principles like SOLID,

Yes. Indeed, they remain the guiding principles. Nothing changes.

or canonical patterns (perhaps entirely new ones) that a dynamic language newbie should know?

Some things are unique. Mostly the impact is that the implementation techniques change.

A pattern is -- well -- a pattern. Not a law. Not a subroutine. Not a macro. It's just a good idea that gets repeated because it's a good idea.

Good ideas don't go out of style or change dramatically.

Other notes. Python is not "weakly typed". It's more strongly-typed than Java or C++ because there's no cast operation. [Yes, there is a way to fudge the class associated with an object, but it's not the kind of thing that's done except to prove a fussy, legalistic point.]

Also. Most design patterns are based on different ways to exploit polymorphism.

Look at State or Command or Memento as examples. They have class hierarchies to create a polymorphic states, commands or mementos of state changes. Nothing changes significantly when you do this in Python. Minor changes include the relaxation of the precise class hierarchy because polymorphism in Python depends on common methods not common ancestors.

Also, some patterns are simply an attempt to achieve late binding. Most Factory-related patterns are an attempt to allow easy change to a class hierarchy without recompiling every C++ module in the application. This isn't as interesting optimization in a dynamic language. However, a Factory as a way to conceal implementation details still has huge value.

Some patterns are an attempt to drive the compiler and linker. Singleton, for example, exists to create confusing globals but at least encapsulate them. Python singleton classes aren't a pleasant prospect. But Python modules already are singletons, so many of us just use a module and avoid trying to mess with a Singleton class.

Related Topic