About this page
On this page I try to compile concepts from the Software Engineering field that have caught my eye for one reason or other. What little content there is is still rather unorganized.
Note: The Book References page is slightly related.
- 2-tier solution
- Classical client/server architecture: Processing happens on the client and connection between client/server is used for data exchange.
- 3-tier solution (aka n-tier, multi tier)
- Tiers are: Client, application server, database. Takes the processing away from the clients, leaving them with only data presentation.
- Dependency Injection
- Inversion of Control
- Thin client
- The client role in a 3-tier solution where the client only presents data but does not do any processing itself.
Architecture / Design
Inversion of Control
Inversion of Control (often abbreviated as IoC) describes a very broad concept where
- A generic reusable piece of code has flow control over a generic process, and
- Delegates the particulars of that process to custom-written code
I hesitate to call IoC a "design pattern" because the concept is so generic. IoC is commonly used in frameworks. Typical design patterns that make use of IoC are:
- Template Method
I came across Dependency Injection in this informIT article, which is an interview with the GoF in honor of the 15 year anniversary of their "Design Patterns" book. They suggest Dependency Injection as a new pattern that could be included in a revised/refactored version of their book.
- Martin Fowler's seminal article which coined the term
- The Wikipedia article has a useful explanation and example of the pattern/concept.
- Google search
Dependency Injection (often abbreviated as DI) describes a set of design patterns that make use of Inversion of Control (IoC) in a very specific way. Because IoC is a very broad concept that describes a large variety of cases, the use of the term does not carry a lot of meaning. Saying that a design uses IoC provides only a very general description of how the software using that design works. After discussions with many IoC advocates, Martin Fowler therefore coined the term "Dependency Injection", with the goal to describe a subset of IoC designs that make use of IoC in a very specific way. The seminal article is the one listed first in the references section above.
When DI is used, one object A that performs a certain task in a general way is "injected" with another object B that performs one or more parts of that task in a more specific way. It can be said that object A depends on object B, because object A cannot perform its task without object B. The basic intent of DI is to decouple an object (object A) from
- The creation of its dependencies (object B), and
- How those dependencies (object B) are added to it
There are several classic types of DI:
- Constructor injection: Object B is injected into object A via constructor of class A. The wiring between the two objects is usually fixed and cannot be changed later on.
- Setter injection: Object B is injected into object A via a setter function. The wiring between the two objects remains flexible and can potentially be changed later on.
- Interface injection: An
Injectioninterface is defined that contains an injection method that will inject object B. Class A then implements the interface, with the injection method performing the actual injection. The injection method basically replaces the setter and the constructor from the previous two examples. At runtime, object B is injected into object A via the injection method. Fowler in his article also presents the necessity of an
Injectorinterface that contains an injector method, and a third party class C that implements the
Injectorinterface by actually calling the injection method. I must admit that I have not yet grasped the full meaning of this design.
This design pattern uses a central
Registry called "Service Locator" which – somehow – knows how to get hold of all sorts of service objects upon request. There are a few ways how a Service Locator can locate the service objects it needs to provide:
- Already instantiated service objects can be registered with the Service Locator
- A different approach is to register merely the type of a conrete service implementation with the Service Locator. Then, when someone requires that service object, the Service Locator dynamically creates an instance of the previously registered type.
- This can be expanded even further so that a Service Locator reads a configuration file that describes the available services and their types. The Service Locator then creates service objects via reflection.
A Service Locator can be implemented so that it automatically resolves the dependencies of a requested service. For instance, service class A depends on service class B, which must be injected into service class A via its constructor. When service object A is requested, the Service Locator uses reflection to examine the constructor of the registered type A, noticing that a service object B is required. The Service Locator then automatically creates the required service object B and passes it to the constructor of service class A.
Service Locator may be a Singleton, but this is not necessarily so. For instance, it may be desirable to have per-thread service locators.
Service Locator vs. Dependency Injection
Service Locator is not a DI, or even an IoC pattern, because the dependent class A actively gets the service B it depends on from the Service Locator. Nevertheless, Service Locator breaks up hard-wired dependencies because it allows a third party to define who/what provides a required service. Service Locator thus provides the same decoupling mechanism that DI also provides.
The difference is that pure DI requires an overarching authority that performs the actual DI. This is suitable for some sort of container architecture, where at runtime the container acts as the overarching authority that performs the actual DI.
For the ultimate flexibility, it is possible to combine Service Locator with DI by injecting dependent class A with the Service Locator object. Although the dependent class A still actively gets the service B it depends on, it no longer has to know where to obtain the Service Locator from. I cannot imagine yet where this solution with full-blown flexibility is useful, but I'm quite sure that it also has its use in a container environment.
Nothing here yet.