Here are the study notes of my recently attended training "Pattern-Oriented Design". The lecturer is Amir Kolsky.
- Six Do's
- Do the right thing
- Do it right
- Do it efficiently
- Do it safely
- Do it predictably (in estimated time)
- The above three items is about design, which is developer's responsibility.
- Do it sustainably
- Discussion: possible issues in a project
- External dependencies
- The dependencies change.
- Tight schedule
- Scope change
- Requirement change/add
- Quality problems
- Overly complex design
- Conclusion: most are caused by design change
- Discussion: the difference between procedural design and object oriented design
- Procedure consider two concepts: behavior (procedure) and data
- OO consider two concepts: entities and relationship, where each entity contains behavior and status (data).
- Three magic questions to know whether a design is good
- How can I test it?
- The easier the better
- What do I need to know (if change it)?
- The less the better
- What do I need to do?
- The less the better
- Two questions to know whether an interface is good.
- Assertive or Inquisitive?
- Stable or Unstable?
- Most comments are not needed. Here is the six kinds of comments and only the sixth is valuable.
- Not a comment.
- e.g. author, time (version controller need to cover such information instead of comments)
- e.g. repeat the method name
- Comment the legacy code instead of deleting it.
- Explain what the code do. The good method name should explain.
- Explain how the code do. The clear code implementations should explain.
- Only this is valuable as the code cannot show it.
- Three steps to look into a design diagram
- Look for relationship
- Static: inheritance
- Dynamic: interface
- Abstract class: variation
- Stable or unstable
- Three essential skills of a developer
- Programming = Design -> Implementation
- Design = Problem -> Design
- Refactor = Design -> Another Design
- The "Constants.cs" file is a bad thing
- It has poor cohesion.
- Break the second magic question: need to know the whole design of the system if need to change the file.
- Criterions to measure code quality
- Good names. No need to explain code with comments.
- No Redundancy
- Redundancy: A change to one thing would necessitate a similar change to all the redundant ones.
- Strong Cohesion
- "One Responsibility in One Place"
- Intentional Coupling
- The technical nature of the relationship between two entities.
- Good coupling: intentional. Vs. Bad coupling: accidental.
- Encapsulation aims to improve coupling and cohesion
- Hidden things cannot be coupled to.
- Cohesive issues are easier to hide.
- Need a balance between encapsulation and redundancy.
- The locality of responsibility.
- Need a balance between focus and cohesion.
- Context of a design:
Pay 100% work
Pay 100% work
Pay 100% work
Pay 0% work (just need simple refactor if they become required,
as the code is well maintainable)
- There are two separated aspects to design a system. Never mixing the two aspects when doing design.
- How the system runs?
- Design the interface/relationship between objects.
- How to construct the system?
- Factory is responsible for construction.
- Design is about the problem, not the implementation.
- Advice from the Gang of Four
- Design to interfaces
- Favor object delegation over class inheritance
- Consider what should be variable in your design … and "encapsulate the concept that varies"
- The Strategy Pattern
- We need a different behavior (variation) at different times (dynamic) for different clients (reuse) requesting the service.
- GoF Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
- Commonality-Variability Analysis
- Commonality analysis is the search for common elements that helps us understand how family members are the same.
- Those things that are found by commonality analysis can often become the abstract types.
- The Template Method Pattern
- GoF Intent: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
- E.g. Commonality: the steps of several algorithms. Variation: each specific algorithm
- The Bridge Pattern
- GoF Intent: De-couple an abstraction from its implementation so that the two can vary independently.
- The Adapter Pattern
- We need to change the interface of a class that has the right stuff but has the wrong interface.
- GoF Intent: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
- The Façade
- We want to use a subset of the functionality of a complex system, or to simplify its interface, or to improve how it is used, or to provide OO access to a non-OO system.
- GoF Intent: Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.
- The Analysis Matrix
- Motivation: Information overload:
- More information than you need.
- No good way to organize it.
- No way to tell what is important.
- No way to see what the cases are.
- Each column represents a given case, Each row is used to represent the concept that case is an example of. Build the matrix as we go.
- The Abstract Factory
- We need to create families of objects for particular situations. That is, particular clients need particular sets of instantiations.
- GoF Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
- The Singleton Pattern
- GoF Intent: Ensure a class only has one instance, and provide a global point of access to it.
- The Family of Proxy Patterns
- We need to add functionality before or after accessing an object in such a way that the client object doesn't know it is talking to a different object.
- GoF Intent: Provide a surrogate or placeholder for another object to control access to it.
- Different kinds of proxy patterns
- The Protection Proxy Pattern
- The Cache Proxy Pattern
- The Virtual Proxy Pattern
- The Remote Proxy Pattern
- The Decorator Pattern
- GoF Intent: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.
- A common example of decorator pattern is the Streaming IO: FileStream, MemoryStream, CompressionStream…
- Chain of Responsibility
- Have a set of objects that can perform a task but the requester of the task does not want to know which one actually does it.