High Level Architecture¶
The architecture of the Domain Services components is that of an Onion Architecture - also described by Robert C. Martin (Uncle Bob) as Clean Architecture. The outer layer components all consume the domain model and services - either by providing concrete implementations of abstractions (interfaces or abstract classes) or as a direct consumer of functionality. Thus, the direction of coupling is always toward the center of the onion – the domain layer.
The Domain layer comprises the domain model and services. Examples of services are
JobService. The domain layer is the core of the Domain Services ecosystem. The Domain layer has no dependencies on any other components
The outer layers are also part of the Domain Services ecosystem, but they act as infrastructure layers who have a dependency to the domain layer, but also are allowed to reference various third party frameworks and libraries such as Polymer to implement Web Components, Nancy to implement Web APIs or DHIs own MIKE SDK or DIMS.CORE API to implement providers.
The Web API layer exposes the domain services as an http-based REST API for support of distributed applications – primarily browser and mobile apps.
The Providers are concrete implementations of the abstractions defined in the domain layer – e.g. concrete implementations of an
The Workflow Activities are small blocks of functionality that can be combined to form workflows. Examples of workflow activities are
Below, the individual layers are described in more details.
The domain layer contains a number of domain-specific services. Most services are related to data retrieval and storage, but some are related to other services such as execution of jobs (e.g. workflows). Examples of service are
The domain layer also contains various "stand-alone" functions for analysing domain entities such as time series, GIS feature geometry, radar images etc. Examples of such analysis tools are time series tools such as resample and gap-filling or GIS tools such as re-projection or various spatial analysis tools (distance, contains, intersects etc.).
Furthermore, the domain layer contains a number of helper classes such as a
ServiceLocator and a
ConnectionService for managing configuration data such as repository connection strings.
Finally, the domain layer contains all interface definitions and abstract base classes. These abstractions also serve as extensibility points of the domain layer functionality. The extensibility points come in the form of provider interfaces like
The domain layer is implemented as a collection of POCO (Plain Old CLR Objects) libraries with no hard-wired dependencies to other components or frameworks than .NET itself. This is a characteristic of using the Dependency Inversion Principle and dependency injection (DI).
The domain layer is made as a DI-friendly library – perfectly suited for use with any DI framework. It is up to the consumers (e.g. applications) to make the decision about possible DI Frameworks to be used for composing the object graph of the application. In for example the Web API (which is a consumer of the domain layer) the decision has been made to use Pure DI – i.e. no particular DI framework (e.g. Unity) is used. However, another consumer can make its own decision about a DI framework strategy.
Providers are components with concrete implementations of the abstractions of dependencies defined in the domain layer. These concrete implementations are also known as plugins. A provider is technology-specific, meaning that it has a dependency on one-and-only-one specific technology - e.g. PostgreSQL. In other words, a provider is a collection of technology-specific plugins.
Abstractions are typically represented by interfaces and/or abstract base classes. An example of such an interface is the
ITimeSeriesRepository interface. This interface represents a dependency of the
TimeSeriesService type. A
TimeSeriesService instance needs to know the concrete time series repository to use when handling incoming requests. The below diagram shows an example of the full stack dependency graph for a fictitious "Time Series Visualizer".
The provider layer contains various technology-specific implementations of the
ITimeSeriesRepository interface. Each of these implementations can potentially utilise native libraries of the underlying technology – e.g. the MIKE WORKBENCH Platform modules, the DIMS.CORE API or the MIKE SDK. This is the Repository Pattern.
The Web API components exposes the domain services through an http-based web API. The Web API components supports distributed applications across platforms such as Windows, Web iOS and Android. The Web API components are very lean. Rather than containing heavy business logic, the Web API components provide a standard way (a protocol) for how the domain services are accessed and exposed over http on the Internet (WWW).
The Web API components act as a kind of "bridge" between an http endpoint and the business functionality encapsulated in the stateless services in the domain libraries.
The architecture of the Web API components are RESTful.
Typically, the Web Components will draw on functionality defined in the domain layer (exposed via the Web API components). Examples of such components are the
dhi-leaflet-images-wms used to display maps with data overlays retrieved from the
MapService (using the WMS standard) or the
dhi-timeseries-editor for visualization of time series data retrieved from the
A complete reference to the Polymer Web Components can be found here.
Workflow activities are small blocks of functionality that can be combined to form workflow sequences. The workflow activities (and the workflows) are implemented using Windows Workflow Foundation (WF), which is a framework within the .NET framework. Examples of workflow activities are
Workflow activities are often based on functionality the domain layer or native libraries. This ensures lean workflow activities that merely are wrappings of already existing functionality.
Workflows are executed through the
JobService using for example the WF provider implementation of the
IRemoteWorker interface. More details about job/workflow execution can be found here.