-
Notifications
You must be signed in to change notification settings - Fork 9
guide coding conventions
This guide describe the conventions for naming and structure in a devon4quarkus application. In addition to the points mentioned here, the code should follow the general Java conventions (see Oracle Naming Conventions, Google Java Style, etc.).
-
Using CamelCase even for abbreviations. devon4j naming conventions clearly discourage to use CAPITALCASE for abbreviation (
XmlUtil
instead ofXMLUtil
,Dao
instead ofDAO
) -
Eto
vs.Dto
and dropping theEto
andCto
concept -
*RestService
vs.*RestController
. According to devon4j we should use*RestService
that has already been established -
Spring-data vs.
Dao
- see https://github.com/devonfw-forge/devonfw-microservices/issues/37 -
Structure of
logic
layer? - see https://github.com/devonfw-forge/devonfw-microservices/issues/38 -
Bean-Mapping - see https://github.com/devonfw-forge/devonfw-microservices/issues/8
-
Lombok usage - see https://github.com/devonfw-forge/devonfw-microservices/issues/29
For a devon4quarkus-based application, we recommend using the following Java package scheme:
«root».«component».«layer»[.«detail»]*
See also existing devon4j packaging that we want to simplify and modernize here.
Segment | Description | Example |
---|---|---|
|
The root package. Typically we suggest to use |
|
|
Matches your maven |
|
|
Matches your maven |
|
|
Only used if the service serves multiple business components. Most microservices usually address a single business component/domain. In this case it is ommited(its already implied by the artifactid) |
|
|
The name of the technical layer (See technical architecture) which is one of the predefined layers ( |
|
|
You will technically have the freedom of choice to define your sub-packages. Compared to |
|
|
Further division based on common stereotypes based on type of component. Suggested stereotypes for |
|
For a typical backend microservice that provides HTTP API and data persistence via JPA in the business domain serviceorder
, the structure would be something like this:
«group».«artifact» ├──.domain | ├──.dao | | ├──ServiceOrderDAO | | └──ServiceOrderItemDAO | ├──.model | | ├──ServiceOrderEntity | | └──ServiceOrderItemEntity ├──.logic | ├──NewServiceOrderValidator | └──ServiceOrderEventsEmitter └──.rest ├──.controller | └──ServiceOrderRestController ├──.mapper | └──ServiceOrderMapper └──.model ├──NewServiceOrderDTO ├──ServiceOrderPageResutltDTO └──ServiceOrderDTO
When using JPA/Hibernate for data persistence, please use the following subpackages under your domain package:
-
dao
: For the Data Access Objects (DAOs). The naming should be always«entity»DAO
-
repo
: For repositories, if you use Spring Data for data access -
model
: For all entities, views or other objects used to read and write to DB.
Use the layer to provide any microservice-specific business logic and add sub-packages as needed, depending on the type and number of classes required.
Before introducing a new service, check whether it is really needed or whether it can be replaced by a standard/framework solution (e.g. validators can be covered by the bean validation specification in 90% of cases by using annotations on models).
Strive for clear naming, based on the scope of the class, instead of generic names. BAD: OrderService
, EmailManagement
, BETTER: OrderValidator
, EmailSender
Depending on the requirements of the project, a service may provide several APIs, e.g. a fixed version, a public API that must remain strictly backward compatible, and a separate non-public API used for internal functions or operations. Often the app needs to provide multiple public API versions.
If this is the case, we suggest to introduce «version»
as an intermediate package:
└──.rest ├──internal | ├──.controller | | ├──AdminOperationsRestController | | └──EventRestController | ├──.mapper | | └──AdminOperationMapper | └──.model | ├──EventDTO | ├──AdminOperationDTO | └──AdminOperationResultDTO ├──v1 | ├──.controller | | └──ServiceOrderRestController | ├──.mapper | | └──ServiceOrderMapper | └──.model | ├──NewServiceOrderDTO | ├──ServiceOrderPageResutltDTO | └──ServiceOrderDTO └──v2 ├──.controller | ├──ServiceOrderItemRestController | └──ServiceOrderRestController ├──.mapper | └──ServiceOrderMapper ├──.filter | └──CustomPayloadFilter └──.model ├──NewServiceOrderDTO ├──ServiceOrderItemDTO ├──ServiceOrderPageResutltDTO ├──ServiceOrderPatchRequestDTO └──ServiceOrderDTO
-
service.[api|impl].[rest|ws]
simply becomesrest
,ws
(in case someone is still using legacy SOAP),grpc
, etc. Technically we can still derive that this all implies theservice
layer. -
dataaccess
becomesdomain
. You are not forced to follow this and architcture validation such as oursonar-devon4j-plugin
will in the future support both. However, new CobiGen templates for quarkus/cloud-native will use this new default and would need to adopt them if you want to change. We also suggest to put entities in themodel
sub-package (see«type»
). -
logic
remainslogic
In addition to the general Java naming conventions, the following rules should be observed
-
Names should be descriptive and concise. Always use short but speaking names (for types, methods, fields, parameters, variables, constants, etc.).
-
Name should indicate the type of object it represents.
-
Strictly avoid special characters in technical names (for files, types, fields, methods, properties, variables, database tables, columns, constraints, etc.). In other words only use Latin alpahnumeric ASCII characters with the common allowed technical separators for the accordign context (e.g. underscore) for technical names (even excluding whitespaces).
-
For package segments and type names prefer singular forms (
CustomerEntity
instead ofCustomersEntity
). Only use plural forms when there is no singular or it is really semantically required (e.g. for a container that contains multiple of such objects). -
Avoid having duplicate type names. The name of a class, interface, enum or annotation should be unique within your project unless this is intentionally desired in a special and reasonable situation.
-
All classes in single «type» package should have the same naming structure (e.g. dont mix
EntityRepo
andOtherEntityDAO
insidedao
package). -
Avoid artificial naming constructs such as prefixes (
I*
) or suffixes (*IF
) for interfaces. -
Avoid property/field names where the second character is upper-case at all (e.g. 'aBc').
-
Names of Generics should be easy to understand. Where suitable follow the common rule
E=Element
,T=Type
,K=Key
,V=Value
but feel free to use longer names for more specific cases such asID
,DTO
orENTITY
. The capitalized naming helps to distinguish a generic type from a regular class.
This documentation is licensed under the Creative Commons License (Attribution-NoDerivatives 4.0 International).