Agreed, some people act as if design patterns are the holy grail and they try to fit in every design pattern they know of. That’s not very practical, as it tends to make your code (much) harder to understand, and since I’m rather dumb and lazy, I like code I can understand easily. However, that’s not the reason Tony has started this topic, so although you seem to agree on the general consensus (“design patterns aren’t silver bullets”), your arguments differ. His argument is: “If design patterns do not provide any reusable code then what is the point of using them?”
Saying that one should not use design patterns because you can not reuse the solution after creating a specific solution to a specific problem is strange, as the context will be different in each situation, thus the solution is different just as well. Yes, you have to create a solution to your problem, you will have to anyway, regardless of whether you call them design patterns or go against the rest of the world. If you still think that design patterns are worthless, even though the resulting code is clean, has just as many lines of code as another solution to the same problem, and has the downsides documented for you, you’re just not good at abstract thinking. Seriously.
Still, you’re better for it. Now, when you run into a problem, you’ll at the very least know of one solution, regardless of the fact that it’s a design pattern or not. You use them, I use them, Tony uses them. I’m just the only one of the three who dares admitting to that.
No, I don’t go through my book of Patterns of Enterprise Application Architecture when I encounter code in which there are a few candidates objects to create, which all adhere the same interface, and the one I want is dependent on, say, a simple string variable. I just factor out the creation into it’s own method and let that method decide. If multiple objects need to create that object based on that simple string variable, I factor out the method into it’s own object.
Guess what? That’s an implementation of the Factory pattern. Did I know that from the start? No, I just refactored in the most DRY and logical solution, and the design pattern was implemented. I could throw my hands in the air and shout: “oh dear, that’s a design pattern I’ve just incorporated into my code, will it be reusable?”, or I could just accept the fact that the rest of the world already knows this solution and calls it a factory.
I’ll document my code and call it a factory too. Not because I felt the urge to implement a factory, but because it’s the best thing to do at that time, in that situation, according to my experience and acquired knowledge of best practices. I wouldn’t have known it’s a factory if I wouldn’t have known design patterns. I would’ve come up with the exact same solution though, eventually, but it’d simply take longer. Knowing what “pre-discovered” solutions to a problem there are, will help in your day to day routine.
It’s about learning, mostly from the ones before you. You can look the other way and try to figure out on your own, or simply just read a catalog of design patterns for a change. The nett result of the latter is that you’ll be wiser from it, the former is that you’re doing a lot of thinking work already done. You shouldn’t stop thinking and implement design patterns blindly, and you should think about the implications they will form, even if the implication is as simple as readability.
No, we’re are not mindless drones that should be listening to everything authors of design patterns have to say, and I actually have critique on some of the patterns I’ve read about. Still, ignoring the patterns is ignoring ideas to solve the problems that you’re facing. I’ll let you decide if that’s a good idea. I, myself, do read about patterns, and I don’t incorporate them until I think to myself: how the hell do I solve this? Oh wait, didn’t I read a piece on a problem that somehow resembles this problem? Ah yes, it was $pattern. Do I like that solution in this particular situation? Great, let’s solve it that way. If I don’t like the solution described, I find another solution.
There are exceptions, too. For example, I use the Model View Controller pattern per default if the application is of a well enough size. I use my own implementation, and my own idea’s about them, because that’s what works for me. The pattern itself has no implementation, so an (or more importantly, my) implementation can not be wrong. It could, however, be inefficient, inflexible, or hard to comprehend. All the moaning about who has the “purest” implementation is non-sense. There is no implementation, so it can never be the purest. It can be the most flexible, the most readable, the fastest or the most loosely coupled implementation, but never the purest. Mileages vary, depending on a lot of external factors.
So, in conclusion, I’d have to say: make sure you know some of the design patterns, or at least the ones most frequently used in your languages, make up your mind about each of them, carefully balance the need to implement them and only do so when called for. You’re simply broadening your scope of solutions, with knowledge of those solutions, including their up- and downsides. Ignoring the solutions others before you have explored and documented, you’re a fool. I believe people should stop whining about design patterns and who’s implementation is purest, because you’ll now know it’s not true anyway. Just use what you need to, in the way that is right for you and don’t use the rest.
Yes. And all those years of experience from N of the greatest minds in OO programming are distilled and described in books about design patterns. Think twice before you say it’s overrated, think three times before you claim they are useless and shouldn’t be used. Knowing design patterns is gaining knowledge of solutions in a very structured manner. You could try and pretend you solve everything yourself, but you’d still have to find out the downsides of your solutions – the hard way. And the ironic part is that if you come up with a really good solution, chances are that it has already been done and documented in a pattern, before you thought of it.
Reusability and flexibility are actually closely related in the world of OO programming. Reusability is achieved by making sure that objects can be reused in a different context and by other objects. Flexibility is achieved by making sure that you can use (or, inject) a different implementation of the same interface. Before you have flexibility, you must first have reusability. It’s that simple, really.