Inversion Of Control/Dependency Injection
- Modules should have a focused purpuse, decoupled from other objects
- Code to interfaces, not objects
- Properties that represent the interfaces are filled at runtime
- Replacing modeuls has no effect on other modules
- Object coupling occurs at runtime
- Don’t call us, we’ll call you
- Register handlers for an event, so the object firing events doesn’t have to know about what will be done after that event
- Don’t instantiate objects within a constructor, or elsewhere. Pass objects to the constructor, or use some kind of object factory.
Principle of Least Knowledge
- One class should know as much as it needs to know and no more
- Rather than pass an object with a property the constructor needs, pass the property itself
Avoid Global State
- If an object requires another object, don’t rely on the object being configured elsewhere
Use exceptions to deal with resource failures (memory, disk, network, …)
- Handle these exceptions in the approriate layer, converting to the higher level.
- SqlException becomes DatabaseUnavailableException becomse ProductInfoUnavailable
Avoid long message sequences, ‘Don’t talk to strangers’, Law of Demeter
- Only do things with parameters of the method, or members of the object
- dont do: ObjectA.GetObjectB().GetAnotherObject().DoSomething()
- This couples object A with the distant object.
Test Driven Development
- Write tests and then only write code if the test fails
Composition Over Inheritance
- It is easy to change objects by their associations, harder to change the base class, change the contract
- For example, don’t subclass AuthenticatedServlet, even if it is always authenticated, rather create a new servlet class that has a Credentials object
Avoid Complicated switch or if blocks
- Consider refactoring polymorphically, base classes are easier to test, easier to add new code paths
Object Design:
- Think about responsibilities more than attributes
- Clearly state the responsibilities before assigning it – Who should be responsible for _____?
- Mimic the real world as much as possible (low representational gap). If a cashier creates a sale, then the cashier object should create the sale object
- Design for a separation of major system concerns
- GRASP : General Responsibility Assignment Software Patterms
Creator - Class B should create A if
- b contains A
- B records A
- B closely uses A
- B has the data needed to initialize A
Expert Assign a responsibility to the class that has the information needed to fulfill it Low Coupling Assign responsibilities to keep coupling low, use this as a determining factor when considering alternatives Controller Represents the overall system, a root object, or a single use case carried through. This object doesn’t do much work itself, rather it delegates the work to appropriate domain objects, and tracks the progress, the state of the use case. High Cohesion Each object is relatively specialized, all of the methods are focused along one dimension. Single Responsibility Principle. Classes have a small number of highly related methods Polymorphism Rather than if/else logic to perform operations based on the type of an object, subclass the object and implement the branches in the class they apply to. Pure Fabrication Assign a highly cohesive set of responsibilities to a convenience class, one that does not represent a real world concept, when there is no design that allows a real world concept to suffice without hampering the design (coupling, cohesion, etc). These should be very reusable, very clean and focused. Indirection Create an object that sits in between a domain object interaction, to insulate each from changes in the other. An adapter object, an intermediate object. Protected Variations Identify points of potential instability, and design (functional) interfaces around them. Insulate the general program from volatility in specific modules. Most design patterns and programming best practices derive from this goal.
Model-View separation
- Do not couple non-ui objects with UI objects
- UI windows don’t “do” anything, they just take input and make requests of the application layer, which does things (presumably with the domain layer), and returns UI update instructions (error or confirmation)
- So an operation begins with the UI, but isn’t carried out until the domain class
Command-Query separation
- Every method should either perform an action, or retrieve a value (with no side effects)
Layer systems
- Prevent the aspects of the system from being tightly coupeled
- Extract business logic from user interface
- Encapsulate all technology specific stuff in one place so that’s the only place that changes when the tech does
- Allow developers to work on different aspects without overlapping
- Allow code to be reused
- Potential layers, each probably depends on the one below it, but the lower layer has no knowledge of the higher, so the UI accesses the application layer, but the application layer never accesses the UI
- UI
- GUI screens, reports, user interactions
- Application
- Workflow, session state, screen transitions
- Domain
- Business rules
- Services to do things
- Business Infrastructure
- low level business services, used in multiple applications (currency converter, zip code lookup_, etc
- Technical services
- Persistance, security,
- usually uses frameworks
- Foundation
- data structures, network IO, databases
Domain Modeling:
- Don’t try to create a complete, correct domain model, rather let it grow with the project
- Use existing terms wherever possible, everyoneone should use the same language, if there are ambiguous concepts, define them
- If you don’t think of X as a number or text, it is probably a conceptual class, not an attribute
- Add a descrition class when there needs to be a description of the item that exists independt of examples of that item (like in a catalog)
- Show associations between objects that need to be remembered
- name relationships Object 1 Verb phrase Object 2
- Sale Paid-by CashPayment (not sale Uses)
- Add an arrow if it is useful to show which object is on the let of the above sentence – which way to read the relationship
- Include attributes that you need to remember
- Sale needs a datetime,
- use ‘-’ for private attributes
- use ‘/’ for calculated attributed
- Create data type classes when
- it is an abstraction of a coding scheme (UPC)
- It is a quantity with a unit (money, weight)
- if has seperate sections that may need to be accessed independently
- It has attributes