views:

2100

answers:

18

I have general academic knowledge of the various design patterns that are discussed in GoF and Head First Design Patterns, but I have a difficult time applying them to the code that I am writing. A goal for me this year is to be able to recognize design patterns that are emerging from the code that I write.

Obviously this comes with experience (I have about 2 years in the field), but my question is how can I jumpstart my ability to recognize design patterns as I am coding, maybe a suggestion as to what patterns are easiest to start applying in client-server applications (in my case mainly c# webforms with ms sql db's, but this could definitely be language agnostic).

+16  A: 

It doesn't work that way round, with experience you forget about patterns (or you pre-date "patterns") and just write code based on experience and common sense.

Patterns help you take a design and create a framework of code that solves that design. If you writing good clean code what need do you have of recognising patterns.

The real trick is getting that feeling that your code stinks (a technical term) and then there is need to back-off and analyse if there is a pattern that can help the code stop stinking.

AnthonyWJones
ah i see, so paying attention and recognizing code smells and then taking a step back and reflect on how to refactor them (with patterns or not) would be the suggestion?
Jon Erickson
Yeah--from what I've seen of it patterns are simply formalized ways of talking about what we already know.
Loren Pechtel
Be that as it may, if you think of what you do as a craft, then like any other craft, it is important to know the formalized names of the patterns we are using. In that sense, it is critical to a craftsman to raise to the surface the things he/she is doing instinctively. What you are saying doesn't work for professionals in any other field
jlembke
@jlembke: It is true that their having names does make it easier to communicate to others what I'm doing and it does help resolve the age old question "What do I call this class?". I guess that's perhaps what you mean by "surface the thing", if so then yes I would agree. Although I wouldn't agree that in "crafts" it critically important to know the formalized names of things. For example there are skilled musicians out there who can't read sheet music.
AnthonyWJones
But there are no architects of any worth who do not know how to read blueprints, or know what a rafter, a truss, or a vestibule is. If our approach to development is like the untrained musician, talented thought he may be, the craft is in trouble. In professions like Architecture, it's those patterns, consciously addressed, that allow thinking beyond just straight lines and angles, or "good clean code" in our case, and allows us to communicate designs and abstract our thinking. It's easier to think about and work with a "truss" than it is "this thing that has certain angles I use for support"
jlembke
A: 

I think a deep understanding of the problems they solve and the strength's/weaknesses they bring along will let you fit them in your problem domain more easily.

Ido
+2  A: 

I'm still new at this myself... I try to keep design patterns fresh in my mind by reviewing them often. This combined with whiteboarding has really helped me. I have a hard time looking at the code and seeing patterns emerge but as I whiteboard, use system metaphors, and other more visual/creative representations, they pop out.

And yes, I think experience is key -- this has been getting easier for me over the last 6 years of programming.

Andrew Flanagan
+2  A: 

I asked a similar (but not duplicate) question a while back.

The best way to jumpstart your pattern recognition (hehe) is to understand the patterns well enough to spot them in the wild. You should reach a point where you are drawing on your knowledge of the patterns when writing code rather than identifying patterns that emerged in your own code.

Remember that the point of design patterns is to use a technique that's been done before and described in a specific way, such as implementing "undo" in a text editor.

I would start with the Singleton (though it is overused), the Factory, and the Command patterns. These are the ones I've seen the most "in the wild."

Robert S.
+4  A: 

It is definitely experience.

Try reading the book Design Patterns Explained by Alan Shalloway it's a story of how he came to understand, recognise and apply patterns - it really helped me out in understanding them, even though it's written in a slightly conversational style and he uses an outdated metaphor throughout the book. Definitely recommended.

Some patterns are very obvious, if you've got lots of different objects doing a new MyObject in lots of places - maybe you need a factory pattern.

If you've got configuration information that's being used a lot you may need a singleton.

Reading the spec can help you, look for familiar sentences and see if they match up with the pattern catalogue's descriptions.

Rob Stevenson-Leggett
+5  A: 

In general, if you start seeing redundancies and a lot of boiler plate code in your source tree, it usually means some sort of pattern may be useful there.

Or lets say you have a complicated form that has many components that listen to many other components. Assume you can't simplify that dependency tree, and you will probably be forced to use the observer pattern just so you can sanely debug the thing.

I wouldn't worry too much about adhering to patterns from the start, but if you see a issue in your source tree (something inelegant, or something not easily extendable) then search out for patterns or maybe even other APIs and Frameworks to help you along.

APIs and Frameworks usually enforce good patterns and solve your source tree headaches at the same time, so you may actually do better keeping on the cutting edge platform enhancements than just trying to adhere to very abstract and formal design patterns.

+2  A: 

Exercises. Practice writing (multiple) short programs that specifically use the different patterns. Then practice combining multiple patterns in one program. The more you familiarise yourself with them, the more they'll stick in your head. Also, don't just code and hope patterns come out of it; think about the problem, and how you can represent that using patterns. If no patterns spring to mind, and you can't find something similar, or some algorithm, or some paper, THEN go with just bashing out some code to solve it.

Lee B
+5  A: 

Probably the best way to recognize them is to really study them in detail, understand their inter workings and understand WHY they're useful in the scenarios which they are implemented. Look at as many examples of them as you can and find examples that make sense to you. Really, only time and experience will give you the best sense of where design patterns fit into software development so if you're not getting it right of the bat don't worry...eventually it will hit you with that "AH-ha!" moment.

Read books, blogs, and articles from Uncle Bob, Fowler, and other OO leaders as well to continue your learning experience.

Oh yeah, and the Singleton and MVC patterns were the easiest for to understand at first, followed by the Factory pattern which these days seems to be a very widely used pattern so it may be a good candidate to learn first.

matt_dev
+2  A: 

recognize design patterns that are emerging from the code that I write.

First, you need to recognize that Design Patterns are a design-time activity and not a code-time activity. There may be a very rare number of developers who successfully incorporate Design Patterns on the fly, but most everyone else needs to plan on using them correctly. Very seldom do they just fall out from the code and not seem like contrived uses of a design pattern. Don't count on refactoring to save you. If the overall architecture is bad, refactoring isn't going to help.

The simplest way to learn to use Design Patterns "for me" was to learn enough design patterns to be able to recognize when one exists for any particular situation. Then it is just a matter of looking up the how to use the pattern and applying it to the specifics of your situation. There is no need to memorize how each pattern works. Remembering what problem each pattern is trying to solve is far more useful. It's not rocket science, but does require an ability to take a number of very specific goals and generalize them into common goals.

Dunk
A: 

I think reading the book is a very good start. First try to learn the patterns that is the definition of the pattern. Next identify the scenarios each pattern help. Next read other people's code or from some open source project's code where these patterns are applied and try spotting the pattern and understand how it helped in the particular case. Then practice by using the patterns in practice problems.

TheVillageIdiot
+36  A: 

There are some decent answers here, but I find most of them lacking something. Some have said "its just experience," which isn't very helpful and I don't agree with.

There are some suggestions about doing exercises and small programs, which will help you remember the patterns, but seems like rote memorization, which isn't as useful as really understanding design patterns. Its easy to understand patterns in isolation, but harder to apply them within an old, crufty program.

The patterns I've seen mentioned so far are Singleton and Factory, which are probably two of the more harmful and misleading design patterns.

Anyways, my answer, from my personal experience:

Test Driven Design: This almost forces to you use new patterns out of necessity. The object collaboration and composition patterns it forces you to use can really shift your understanding and view of some patterns. Patterns like Visitor, Strategy, Adapter, and Bridge become a lot more clear.

New Projects: With new projects, you can use any patterns in any way you choose. A new project lets you analyze your problem space and figure out what patterns might be appropriate and why. This heavily relies on your creativity and ability to think about future uses and reuses of your project.

Existing Projects: Old projects will naturally need some redesign, and if you poke around, you'll be able to see where patterns can be used. These usually require surgical operations, but thats a fun challenge. You need to avoid the urge maintain the status quo, to keep doing things "how they've always been done." Part of the problem you may run into is that you can't use a pattern because it will break everything. In that case, you're most likely a) using the wrong pattern or b) not limiting the scope of the pattern enough. When you find how a pattern can easily slip into existing code, then you're beginning to really understand the pattern.

Code Duplication: Any time you see the same function or routine used more than a couple times in similar contexts is probably a place some sort of pattern could have been used. If you have an old project with a lot of glue javascript, you'll see lots of copy-paste duplication you can probably abstract out. This is also a classic "code smell" that others have mentioned.

Your own laziness: Part of the purpose of design patterns to to provide flexibility. This flexibility pays off in the long run when you have an odd request. You may end up writing a fair amount of code to glue the pieces together, but thats better than having to set up global flags and pass magic values to identify the use case. I'd like to clarify that I mean laziness in the sense of ultimate laziness. It may be easier to hack something together, but you still have to test, release, and maintain it, which is a helluva lot more work than writing it.

An example: While writing a data import script, I would log information to a file because thats what the final version needed to do. This required me to re-tail the file every invocation. How frustrating. Wouldn't it be nice if I could log to the console during dev with the flip of a switch, without having to put hacks in the code? Enter the Facade pattern and Strategy patterns.

Using What You Don't Know: By this I mean, if you don't know the requirements fully, you're forced to abstract it out so that you can easily adapt to a change in them. "Requirements" doesn't just mean a crappy spec your client handed you, it also means your own uncertainties as you write your code. If you find yourself blocking on an issue, abstract it out and stub it. Now, suddenly, you can stub it out with any behavior, be it for testing, development, or lucid requirements.

Experience: Others have said this as a generality, so I'd like to clarify. I think experience - real wisdom and knowledge - means understanding whats going on "behind the scenes." That is to say, what the goals are rather than the symptoms of the problem. Experience is the intuitive equivalent of the critical thinking I mention below.

Creativity and Critical Thinking: This is the only one you need really, but its not very helpful to say "think better" :). I've found a lot of developers are too pragmatic - "we'll just solve this specific case and be done with it." Iterate that a few times and you end up with the maintenance nightmares we all complain about. So, solve the generalized, "n - 1" case. That doesn't mean you need to look on from the heavens and try to write "100% clean, pure" code in an attempt to solve every imaginable situation, but that you should step back once and try and design for that. This ties into above.

Anyways, I'll give some examples, I hope these are helpful.

Its easy to use the Singleton patterns - "I have one datastore, and I want to make access to it easy" - but thats shortsighted. How do you isolate and easily test pieces that depend on the datastore? What if there are multiple datastores, one for reading, one for writing, one for searching, and one for historical data? Think about your ease of development, qa, and release process. What happens when you need to selectively disable or change the behavior of a component?

Another example is users: its easy to have a Singleton $user object which represents the currently logged in user. What happens when you need to sudo as another user, or do operations within the context of another user, such as timezone conversion or dealing with preferences?

Say you have some sort workflow you walk through as users update objects. A new requirement needs to make external service calls and users must update the object correctly. If something goes wrong, then you have to go back to before this workflow. Other updates may occur during this workflow. Conceptually, this is similar to the Command pattern, perhaps with a bit of Strategy mixed in, but its not so apparent because those definitions don't include "workflow" or "concurrent updates," and can become further muddled if the architecture isn't friendly to "undo"

Richard Levasseur
Great answer, Richard. Thankyou!
Garth T Kidd
Really useful! Voted up!
Erik Töyrä
A: 

Along with all the great advice here I cannot more highly recommend Refactoring to patterns by Joshua Kerievsky which provides real world examples of when and why you would, but more importantly, wouldn't use a particular software design pattern.

Bedwyr Humphreys
A: 

Most design patterns are extremely obvious. I think most good programmers I know independently created and used every one of the common patterns long before there were any books published on the matter.

So for experienced programmers, the patterns books are more often used as a way to assign a common language to things we all know.

For those just beginning, the patterns books can be used to pre-fill your programming toolbox. Just reading through them and understanding what they are and why they exist means that when you encounter that situation in code you might recognize it and know a good, ready-made solution.

Don't worry about it if you miss them though since you've read and deeply understood the pattern, you'll probably come up with the exact same thing even if you don't realize where you learned it.

Bill K
A: 

Maybe you should think what design pattern you would use for the problem. This isn't the case every time, but sometimes it is.

Tuoski
+1  A: 

You need to studing all the Code Smells and be able to detect them in your code http://en.wikipedia.org/wiki/Code_smell

and if you find them try to start appling the design patterns there ...... is very easy to detect some of them for example a lot of "if" im your code means you can encapsulate those options in objects and trigger the creation of the object with whatever you are comparing....

+1  A: 

I think that the only way to become more experienced with Design Patterns is to start using them, as you can do this right now.

You can't succeed without a failure. At the beginning your code actually may become worse, or you can spend more time on it without significant benefits in quality. It just like when you start using test-driven development, at the beginning your productivity will be lower then before TDD.

But with time your experienced will grow and productivity too. Quality will enhance.

Fedyashev Nikita
+3  A: 

Although I think Design Patterns are key tools in your arsenal, it occurs to me that they are secondary to Design Principles as expressed in SOLID (and elsewhere). In my experience, knowing and applying SOLID principles and a family of other principles and practices around them, will often steer you to a pattern organically.

Things to think about to help appropriate patterns emerge:

  1. Design to Interfaces, not concretions
  2. Composition over inheritence
  3. Separate use from construction
  4. Keep state private
  5. Program by intention
  6. Encapsulate Construction
  7. Testability
  8. High Cohesion/Low Coupling
  9. Assert, don't ask
  10. SOLID and other principles, especially Dependency Inversion, Open-Closed, and Single Responsibility

If you are thinking in terms of principles first many times patterns like Strategy and Bridge will come out organically.

jlembke
A: 
  • Practice GoF book
  • Create hypothetical problems related to your job, or similar problems defined in the book
  • Try to solve them with design patterns
  • Measure your work with metrics, before and after cases

And also read other recommended books in stackoverflow about design patterns and anti-patterns: AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis

baris_a