Skip to content

Latest commit

 

History

History
97 lines (70 loc) · 9 KB

File metadata and controls

97 lines (70 loc) · 9 KB

Architecture

This section describes some of the architectural patterns upon which Apache Isis builds.

Hexagonal Architecture

One of the patterns that Evans discusses in his book is that of a layered architecture. In it he describes why the domain model lives in its own layer within the architecture. The other layers of the application (usually presentation, application, and persistence) have their own responsibilities, and are completely separate. Each layer is cohesive and depending only on the layers below. In particular, we have a layer dedicated to the domain model. The code in this layer is unencumbered with the (mostly technical) responsibilities of the other layers and so can evolve to tackle complex domains as well as simple ones.

This is a well-established pattern, almost de-facto; there’s very little debate that these responsibilities should be kept separate from each other. With Apache Isis the responsibility for presentation is a framework concern, the responsibility for the domain logic is implemented by your application code.

A few years ago Alistair Cockburn reworked the traditional layered architecture diagram and came up with the hexagonal architecture (also known as/very similar to the Onion architecture):

hexagonal architecture
Figure 1. The hexagonal architecture emphasizes multiple implementations of the different layers.

What Cockburn emphasizes is that there’s usually more than one way into an application (what he called the user-side' ports) and more than one way out of an application too (the data-side ports). This is very similar to the concept of primary and secondary actors in use cases: a primary actor (often a human user but not always) is active and initiates an interaction, while a secondary actor (almost always an external system) is passive and waits to be interacted with.

Associated with each port can be an adapter (in fact, Cockburn’s alternative name for this architecture is ports and adapters). An adapter is a device (piece of software) that talks in the protocol (or API) of the port. Each port could have several adapters.

Apache Isis maps very nicely onto the hexagonal architecture. Apache Isis' viewers act as user-side adapters and use the Apache Isis metamodel API as a port into the domain objects. For the data side, we are mostly concerned with persisting domain objects to some sort of object store. Here Apache Isis delegates most of the heavy lifting to an ORM (DataNucleus or similar).

Aspect Oriented

Although not a book about object modelling, Evans' "Domain Driven Design" does use object orientation as its primary modelling tool; while naked objects pattern very much comes from an OO background (it even has 'object' in its name).

It’s certainly true that to develop an Apache Isis application you will need reasonably good object oriented modelling skills. But given that all the mainstream languages for developing business systems are object oriented (Java, C#, Ruby), that’s not such a stretch.

However, what you’ll also discover is that in some ways an Apache Isis application is more aspect-oriented than it is object oriented. Given that aspect-orientation — as a programming paradigm at least — hasn’t caught on, that statement probably needs unpacking a little.

AOP Concepts

Aspect-orientation, then, is a different way of decomposing your application, by treating cross-cutting concerns as a first-class citizen. The canonical (also rather boring) example of a cross-cutting concern is that of logging (or tracing) all method calls. An aspect can be written that will weave in some code (a logging statement) at specified points in the code).

This idea sounds rather abstract, but what it really amounts to is the idea of interceptors. When one method calls another the AOP code is called in first. This is actually then one bit of AOP that is quite mainstream; DI containers such as Spring provide aspect orientation in supporting annotations such as @Transactional or @Secured to java beans.

Another aspect (so to speak!) of aspect-oriented programming has found its way into other programming languages, that of a mix-in or trait. In languages such as Scala these mix-ins are specified statically as part of the inheritance hierarchy, whereas with AOP the binding of a trait to some other class/type is done without the class "knowing" that additional behaviour is being mixed-in to it.

Realization within Apache Isis

What does all this have to do with Apache Isis?

Well, a different way to think of the naked objects pattern is that the visualization of a domain object within a UI is a cross-cutting concern. By following certain very standard programming conventions that represent the Apache Isis Programming Model (POJOs plus annotations), the framework is able to build a metamodel and from this can render your domain objects in a standard generic fashion. That’s a rather more interesting cross-cutting concern than boring old logging!

Apache Isis also draws heavily on the AOP concept of interceptors. Whenever an object is rendered in the UI, it is filtered with respect to the user’s permissions. That is, if a user is not authorized to either view or perhaps modify an object, then this is applied transparently by the framework. The SecMan extension provides a rich user/role/permissions subdomain to use out of the box; but you can integrate with a different security mechanism if you have one already.

Another example of interceptors are the Command Log and Auditer modules. The Command Log module captures every user interaction that modifies the state of the system (the "cause" of a change) while the Auditer module captures every change to every object (the "effect" of a change). Again, this is all transparent to the user.

Apache Isis also leverages the Spring framework’s event bus. A domain event is fired whenever an object is interacted with, and this allows any subscribers to influence the operation (or even veto it). This is a key mechanism in ensuring that Apache Isis applications are maintainable, by decoupling logic into separate modules. But fundamentally its relying on this AOP concept of interceptors, with event subscribers in one module potentially influencing or responding to interaction triggered in another.

Finally, Apache Isis also a feature that is akin to AOP traits. A "contributed action" is one that is implemented by a mixin class but that appears to be a behaviour of rendered domain object. Mixins can also contribute read-only properties or collections: effectively the result of running a query that returns a scalar or a vector. In other words, we can dissociate behaviour from data.

That’s not always the right thing to do of course. In Richard Pawson’s description of the naked objects pattern he talks about "behaviourally rich" objects, in other words where the business functionality encapsulates the data. But on the other hand sometimes the behaviour and data structures change at different rates. The single responsibility principle says we should only lump code together that changes at the same rate. Apache Isis' support for contributions (not only contributed actions, but also contributed properties and contributed collections) enables this. And again, to loop back to the topic of this section, it’s an AOP concept that being implemented by the framework.

The nice thing about aspect orientation is that for the most part you can ignore these cross-cutting concerns and - at least initially - just focus on implementing your domain object. Later when your app starts to grow and you start to break it out into smaller modules, you can leverage Apache Isis' AOP support for mixins and interceptors (using the event bus) to ensure that your codebase remains maintainable.