Someone made an interesting statement: "The earlier you start coding, the more time you take to complete it!"
It is so true and we have all seen it so many times in real life. Coding without spending enough time on understanding the requirements well, without spending enough time on framing the architecture properly and without an appropriate design for each component of the system is a sure formula for failure. Yet, so many project make all the efforts to follow this path and are naturally led to disaster.
The most important part of any architecture or design is to identify and separate out components that are expected to change differently. Identifying these components requires a lot of experience topped up by understanding the domain. This, coupled with an understanding of the current requirements can lead you to a good architecture followed by a good design.
A good code is possible only when we have a good design. But the converse is not always true. A good code is possible only when the developers understand the spirit of the design as well as that of the language. Choosing the right language to implement and abiding by its spirit, makes the code more efficient, readable and maintainable.
One of the most important principles that successful designers follow, is that they do not solve all the problems from first principles. That is impossible! It is very important to use time tested solutions to recurring problems. I learnt this the hard way - and that was when I started learning the basics of design patterns.
Each application is unique in itself. You cannot use the same generic solution everywhere. But, each application is a combination of multiple components - that are present in almost everywhere. The real task of a designer is to identify these components. Once you have identified such components of the main application, you can take up the task of solving them using the generic solutions available from the past. This is easier said than done. Identifying these individual components is not such a trivial task. That is what a good designer needs to master.
The time tested Design Patterns give us a chunk of predefined problem components and their solutions. They provide an important direction to the thought process. It is like travelling on a defined path, rather than finding our own way in a forest. It is true that, there are times when we have to deviate from the beaten path, and it is important that we should be able to do it. Hence, it is important that we retain that courage and stamina for when it is required; by following the time tested path when it is available.
These patterns are independent of the semantics of the language we use. Often we spend so much time on the semantics of a language, that we tend to ignore the spirit of design. The design patterns help bridge this gap. They help us use the language in an appropriate way, so that the solution that we get is sturdy and capable of handling more and more changes.
But, one should be careful. Just because we use a design pattern, it is not necessary that we will get an elegant solution to our problem. If not used correctly, it could even add complexity to the design. Hence it is important to understand each of these patterns and their spirit - so that we can identify and apply them where they should be.