Crafting Design for Future Changes
Sending a message to an unknown object describes its behavior and suggests an abstraction. To explore different ideas, we need mechanisms like TDD. Teams are vital in defining communication patterns, and TDD is a valuable tool. To improve system cohesion, focus on information filtering when necessary. Objects should describe behavior based on their role, corresponding to an interface. Roles represent groups of behaviors and help model concepts in software.
Making a system DRY is challenging because not all identical code is considered duplication. Remove duplication on the third occurrence. Code propagates within a team, so removing unnecessary code is crucial. Code smells in tests can state logic duplication. The object containing data should also have the corresponding behavior. Avoid defining getters and setters as part of objects. Commands should refrain from querying for information. Interface discovery is a technique for unit testing collaborating objects. This technique allows us to define APIs guided by the consumer rather than the provider.
Testable systems ensure future changes, but having tests doesn’t guarantee a solid design. TDD helps decompose problems into manageable chunks, leading to better designs. A good design aims for simplification and is tied to velocity. A team’s testing speed indicates the quality of their test suite. The Test Pyramid suggests having more unit tests and fewer integration tests for a better design.
Design decisions are made when writing code, regardless of using TDD. Friction with testing is usually a result of poor initial design rather than TDD itself. Address design issues before resorting to extensive stubbing. Efforts in design and architecture ensure code maintainability and help future changes. Good design simplifies and reduces friction when implementing new features or modifications.