The following text can be seen as a concept documentation. It explains foundational decisions, as well as design and architecture patterns used by the framework. It helps in understanding the ideas behind the framework and how it is supposed to work.
1.1) Domain Driven Design
One of the largest problems in software projects is not technology, but language and semantics. One might think it is easy to build great products with great tools, but this will ultimately fail when requirements are misunderstood or the code is unmaintainable over the long term. Just because it does not reflect the problem domain well enough for which it is purposed. Domain Driven Design (DDD) tackles this problem by providing best practices for understanding the domain and utilizing that knowledge throughout the whole development process. It gives guidelines about how to make communication easier by defining an ubiquitious language. This ubiquitous language is used by all team members, including domain experts and engineers, to prevent miscommunication that originates from different vocabulary being used. Engineers represent the domain knowledge in a domain model. This can be done by creating documentation with the Unified Modeling Language (UML) using class diagrams, activity diagrams and such, then translating it to code following the DDD principles either manually or using Model Driven Architecture (MDA) and Model Driven Software Development (MDSD). Alternatively you can simply do this in your mind without any modeling or code generation tools, skipping the intermediate step and translating the model directly into code. In any case the idea here is to use the ubiquitous language and domain model consistently for communication, documentation and code.
One of the problems of the DDD introductory literature is that it focuses a lot on the business layer (which they call domain layer) and thus more on the backend side of application development. No criticism here, since their patterns there are great and the idea of using a distinction between value objects, entities, repositories and services (among a few more) helps structuring that side of applications a lot. But DDD can be applied to the presentation layer as well with great benefits. When researching in that direction, one easily stumbles upon the next pattern this framework is based on, the ...
1.2) Naked Objects Pattern
The Naked Objects Pattern is building on the premise, that a good domain model is suitable to be externalized as a user interface. And vice versa that the requirement of externalizing it, results in a better domain model. How this externalization of a domain model looks like in practice is demonstrated by the following example:
Domain Model Gets Converted to User Interface
Here you see that:
- each class is represented individually as an area in the UI
- getters and setters result in input fields
- a list of contracts associated with the customer results in a table being displayed
- action methods result in buttons
- each element in the UI can be identified via a bean path in the model (e.g. 'name', 'contract.status' or 'address.street' relative to the customer class)
For this to work, you will notice that the domain model not only contains the state (properties), but also the logic about how to manipulate it (actions). The model thus becomes intelligent and the Naked Objects Pattern uses that intelligence to make it available as an user interface (UI). To understand this better, please see the next graphic for a comparison of applications based on the Model View Controller (MVC) Pattern and applications based on the Naked Objects Pattern:
MVC vs Naked Objects in a Layered Architecture
Adaption of an image made by Daniel S. Haischt which was originally publicized on Wikipedia, licensed under CC BY-SA 3.0
With this it becomes apparent what the Naked Objects Pattern is aiming for. By being able to match the views to the models, you can completely remove the controller layer and automate it using binding conventions to the intelligent models. The application thus becomes simpler to understand and easier to maintain, since you are forced not to allow the clutter between the view and model to appear in the first place. In MVC, the controller layer is normally implemented to handle differences in the layers, but the Naked Objects Pattern makes this obsolete.
1.3) RAD & CRUD vs Naked Objects
The Naked Objects Pattern goes even further conceptually and says it can completely generate the view for you based on those binding conventions. In practice this idea is often manifested in Rapid Application Development (RAD) and Create Read Update Delete (CRUD) frameworks. When they also promise to provide data driven user interfaces, you will mostly see fancy looking web pages with lots of tables that display database entities with common data manipulation facilities you are used from CRUD. Those frameworks sure are nice for CRUD applications, but fail miserably for more complex and customized user interfaces. As soon as you try to deviate from their chosen conventions and try to extend their views or even modify them, these frameworks will in the worst case make it so hard for you, that you are forced to writing your view from scratch in those special cases. RAD and rapid prototyping is nice and this framework is also usable in this direction, but a good framework should give you the freedom to extend and modify the generated views as easily as possible. The idea to provide this freedom in this framework is by embracing Wicket instead of hiding its existence, thus still making easily accessible everything you can do with Wicket. Since Wicket is a MVC framework, applying the Naked Objects Pattern on it is easy and has to just focus on automating parts of the Controller and View for you while still allowing you to use your own code as a replacement for the defaults where needed.
1.4) Document View Architecture
One more problem with many CRUD frameworks is that they usually bind to entities from the persistence layer and are thus interwoven with the data management. When you want to use entities for the UI you might have to extend them with UI specific annotations and methods for e.g.:
- ordering of fields
- internationalizing strings
- providing choices for combo boxes
- retrieving data from tables or saving data to tables
- converting the data into a different form to be displayed
- opening modal dialogs or displaying status messages
This for example has the following drawbacks:
- you cannot reuse your existing (maybe legacy) entities for new views, since they might not match in structure
- you might need to call repositories or services from your entity while your architecture suggests keeping them stupid, for data holding purposes only
- you might accidentally mix the DDD concepts of service, repository and entity and put everything in your entities
- you cannot reuse the entities easily in other modules since they are bound to your UI framework
- refactorings in your UI might lead to refactorings in your database and vice versa
- it is not easy to write reusable Wicket pages, panels and components when they are bound to a specific persistence layer framework
- some entity hierarchies might be so complex that they have to be split among multiple views/tabs/wizards, each having different requirements on the model and needs to hide things
- you may want different perspectives on the same data but the entity class does not match all perspectives properly
Here the Document View Architecture comes in handy. Instead of putting everything into your entities and using them as your models for the UI, you implement documents that match directly to the desired views you want. The documents handle data retrieval and manipulation using services and repositories and provide adjusted data from the entities where needed or just delegate to those directly where appropriate. The documents can even reuse entity classes completely where possible and extend them from the outside by providing additions and overrides for the nested properties and actions. Applying the Document View Architecture enables this framework to give you the freedom of choosing your own frameworks for the business and persistence layer. This makes it a lightweight web framework instead of a complete development platform.