AI coding assistant guidelines
General
-
Use the Onion Architecture and follow
com.[domain-module].[api|application|domain]
package structure.
Domain Model
-
Use Java records for the domain model, events, commands, requests and responses, because those are more concise and are serializable by default.
-
Prefer Java
Optional
for nullable values.
Entities
-
Commands can be defined as records inside the entity and they don’t have to have a common interface.
-
Command handlers should be implemented in the entity and not in the domain object. The domain object should have methods for business logic validations but it should not handle commands directly or be concerned with entity effects.
-
Command handlers that make updates without returning any information should return
akka.Done
for successful responses andeffects().error()
for validation errors. Use static import forakka.Done.done()
method. -
Events should be defined in the domain package and the events for an entity should have a common sealed interface, and define
@TypeName
for serialization. -
applyEvent
method should never return null, return the current state or throw an exception. -
Key Value Entities, Event Sourced Entities, Workflows can accept only single method parameter, wrap multiple parameters in a record class.
Endpoints
-
Implement HTTP endpoints with
@HttpEndpoint
and path annotations. -
Request and response endpoints should be defined as records inside the endpoint. Domain objects should not be exposed to the outside by the endpoint but instead be converted to the request and response objects of the endpoint. Include a
fromDomain
conversion method in the response record if there are many fields or nested records that needs to be converted from domain to endpoint records. -
Endpoints can return the response directly, without
CompletionStage
, since we prefer to use non-async code. For endpoint methods that create or update something it can returnHttpResponse
and return for exampleHttpResponses.created()
orHttpResponses.ok()
. -
Use
ComponentClient
for inter-component communication. When using thecomponentClient
you should use themethod
followed byinvoke
. Don’t useinvokeAsync
since we prefer to use non-async code, without composition ofCompletionStages
.