6. Introduction

The devonfw provides a solution to building applications which combine best-in-class frameworks and libraries as well as industry proven practices and code conventions. It massively speeds up development, reduces risks and helps you to deliver better results.

This document contains the complete compendium of the devon4j, the Java stack of devonfw. From this link you will also find the latest release or nightly snapshot of this documentation.

6.1. Architecture

There are many different views on what is summarized by the term architecture. First we introduce the key principles and architecture principles of the devonfw. Then we go into details of the the architecture of an application.

6.1.1. Key Principles

For the devonfw we follow these fundamental key principles for all decisions about architecture, design, or choosing standards, libraries, and frameworks:

  • KISS
    Keep it small and simple

  • Open
    Commitment to open standards and solutions (no required dependencies to commercial or vendor-specific standards or solutions)

  • Patterns
    We concentrate on providing patterns, best-practices and examples rather than writing framework code.

  • Solid
    We pick solutions that are established and have been proven to be solid and robust in real-live (business) projects.

6.1.2. Architecture Principles

Additionally we define the following principles that our architecture is based on:

  • Component Oriented Design
    We follow a strictly component oriented design to address the following sub-principles:

    • Separation of Concerns

    • Reusability and avoiding redundant code

    • Information Hiding via component API and its exchangeable implementation treated as secret.

    • Design by Contract for self-contained, descriptive, and stable component APIs.

    • Layering as well as separation of business logic from technical code for better maintenance.

    • Data Sovereignty (and high cohesion with low coupling) says that a component is responsible for its data and changes to this data shall only happen via the component. Otherwise maintenance problems will arise to ensure that data remains consistent. Therefore interfaces of a component that may be used by other components are designed call-by-value and not call-by-reference.

  • Homogeneity
    Solve similar problems in similar ways and establish a uniform code-style.

6.1.3. Application Architecture

For the architecture of an application we distinguish the following views:

  • The Business Architecture describes an application from the business perspective. It divides the application into business components and with full abstraction of technical aspects.

  • The Technical Architecture describes an application from the technical implementation perspective. It divides the application into technical layers and defines which technical products and frameworks are used to support these layers.

  • The Infrastructure Architecture describes an application from the operational infrastructure perspective. It defines the nodes used to run the application including clustering, load-balancing and networking. This view is not explored further in this guide.

Business Architecture

The business architecture divides the application into business components. A business component has a well-defined responsibility that it encapsulates. All aspects related to that responsibility have to be implemented within that business component. Further the business architecture defines the dependencies between the business components. These dependencies need to be free of cycles. A business component exports his functionality via well-defined interfaces as a self-contained API. A business component may use another business component via its API and compliant with the dependencies defined by the business architecture.

As the business domain and logic of an application can be totally different, the devonfw can not define a standardized business architecture. Depending on the business domain it has to be defined from scratch or from a domain reference architecture template. For very small systems it may be suitable to define just a single business component containing all the code.

Technical Architecture

The technical architecture divides the application into technical layers based on the multilayered architecture. A layer is a unit of code with the same category such as service or presentation logic. A layer is therefore often supported by a technical framework. Each business component can therefore be split into component parts for each layer. However, a business component may not have component parts for every layer (e.g. only a presentation part that utilized logic from other components).

An overview of the technical reference architecture of the devonfw is given by figure "Technical Reference Architecture". It defines the following layers visualized as horizontal boxes:

  • client layer for the front-end (GUI).

  • service layer for the services used to expose functionality of the back-end to the client or other consumers.

  • batch layer for exposing functionality in batch-processes (e.g. mass imports).

  • logic layer for the business logic.

  • data-access layer for the data access (esp. persistence).

Also you can see the (business) components as vertical boxes (e.g. A and X) and how they are composed out of component parts each one assigned to one of the technical layers.

Further, there are technical components for cross-cutting aspects grouped by the gray box on the left. Here is a complete list:

Technical architecture
Figure 23. Technical Reference Architecture

We reflect this architecture in our code as described in our coding conventions allowing a traceability of business components, use-cases, layers, etc. into the code and giving developers a sound orientation within the project.

Further, the architecture diagram shows the allowed dependencies illustrated by the dark green connectors. Within a business component a component part can call the next component part on the layer directly below via a dependency on its API (vertical connectors). While this is natural and obvious it is generally forbidden to have dependencies upwards the layers or to skip a layer by a direct dependency on a component part two or more layers below. The general dependencies allowed between business components are defined by the business architecture. In our reference architecture diagram we assume that the business component X is allowed to depend on component A. Therefore a use-case within the logic component part of X is allowed to call a use-case from A via a dependency on the component API. The same applies for dialogs on the client layer. This is illustrated by the horizontal connectors. Please note that persistence entities are part of the API of the data-access component part so only the logic component part of the same business component may depend on them.

The technical architecture has to address non-functional requirements:

  • scalability
    is established by keeping state in the client and making the server state-less (except for login session). Via load-balancers new server nodes can be added to improve performance (horizontal scaling).

  • availability and reliability
    are addressed by clustering with redundant nodes avoiding any single-point-of failure. If one node fails the system is still available. Further the software has to be robust so there are no dead-locks or other bad effects that can make the system unavailable or not reliable.

  • security
    is archived in the devonfw by the right templates and best-practices that avoid vulnerabilities. See security guidelines for further details.

  • performance
    is obtained by choosing the right products and proper configurations. While the actual implementation of the application matters for performance a proper design is important as it is the key to allow performance-optimizations (see e.g. caching).

Technology Stack

The technology stack of the devonfw is illustrated by the following table.

Table 2. Technology Stack of devonfw
Topic Detail Standard Suggested implementation

runtime

language & VM

Java

Oracle JDK

runtime

servlet-container

JEE

tomcat

component management

dependency injection

JSR330 & JSR250

spring

configuration

framework

-

spring-boot

persistence

OR-mapper

JPA

hibernate

batch

framework

JSR352

spring-batch

service

SOAP services

JAX-WS

CXF

service

REST services

JAX-RS

CXF

logging

framework

slf4j

logback

validation

framework

beanvalidation/JSR303

hibernate-validator

security

Authentication & Authorization

JAAS

spring-security

monitoring

framework

JMX

spring

monitoring

HTTP Bridge

HTTP & JSON

jolokia

AOP

framework

dynamic proxies

spring AOP

6.2. Components

Following separation-of-concerns we divide an application into components using our package-conventions and architecture-mapping. As described by the architecture each component is divided into these layers:

Please note that only CRUD oriented components will have all four layers within the same component. Some types of applications may have completely different components for the client.

6.2.1. General Component

Cross-cutting aspects belong to the implicit component general. It contains technical configurations and very general code that is not business specific. Such code shall not have any dependencies to other components and therefore business related code.

6.2.2. Business Component

The business-architecture defines the business components with their allowed dependencies. A small application (microservice) may just have one component and no dependencies making it simple while the same architecture can scale up to large and complex applications (from bigger microservice up to modulith). Tailoring an business domain into applications and applications into components is a tricky task that needs the skills of an experienced architect. Also the tailoring should follow the business and not split by technical reasons or only by size. Size is only an indicator but not a driver of tailoring. Whatever hypes like microservices are telling you, never get mislead in this regard: If your system grows and reaches MAX+1 lines of code, it is not the right motivation to split it into two microservices of ~MAX/2 lines of code - such approaches will waste huge amounts of money and lead to chaos.

6.2.3. App Component

Only in case you need cross-cutting code that aggregates other component you may introduce the component app. It is allowed to depend on all other components but no other component may depend on it. With the modularity and flexibility of spring you typically do not need this. However, when you need to have a class that registers all services or component-facades using direct code dependencies, you can introduce this component.

6.2.4. Component Example

The following class diagram illustrates an example of the business component Staffmanagement:

logic layer component pattern

Here you can see the structure and flow from the service-layer (REST service call) via the logic-layer to the dataaccess-layer (and back).

Last updated 2019-11-13 14:38:09 UTC