Plans and Guidelines for Evolving the Mifos Architecture

This page discusses a proposed approach for evolving the current code base. Three interrelated goals are discussed here:

  1. making Mifos more modular
  2. making Mifos cleanly layered
  3. defining APIs in each module for internal use in Mifos as communication points between modules and to expose as integration points for external applications or plugins.

Some of the ideas here were tested out in the "Cheetah" version of Mifos, which was done as an exploration of what we would like the structure of Mifos to ultimately look like.

Groundwork

The following steps were requirements for proceeding with the work proposed here. Each of these has now been completed:

Application Module Decoupling

At the maven module level, Mifos is currently divided into the following modules:

The acceptanceTests module encapsulates all our SeleniumRC based acceptance tests and makes use of some more generic functionality provided by the testFramework module.

The serviceInterfaces and userInterface modules were included to mirror the structure that was used for the "Cheetah" (proof of concept) version of Mifos.

The common module includes generic support used in both tests and the Mifos application code.

Finally, the application module contains almost all of the code in Mifos. To make it faster and easier to develop Mifos, we want to split the application module into multiple modules where each module contains code that deals with a well encapsulated functional area of Mifos. Interactions between modules would be support by making calls into the API of a module.

The current structure of Mifos divides the application at the package level inside the "application" module as follows:

If we modularized Mifos along the lines of functional areas, then we could imagine a package structure (with corresponding modules per top level package) that looked something like this:

With a structure like this, we could could strive to each module self contained by having all interaction with the module be through an API defined for the module. In this way, each module would operate only on the business objects defined within that module and would then use a service level API (and associated data transfer objects or DTOs) to interact with other modules.

Some goals of moving to this kind of modularization are:

Incrementally increasing modularity

A big question about increasing modularity is "How do we make Mifos more modular in an incremental way?"

One approach would be to start rearranging package structure by moving functionality out of the "application" module to match our target package (and module) structure, and begin introducing APIs for the top level packages. Work could to eliminate dependencies on business objects from other high level packages could be done incrementally until reaching the point that all "foreign" business object references have been removed and either replaced by API calls to another module or redesigned away. At this point the now independent package could be made into a maven module that would build a jar file.

Here's a sketch of what an initial step towards modularization might look like by pulling out high level packages for accounts, customers, reports and userInterface. The idea is to reorganize the package structure first, to match what we expect the module structure to eventually be. As part of this process, we can reorganize packages so that under org.mifos we will have packages split by functional area of the application. Much of the code currently under the "framework" package is actually specific to a given area of the application, so it could be rolled up under the application package and then have subpackages distributed to the functional area where they belong. Eventually these intial high level packages will be broken down further once enough of the tight coupling within them has been removed.

Right now each of the packages under org.mifos.application also include user interface classes. The plan here is to pull these classes out into a separate org.mifos.userInterface package. These should be separated from the business logic and use an API (or service facade) to call down into the domain (business) code. Before the UI classes can be separated out, the presentation logic needs to be decoupled from the business logic and business objects.

Improving the Layering of the Mifos Architecture

Currently the presentation layer of Mifos (Struts action classes) has business logic mixed in and directly references business objects (and in some cases persistence code).

There are also persistence operations that are mixed into some business objects. We would like persistence (and transactional) operations to be cleanly separated from business objects in order for business objects to be true POJOs (plain old java objects).

In order to move to a more maintainable code base and to facilitate breaking Mifos into modules, we would like to move to a cleanly layered architecture.

In order to do this we want to:

Once the presentation layer has been cleanly separated from the business logic and objects, then we can take steps like:

Making all business object into POJOs will mean that code can be more easily unit tested in memory.

Defining APIs for Mifos

APIs play a key role in moving Mifos to a loosely coupled, easier to understand, maintain and extend architecture. They will be used:

One proposal is to add an API package below each highest level module package. This API package would contain all the API methods and DTO classes for moving data in and out of the API calls. The eventual structure would then look like:

For any given module, a developer would know where to look for the external API to that module.

We need to compile a set of guidelines as to what rules we would like our external APIs to follow. Here is an initial list:

Specific Mifos Layering, Modularization and API Projects