1. Learn GoF design patterns. Be amazed by the cleverness.
2. While learning others languages, discover that other approaches remove the need for GoF design patterns at all.
Example: Visitor isn't needed in a language with double dispatch (like Lisp). Chain-of-Responsibility is just foldl. Factory for dependency injection is just a closure or a partial function. And so on.
Yes, that's what I was playing at. Other languages have things similar to design patterns, too.
If you are in luck, a language gives you first class support for abstracting new patterns. (Eg in assembly a procedure is just a pattern and convention, most modern languages help you by providing procedures. Same languages are very good at being extended. Lisp is a good example, and so is Haskell. Even Python is great in that respect compared to, say, Pascal.)
I am still trying to figure out what dependency injection really is. It's seems like only the Java guys have a need for it, but they rave about it.
If you have a function which invokes a different object (or more commonly, a different network service), you pass that as a parameter instead of making a call inside the function.
It makes replacing service with fake_service_object easier, thus simplifying the test process.
Common use case:
If your service was a remote database, you can replace the database handle with a mock object which pretends to be a DB but is actually a simple object returning hardcoded values.
1. Learn GoF design patterns. Be amazed by the cleverness.
2. While learning others languages, discover that other approaches remove the need for GoF design patterns at all.
Example: Visitor isn't needed in a language with double dispatch (like Lisp). Chain-of-Responsibility is just foldl. Factory for dependency injection is just a closure or a partial function. And so on.