180 likes | 343 Vues
Layers Architecture Pattern. Source: Pattern-Oriented Software Architecture, Vol. 1, Buschmann, et al. Problem. You are designing a system that needs to handle a mix of low-level and high-level issues Low-level: hardware traps, sensor input, file I/O
E N D
Layers Architecture Pattern Source: Pattern-Oriented Software Architecture, Vol. 1, Buschmann, et al
Problem • You are designing a system that needs to handle a mix of low-level and high-level issues • Low-level: hardware traps, sensor input, file I/O • High-level: user interface, application logic • High-level operations rely on lower-level ones • User-visible functionality must be mapped onto the target platform • Several levels of abstraction must be spanned to perform this mapping • The system is large, and a methodical approach to organizing it is needed to keep it understandable
Solution • Structure the system into an appropriate number of layers, and place them on top of each other • Each layer represents a level of abstraction • Classes are placed in layers based on their levels of abstraction • Layer 1 is at the bottom and contains classes closest to the hardware/OS • Layer N is at the top and contains classes that interact directly with the system's clients
Solution • Layer J uses the services of Layer J-1 and provides services to Layer J+1 • Most of Layer J's services are implemented by composing Layer J-1's services in meaningful ways • Layer J raises the level of abstraction by one level
Structure • Layer J's services are used by Layer J+1 • Classes in Layer J may also use each other • There are no other direct dependencies between layers
Dynamic Behavior • Scenario I • The most common case • Request at Layer N travels down through each successive layer, finally reaching Layer 1 • The top-level request results in a tree of requests that travel down through the layers (each request at Layer J is translated into multiple requests to Layer J-1) • Results from below are combined to produce a higher-level result that is passed to the layer above
Dynamic Behavior • Scenario II • Request at Layer N travels down through successive layers until it reaches Layer J, which can satisfy the request without the help of Layer J-1 • Examples • Layer J caches previous results • Layer J pre-fetches or pre-computes results
Dynamic Behavior • Scenario III • Events generated at Layer 1 travel up through successive layers, finally reaching Layer N • Examples • Interrupt generated by device driver • Asynchronous I/O operation completes • Signal received from OS • Event may stop before reaching Layer N if it can be handled by some intermediate layer • Multiple events at Layer J may be combined into a single higher-level event which is sent to Layer J+1
Implementation • Determine the number of layers (i.e., abstraction levels) • Name the layers and assign responsibilities to them • Define the interface for each layer • Error handling strategy • Part of a layer's interface is the set of errors it might return • The errors returned by a layer should match its level of abstraction • Errors received from the layer below should be mapped into higher-level errors that are appropriate for the layer above • Low-level errors should not be allowed to "leak out" and become visible to high-level layers
Relaxed Layers • Layer J can call directly into any layer below it, not just Layer J-1 • Pros • More flexible and efficient than strict layers • Easier to build than strict layers • Cons • Less understandable and maintainable than strict layers
Consequences • Dependencies are organized in an understandable way • Individual layers can be reused, modified, or replaced • Peel off UI layer, replace with different style of UI • Modify data storage layer to use a different database • Lower layers can be reused in an entirely different application • Lower efficiency • Overhead involved in moving between layers
Consequences • Dependencies between layers can cause problems when a layer needs to be modified. • Layers above and below may be affected, and so on…. • Example Layer J class Manager { Worker m_worker; public void setWorker(Worker w) { m_worker=w; } public void manage() { m_worker.work(); } } Layer J – 1 class Worker { public void work() { // ....working } } What if we need to change worker?
Solution: Dependency Inversion Don’t wire the lamp directly in. Make the lamp implement an interface
Solution: Dependency Inversion • Don’t depend on concrete – Depend on Abstractions Layer J interface IWorker { public void work(); } class Manager { IWorker m_worker; public void setWorker(IWorker w) { m_worker=w; } public void manage() { m_worker.work(); } } Layer J – 1 class Worker implements IWorker{ public void work() { // ....working } } class SuperWorker implements IWorker{ public void work() { //.... working much more } }