We all know that the process of creating a design and the whole architecture of the software is very important before writing the code. But how deep should be dive into the design stuff - should we start from the general architecture and go down til the names of the classes or should be just designate common parts and start coding?
First, the following assertion you made isn't true.
We all know the process of creating a design and the whole architecture of the software is very important before writing the code.
Many, and arguably most development shops have come to the realization that doing a lot of design work up front is not beneficial. The problem is that at the start of the project, everyone (stakeholders, developers, etc.) know the LEAST they are ever going to know about what needs to be built (See Cone of Uncertainty). That is not the time to be making major decisions that are written in stone.
My advice is to do the least amount of design you can get away with before you start coding. After you have done a few rounds of prototypes, flesh out the designs with more detail.
Disclaimer: This advice mostly applies to development efforts where the problem is not that well defined up front and still feels very fuzzy. If you know exactly what you need to build and there isn't a lot of uncertainty, bu all means go deeper on your designs. That said, remember above all that your deliverable is working code, not a design document. Do only as much as you need to get the job done.
This is driven by the development life cycle as well as the various project-level and product-level attributes. There's no single right answer that applies to all projects. Some projects tend to create a system architecture up front, and then enter into detailed design for portions of the system, either iteratively or concurrently. Other projects simply progress from architecture and continually refine the design, which is completed and baselined prior to starting implementation. Other projects might not need a formal design or architecture, and decisions and the current state of the project are captured informally.
There are a number of factors that can help you choose a development methodology, ranging from the amount of risk faced by the project, the amount of visibility desired by both management and the customer, the team's familiarity with the domain and technology, the volatility of the requirements, and so on. Steve McConnell's Rapid Development: Taming Wild Software Schedules has an entire chapter on choosing the appropriate methodology.
We all know that the process of creating a design and the whole architecture of the software is very important before writing the code.
This is a false dichotomy.
Code is just detailed design. Nothing more.
The hoped-for distinction between "design design" and "code design" is the presence of executable code.
However, this distinction becomes murky when we have UML-to-code generators. If we create detailed UML, it becomes the code.
If we have a high-level, formal design language -- some kind of DSL that translates high level design or architecture into code -- then that DSL becomes the real code.
For example. C++ used to be translated to C which was translated to an architecture-neutral intermediate form from which "code" was finally generated. That means the C++ could be called a high-level design language. It sure isn't very close to code.
If we use a high-level GUI generator and IDE to drag and drop icons which create code, what is that? Is it design? But it creates code, doesn't it?
I think the distinction between "design" and "code" isn't terribly helpful.
Which leads to the answer to your question.
should we start from the general architecture and go down til the names of the classes or should be just designate common parts and start coding?
It depends on what your audience needs. You write design at one level so that they can take the design to the next level of detail.
Do they need classes?
Or do they only need design patterns into which the fill in the classes?
Or do they need method names?
It depends on your audience.
I'll point you to the Chapter 9 of the book Python Programming: An Introduction to Computer Science by John M. Zelle, Ph.D. were he introduce the top-down design bottom-up implementation strategy and says that the analysis process eventually bring problems small enough to be trivial to solve.
I would say you should apply the same strategy and go deep were is trivial to solve the problem. But, when is trivial? it depends on your capabilities.
In my experience there are two parts to this question.
- How detailed should the architecture be?
- When should a certain level of detail be specified?
Answer to the first part, how detailed should the architecture be...
The architecture should have the least amount of detail that still ensures desired properties are appropriately promoted or inhibited by the system design. Lower level details can be deferred to downstream designers (might be folks writing code, or perhaps another architect user of the system). Remember that as an architect, your main focus is on system properties, the key quality attributes. Depending on the property, you may need to design parts of the system to different levels of detail.
As an example, depending on the size of the system and the properties that you care about, for an architect overseeing a project with many teams, worrying about class names is too low level. On the other hand, class names might be considered high-level design for a team lead responsible for implementing only a piece of the system. (Aside: for small teams that do it all, you'll trade these hats daily.)
Answer to the second part, when should a level of detail be specified is a little more tricky...
One man's architecture is another man's detailed design - it all depends on your perspective of the system and the properties you are responsible for overseeing. The only aspect of design that really needs to happen first is defining the boundaries between elements and layers of abstraction. Once these are clearly defined, different elements can be designed at different levels of detail, generally (there are exceptions) concurrently.
When a level of detail must be specified could depend on a myriad of factors including...
- Priority or value to the customer
- availability (as are the people available to create it)
- risk and uncertainty
- technical dependencies
- and a lot more...
I think most companies these days are adopting Agile software development: http://en.wikipedia.org/wiki/Agile_software_development
The basic idea is that you:
- only plan as much as you can accomplish in a short time period, such as two weeks
- do the bare minimum development necessary to meet the requirements of a specific feature (vertical slice) of the system.
Then at then end of your two week iteration, you consider your accomplishments and plan your next iteration. Some of the benefits of this methodology are:
- you dont waste time planning for things you wont need
- you avoid developing features that needlessly constrain future requirements
- you get quicker feedback about how well your system is meeting the (often changing) requirements of the user
I would like to echo S.Lott's sentiment of "code is design" and JohnFx's advice of "design as little as possible before you start coding", but expound on why. The reason is simple - writing code is a process of discovery.
You can build castles in the air all you want, but there are things you'll only discover once you actually write the code. You'll bump into code duplication that you were simply never going to see when you were making a bunch of UML diagrams because the implementation just isn't there. You might realize a component needs to be broken up into two or more parts when you try to write unit tests for it. Moreover, you're chasing a moving target - even if you had the clairvoyance to think up the perfect design up front, it'll no longer be perfect once the requirements change.
The best advice I can give you is to follow the core idea behind agile methodologies: take a small step towards your goal, take a good look at the result, and use your newly-found insight to fix mistakes and correct your course. Keep doing that until you're done. And don't forget to Keep It Simple, Stupid!