Layers
Layers divide the code into understandable units of which each could preferably be looked at and understood well without the need to see a lower layer.
Another great benefit of layers is that they compartmentalize changes giving the developer the ability to see that a change can only affect the current layer and the ones using it.
Architectural patterns
Beneath the layers reside architectural patterns, which offer a way of communicating design at a larger scale. My designs usually involve by default a domain model, an MVC and a data mapper, usually even with small programs.
I might use these patterns loosely on a small project, for example, by just putting the data mapping logic to consistently named methods in the same class as the domain model but I find even this little separation quite useful. After the class grows in size it is a lot easier to refactor the data mapping logic to another class or a group of classes if the data logic resides in just a couple of aptly named methods (given that these methods contain no domain logic). With larger systems, of course, the separation is usually made by a more powerful way of separation e.g. creating packages of classes or functions.
Domain logic
Some architectural patterns such as MVC help to separate the domain logic from data persistance and other plumbing. Modeling the domain in the developed software requires using the same language in the code as in conversations with the domain experts and the users of software. If the separation is done well the domain experts can often look at the code and have some ideas about what is happening and may even find defects by themselves.
With small projects and projects with heavy climbing and little domain logic it is often better to omit the domain layer.
Design Patterns
Design patterns are at a level lower than architectural patterns, and design patterns also are an excellent way of communicating complex ideas in few words. I have encountered and implemented myself several designs using design patterns with great success but I'm also aware of the risk involved in using them too much or using them in situations where they are not needed.
For example, I have seen an observer pattern, with the observer and the subject having a broker between them, used in a messaging subsystem which always used the same concrete observer. The subsystem was probably being future proofed from changes with needlessly complex design as a result.
APIs
If we descend one more level down, we reach the API of a class, which I would consider very important even though it resides at quite a low level compared to the aforementioned items. API design is quite often neglected or at least given less time than the actual implementation. I consider an API the most crucial element of a code level module since there's a chance that it can't be changed radically in the future and it can easily consume tremendous amounts of time from the users of the API.
Even though an API wouldn't be published it's still worth it to design it well.
Good books I've read about software design
Layers divide the code into understandable units of which each could preferably be looked at and understood well without the need to see a lower layer.
Another great benefit of layers is that they compartmentalize changes giving the developer the ability to see that a change can only affect the current layer and the ones using it.
Architectural patterns
Beneath the layers reside architectural patterns, which offer a way of communicating design at a larger scale. My designs usually involve by default a domain model, an MVC and a data mapper, usually even with small programs.
I might use these patterns loosely on a small project, for example, by just putting the data mapping logic to consistently named methods in the same class as the domain model but I find even this little separation quite useful. After the class grows in size it is a lot easier to refactor the data mapping logic to another class or a group of classes if the data logic resides in just a couple of aptly named methods (given that these methods contain no domain logic). With larger systems, of course, the separation is usually made by a more powerful way of separation e.g. creating packages of classes or functions.
Domain logic
Some architectural patterns such as MVC help to separate the domain logic from data persistance and other plumbing. Modeling the domain in the developed software requires using the same language in the code as in conversations with the domain experts and the users of software. If the separation is done well the domain experts can often look at the code and have some ideas about what is happening and may even find defects by themselves.
With small projects and projects with heavy climbing and little domain logic it is often better to omit the domain layer.
Design Patterns
Design patterns are at a level lower than architectural patterns, and design patterns also are an excellent way of communicating complex ideas in few words. I have encountered and implemented myself several designs using design patterns with great success but I'm also aware of the risk involved in using them too much or using them in situations where they are not needed.
For example, I have seen an observer pattern, with the observer and the subject having a broker between them, used in a messaging subsystem which always used the same concrete observer. The subsystem was probably being future proofed from changes with needlessly complex design as a result.
APIs
If we descend one more level down, we reach the API of a class, which I would consider very important even though it resides at quite a low level compared to the aforementioned items. API design is quite often neglected or at least given less time than the actual implementation. I consider an API the most crucial element of a code level module since there's a chance that it can't be changed radically in the future and it can easily consume tremendous amounts of time from the users of the API.
Even though an API wouldn't be published it's still worth it to design it well.
Good books I've read about software design