Why Object Oriented Design
Design is a tool for writing code that is easy to change later, as software requirements are constantly changing.
Change is hard because objects need to depend on other objects to collaborate, so it's difficult to ensure that a change in one doesn't cause unexpected changes in other parts of the system.
Design is the art of arranging code so that future unknown changes are as easy as possible to make. Arrangement decisions are based on your understanding of the problem/s, plus an understanding of the benefits and tradeoffs of principles and techniques you can use to solve them.
SOLID, DRY, LoD are examples of design principles. They are based on observations made by experienced developers who noticed that some arrangements of code made their lives easier than others.
Design patterns are solutions to common programming problems that can be used to make your designs more flexible, modular, resuable and understandable (if you know how to apply/adapt them appropriately).
Design fails when a programmer either knows so little about design that they find it difficult to write code that can adapt to change, or when experienced programmers know design teczhniques but don't understand how to apply them, or apply them innappropriately and see patterns where none exist.
You should design when you have some code that you need to arrange so that it will be easy to change. Frequent, small increments.
Good design provides benefits for the lifetime of the application. Bad design makes you miss deadlines or waste time with no payoff.
Procedural languages seperate data from behaviour. The data itself gets sent around and manipulated by anything that interacts with it.
Object-oriented languages combine data and behaviour into a single entity: Objects. An object controls access to it's own data.