[#modules]
= Modules

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:

Enabling and ensuring modularity is a xref:concepts-patterns.adoc#modular[key principle] for the Apache Isis framework.
Modularity is the only way to ensure that a complex application domain does not over time degenerate into the infamous "big ball of mud", software that is difficult, dangerous and expensive to change.

Modules chunk up the overall application into smaller pieces, usually a pacakge and subpackages.
The smaller pieces can be either tiers (presentation / domain / persistence) or functional architectural layers (eg customer vs orders vs products vs invoice etc).
Because Apache Isis takes care of the presentation and persistence tiers, modules for us focuses just on the important bit: considering how the functionality within the domain model should be broken up into modules, and determining the dependencies between those modules.

== Rules of Thumb

The two main rule of thumbs for dependencies are:

. there should be no cyclic dependencies (the module dependencies should form an acyclic graph), and
. unstable modules should depend upon stable modules, rather than the other way around.

By "unstable" we don't mean buggy, rather this relates to its likelihood to change its structure or behaviour over time: in other words its stability as a core set of concepts upon which other stuff can depend.
Reference data (calendars, tax rates, lookups etc) are generally stable, as are "golden" concept such as counterparties / legal entities or financial accounts.
Transactional concepts such as invoices or agreements is perhaps more likely to change.
But this stuff is domain specific.

== Decoupling

Having broken up a domain into multiple modules, there is still a need for higher level modules to use lower level modules, and the application must still appear as a coherent whole to the end-user.

The key features that Apache Isis provides to support this are:

* dependency injection of services
+
Both xref:refguide:applib-svc:about.adoc[framework-defined] domain services and application-defined services (eg repositories and factories) are injected everywhere, using the `@javax.inject.Inject` annotation (Spring's `@Autowired` can also be used).
+
By "everywhere", we mean not just into domain services, but _also_ injected into domain entities and view models.
This enables us to implement behaviourally complete domain objects (if we so wish).

* xref:overview.adoc#mixins[mixins] that allow functionality defined in one module to appear (in the UI) to be provided by some other module.
+
For example, a _Document_ module might allow `Document` objects to be attached to any arbitrary domain object (such as `Order` or `Customer`) in other modules.
A mixin would allow the UI for a `Customer` to also display these attached ``Document``s, even though the _Customer_ module would have no knowledge of/dependency on the _Workflow_ module.
(More on this example xref:overview.adoc#inverting-dependencies[below]).
+
Dependencies are also injected into mixins.
A common technique is to factor out from domain objects into mixins and then generalise.

* the internal xref:refguide:applib:index/services/eventbus/EventBusService.adoc[event bus] allows modules to influence other modules.
+
A subscriber in one module can subscribe to events emitted by domain objects in another module.
These events can affect both the UI (eg hiding or disabling xref:overview.adoc#object-members[object members], or allowing or vetoing interactions).

A good example of this last is supporting (what in an RDBMS we would call) referential integrity.
Suppose the `customers` module has a `Customer` object and a `EmailAddress` object, with a customer having a collection of email addresses.
A `communications` module might then use those email addresses to create ``EmailCommunication``s.

If the `customers` module wants to delete an `EmailAddress` then the `communications` module will probably want to veto this because they are "in use" by those ``EmailCommunication``s.
Or, it might conceivably perform a cascade delete of all associated communications.
Either way, the `communications` module receives an internal event representing the intention to delete the `EmailAddress`.
It can then act accordingly, either vetoing the interaction or performing the cascade delete.
The `customers` module for its part does not know anything about this other module.


[#inverting-dependencies]
== Inverting Dependencies

If we get the dependencies wrong (that is, our initial guess on stability is proven incorrect over time) then there are a couple of techniques we can use:

* use the link:https://en.wikipedia.org/wiki/Dependency_inversion_principle[dependency inversion principle] to introduce an abstraction representing the dependency.

* move functionality, eg by factoring it out into xref:overview.adoc#mixins[mixins] into the other module or into a third module which depends on the other modules that had a bidirectional relationship

Mixins in particular allow dependencies to be inverted, so that the dependencies between modules can be kept acyclic and under control.

For example, suppose that we send out ``Invoice``s to ``Customer``s.
We want the invoices to know about customers, but not vice versa.
We could surface the set of invoices for a customer using a `Customer_invoices` mixin:

[plantuml]
.`invoices` module contributes to `customers`
----
include::docs:resources:partial$plantuml-stereotypes.puml[]

package invoice {
    class Customer_invoices <<mixin>>
    class Invoice <<mi>>
}
Customer_invoices --> "0.*" Invoice: invoices

package customers {
    class Customer <<ppt>>
}
Customer_invoices -.r-> Customer: "contributes to"
----

In the UI, when rendering a `Customer`, we would also be presented with the associated set of ``Invoice``s.

We can also use mixins for dependencies that are in the other direction.
For example, suppose we have a mechanism to attach ``Document``s to arbitrary domain objects.
The documents module does not depend on any other modules, but provides a `DocumentHolder` marker interface.
We can therefore attach documents to a `Customer` by having `Customer` implement this marker interface:

[plantuml]
.`customers` depends upon contributions of `documents`
----
include::docs:resources:partial$plantuml-stereotypes.puml[]

package documents {
    interface DocumentHolder <<role>>
    class DocumentHolder_documents <<mixin>>
    class DocumentHolder_attachDocument <<mixin>>
    class Document <<ppt>>
}
DocumentHolder_documents -d-> "0..*" Document: documents
DocumentHolder_documents -.l-> DocumentHolder: "contributes to"
DocumentHolder_attachDocument -.l-> DocumentHolder: "contributes to"

package customers {
    class Customer <<ppt>>
}
Customer -u.-^ DocumentHolder
----

== Defining Modules

In the context of Java applications, modularity is a rather overloaded term.
We have Maven modules, Java 9 modules and we also have Spring link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html[@Configuration]s, which define a set of domain services.

In the context of Apache Isis, a module is actually the last of these, a Spring module.

The xref:docs:starters:simpleapp.adoc[simpleapp starter app] provide some structure and illustrates the idioms.
To summarise:

* by convention, we have one `@Configuration` module per Maven module.
+
This is at the root package of the maven module.

* all of the domain classes (domain objects and services) are part of that Maven module.
+
All are annotated or meta-annotated with Spring's link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Component.html[@Component] annotation, and Spring's link:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html[@ComponentScan] is used to discover these from the classpath.

* Spring's link:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html[@Import] is used to express a dependency between each "configuration" module.

By convention, we have just one Spring module to each Maven module.
This means that the dependencies between Maven modules (using `<dependency>` are mirrored in the Spring module's `@Import` statements).
We can therefore rely on Maven to ensure there are no cyclic dependencies: the application simply won't compile if we introduce a cycle.

[TIP]
====
Details on how to actually define modules can be found xref:userguide:fun:modules.adoc[here].
====

If the above convention is too officious,then you could choose to have multiple Spring modules per Maven module, but you will need to watch out for cycles.

In such cases (proprietary) tools such as link:https://structure101.com/[Structure 101] can be used to help detect and visualize such cycles.
Or, (open source) libraries such as link:https://www.archunit.org/[ArchUnit] or https://jqassistant.org/[jQAssistant] can help enforce architectural layering to prevent the issue arising in the first place.
(These tools can enforce other conventions, too, so are well worth exploring).



