by andrei
19. September 2008 20:01
You can read about the purpose of this list and how to use it here.
Also, the list of resources is here.
- general implementation
E1
E2
B3 - concepts
- the observer pattern
used when an object of a lower level needs to communicate upward (beyond answering a direct query) - structure
the namespace pattern that will be used is always SmartCA.<Layer Name> . There will be cases where an extra project may be required even though it still belongs in one of the four layers. Usually, this happens in the Infrastructure layer, where you may be implementing some functionality that needs to be separated from the rest of the Infrastructure project. In that particular case, the naming standard that I will follow is SmartCA. < Layer Name > . < Some other functionality name > . An example is a project with a name and namespace combination of SmartCA.Infrastructure.Caching . These types of projects can be added later if and when they are needed.
resources
B3 - smart UI Antipattern
Put all the business logic into the user interface. Chop the application into small functions and implement them as separate user interfaces, embedding the business rules into them.
resources
B1
B3 - service
each layer offers its own services: for example, the application and domain layers call on the SERVICES provided by the infrastructure layer
A Service class has no internal state and can simply act as an interface implementation that provides
operations. This concept is very similar to web services. Services typically coordinate the work of one or
more domain objects, and present the coordination as a well - known operation. It is also important to
note that some services may live in the application layer, some may live in the domain layer, and others
may live in the infrastructure layer.
resources
B1
B3 - Separated Interface pattern
the interface is defined in a separate assembly from its implementation
resources
B3 - Presentation layer
Responsible for showing information to the user and interpreting the user's commands. The external actor might sometimes be another computer system rather than a human user.
resources
B1
B2
B3
code & implementation
E2 - forms classes
code & implementation
E2 - browser classes
code & implementation
E2 - Presentation Model
In the simplest case, your Domain Model is already "presentable" and you could just data bind directly to the Domain Model objects. However, the interface of an application frequently demands that information is presented in a more "user friendly" form than it was in the Domain Model.
The Presentation Model objects are a part of the PL and should have a structure and behavior matching the requirements of the PL (in effect, matching the needs of the UI). In our example, the PM Person class would have a FullName property rather than FirstName and LastName properties found in the Domain Model Person class.
as soon as the PM is there as well as the supporting infrastructure for Wrapping or Mapping to the Domain Model I usually find plenty of opportunity for refining the presentational aspects of the PM, and soon enough the two models will begin to become more and more different, making it easier and easier to motivate complementing the Domain Model with a PM
resources
B4 - state
When making the choice between Mapping and Wrapping, special attention should be paid to the difference in how state is handled in the two approaches.
When wrapping your Domain Model objects, only one instance of the data is used by the application. If you have two views showing the same employee at the same time, and you update the employee's name in one view, the single instance of the data in the wrapped object is updated. If the second view is then refreshed, it should display the updated data, because it is also mapping directly to the same wrapped, updated object.
When mapping your PM objects to your Domain Model objects, however, you could potentially have several different sets of PM objects representing the same Domain Model object, but with different state in them.
resources
B4 - return only PM objects
Another issue is that you have to remember to return PM objects from PM reference properties. For example, when I read the AssignedToProject property of a PM Employee object, I want a PM Project object back, not a DM Project object. Consider a naïve implementation of a Wrapper object with a reference property as shown in the following
resources
B4 - relationships
When we take relationships between the objects into account, the task becomes more difficult again. Object graphs (a group of objects that are all interconnected via relationships) are potentially very large, and if asking the O/O Mapper to fill a PM Employee object from a DM Employee object also results in the filling up of a few hundred related objects, we may have effectively killed performance in our application.
resources
B4 - flattened PM
This approach is often very useful, especially because many UI controls are designed for showing tables of rows, and flattened objects adapt well to this paradigm. But whenever you are interested in representing navigable, deep structures rather than just grids of stuff, the flattened approach falls short. However, you may often find yourself complementing a fully partitioned PM with some flat objects specifically written for some grid in your application.
"Flattened" PM objects provide a good example of how the PM often looks very different from the Domain Model and, of course, the more different they are, the more motivated we are to have two separate models instead of just adding the features needed by the PL to the Domain Model.
resources
B4 - reference values
One way of "solving" these issues with reference properties is to simply avoid reference properties in your PM objects, using "flattened" objects instead that expose only primitive properties, quite possibly from referenced objects as well.
resources
B4 - Identity Mapping in the PM
In the end, we might want a full-blown solution that could handle Identity Mapping in the PM as well, making sure that there are never two different PM instances representing the very same Domain Model instance around in a session.
resources
B4 - Inheritance
This may make it tempting to just go ahead and let the Presentation Model objects inherit from the Domain Model objects instead, overriding whatever properties that need transformation, but leaving all others as they are. The problem with this is that then you are stuck with the public API of the Domain Model, because all public members of a superclass are inherited by the subclass.
In our example, we could have let the PM Employee inherit from the Domain Model Employee, and we could have added the FullName property to the PM Employee, but the PM Employee would also have exposed the FirstName and LastName properties from the Domain Model Employee, because these public properties would be inherited.
resources
B4 - mapping vs wrapping
In some situations, you'll find that wrapping best suits your needs, while mapping works better in other situations. Sometimes you'll use both in the same application, perhaps using wrapping as the default approach but using mapping just for wizards or other "batch jobs" that should be possible to discard without committing.
The choice between wrapping and mapping is influenced by a number of factors, including how state is managed and the opportunities for reducing the amount of boilerplate code in your applications via code generation (wrapping) or via using an O/O Mapping framework (mapping).
resources
B4 - Mapping
The alternative to wrapping your DM objects with your PM objects is to actually copy the data back and forth between the DM objects and the PM objects.
As with the wrapping example, the code for copying the data could be placed in the constructor of the PM object, in which case the constructor would accept the DM object in a parameter
resources
B4 - O/O Mapper framework
resources
B4
- Wrapping
Wrapping is often the easier solution, requiring no additional framework for state management in the PM. The idea here is that you pass the DM Employee object to the constructor method of the PM Employee object. The PM Employee then keeps an internal reference to the DM object and delegates all calls to the DM properties.
Wrapping your Domain Model objects rather than inheriting from them gives a higher level of encapsulation that is usually well worth the extra, admittedly tedious, work of delegating between PM and Domain Model properties.
resources
B4
- onion architecture
- layered architecture
factor out responsibilities into separate cohesive units (clusters of classes) and define the dependencies between those units
each layer specializes in a particular aspect of a computer program
resources
B1
B2
B3
code & implementation
E1
E2 - Infrastructure layer
Provides generic technical capabilities that support the higher layers: message sending for the application, persistence for the domain, drawing widgets for the UI, and so on. The infrastructure layer may also support the pattern of interactions between the four layers through an architectural framework.
Some technical components are designed to directly support the basic functions of other layers (such as providing an abstract base class for all domain objects) and provide the mechanisms for them to relate (such as implementations of MVC and the like).
Any type of framework, data access code, calls to web service calls, and so forth will live in this layer. For example, the Repository Framework implementation
instead of all calls going down, the Infrastructure layer might "know" about the Domain layer and might create instances there when reconstituting from persistence
resources
B1
B2
B3
B4
E14
code & implementation
E2 - factory
factories can be useful in any layer
code & implementation
E1
E2 - Domain layer
Responsible for representing concepts of the business, information about the business situation, and business rules. State that reflects the business situation is controlled and used here, even though the technical details of storing it are delegated to the infrastructure.
the Domain Model should be oblivious of the infrastructure
resources
B1
B2
B3
B4
code & implementation
E1
E2 - Decoupling layers, separation of concerns
Creating programs that can handle very complex tasks calls for separation of concerns, allowing concentration on different parts of the design in isolation
resources
B1
B2 - Decoupling from the database
- command pattern
code & implementation
E2 - Application layer
Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.
approach the application layer as an application programming interface (API), or almost
a façade, to the domain model.
providing some coordination, but it's very thin, only delegating to the Domain layer
Service Layer pattern
isn't mandatory; it is only there if it really adds value
resources
B1
B2
B3
B4
code & implementation
E2
You can find the entire list of techniques in progress in the Development base concepts category. Please feel free to leave any comments or suggestions which could make these lists more useful for everyone.
Also, if you are interested in learning these skills you can try the Developer training modules.
Enjoy programming!
I am putting together a set of concept lists for the main programming techniques, which should help developers learning or using them to be more efficient. Here are the techniques in progress:
Please feel free to leave any comments or suggestions which could make these lists more useful for everyone.
Also, if you are interested in learning these techniques you can try the developer training modules.
Again, please feel free to leave any comments or suggestions which could make the training modules more useful for everyone. We are having great results with them at Akcedo (so they really work), but they can always be improved. Also, if you would like to use the modules or are already using them and you want to discuss about the process feel free to comment and ask questions here.