Entity Analysis and Design

ASAMI, Tomoharu Created: 2025-09-08

We explore the differences between analysis models and design models of entities, which are central to domain models.

When building a design model from an analysis model, one of the key enhancements is the consideration of non-functional requirements—especially quality attributes.

However, there are also aspects of the structural model itself that require extension.

A representative example is the introduction of purpose-specific objects used to manipulate entities.

This article delves into design strategies and architecture for representing entities in programs, as well as the potential for their automated generation.

Programmatic Representation of Entities

The SimpleModeling Reference Profile adopts Scala as the programming language.

Therefore, entity design is realized as Scala code.

In SMRP, the method for manipulating entities is based on using value objects. As a result, the core of entity design lies in defining value objects in Scala.

Limitations of Simple Mappings

The following diagram illustrates an example of an input/output architecture that uses a single value object to operate on an entity.

Input/Output Architecture Centered on Simple Value Objects
Figure 1. Input/Output Architecture Centered on Simple Value Objects

When using a value object, data updates often require an inefficient process of reading, overwriting, and writing back the data.

Furthermore, using a generic record type at the cost of type safety reduces the reliability of the program.

Using the same value object for different purposes can lead to mismatches with usage contexts and require unnecessary consideration.

Data Operation Architecture

The diagram shows the data operation architecture adopted in SMRP.

Entity Input/Output Architecture
Figure 2. Entity Input/Output Architecture

When performing input/output for entities, applications can choose from the following options:

  • Use operation-specific entity values

  • Use I/O-specific entity values

  • Use record functionality

  • Directly use platform-level features

The higher the abstraction level of the function used, the greater the programming ease and reliability through type safety.

Record

SMRP provides generic record objects for flexible data handling.

Defining dedicated Scala classes for every specific use case can be cumbersome and time-consuming. Moreover, having too many similar but subtly different classes may increase the likelihood of introducing bugs.

Record objects serve as a flexible fallback for handling such edge cases.

The following types of record objects are provided in the SimpleModelingLib:

  • org.simplemodeling.record.Record

Purpose-Specific Classes for Entities

In analysis models, an entity is typically defined as a single class, but in design models, it is desirable to define multiple purpose-specific classes with mutual convertibility.

For simple applications, a one-to-one mapping between entity and Scala class may suffice, but as the application grows in complexity, multiple Scala classes per purpose become necessary.

Types of Entity Classes
Figure 3. Types of Entity Classes

While the analysis model represents an entity with a single class, the design model must provide multiple purpose-specific classes and ensure convertibility among them.

Primary Use Categories

  • For logic processing

  • For view

  • For entity operations

    • Read

    • Create

    • Update

    • Bulk update (omitted in diagram)

  • For external integration

Placement in Model Spaces

In the operation space of the application, value objects for logic processing are placed (shown as Entity Value for Operation in the diagram).

In the view space, value objects for external presentation are placed (Entity Value for View).

For entity operations, the following value objects are designed for each specific purpose:

  • For reading: Entity Value for Read

  • For creation: Entity Value for Create

  • For update: Entity Value for Update

  • For bulk update: omitted in the diagram

For external integration, Entity Value for Exchange is provided.

Example of an Analysis Model

In SimpleModeling, design models are created from analysis models written in CML, following the concept of Analysis Model Up/Down.

The following source shows an example of the analysis model Reservation described in CML.

reservation.cml
Reservation
===========

# Entity

## Reservation

### Attribute

| name       | type                    | mul |
|------------+-------------------------+-----|
| id         | identifier              |   1 |
| name       | name                    |   1 |
| description| description             |   ? |
| resourceId | ResourceId              |   1 |
| interval   | Interval[ZonedDateTime] |   1 |
| reserver   | UserId                  |   1 |

Implementation of the Analysis Model in Scala

When directly implemented as a Scala object, the analysis model takes the following form:

Reservation.scala
case class Reservation(
  id: Reservation.Id,
  name: Reservation.Name,
  description: Option[Reservation.Description],
  resource: ResourceId,
  interval: Interval[ZonedDateTime],
  reserver: UserId
)

Design Model

Let us define the following purpose-specific Scala objects derived from the analysis model:

  • For logic processing

  • For view

  • For entity operations

    • Read

    • Create

    • Update

    • Bulk update

  • For external integration

Logic Processing

In CQRS commands, complex domain logic is executed primarily around update operations.

These operations manipulate entities in-memory. Thus, it is necessary to define a class that contains sufficient information to support complex in-memory domain logic.

Reservation.scala
case class Reservation(
  id: Reservation.Id,
  name: Reservation.Name,
  description: Option[Reservation.Description],
  resource: Resource,
  interval: Interval[ZonedDateTime],
  reserver: User
)

Information required for logic processing must be expanded from referenced objects and held as value data within the class.

However, it is not necessary to expand all information from referenced objects. Only the information that is safe for external exposure should be retained. It does not need to be as strictly curated as view-specific classes.

For example, the attribute user is held as an expanded value User, rather than just a data type like UserId.

View-specific classes also expand and retain referenced object contents in a similar manner.

View

Cloud-native applications inevitably adopt a CQRS architecture. In CQRS, views are prepared as data representations for queries.

This requires value objects specifically designed for entity views.

Reservation.scala
case class Reservation(
  id: Reservation.Id,
  name: Reservation.Name,
  description: Option[Reservation.Description],
  resource: Resource,
  interval: Interval[ZonedDateTime],
  reserver: User
)

Information required for view queries must be expanded from referenced objects and stored as value fields. However, it is not necessary to expand all information from the referenced objects. Only the information that can be safely exposed externally should be retained.

For example, the resource attribute is stored as a value Resource instead of the data type ResourceId.

Similarly, the user attribute holds an expanded value User instead of UserId.

Entity Operation

These are value objects designed to perform operations on entities persisted in a database.

Read

Scala class used when loading a single entity from the database.

To enhance compatibility with the database, it is constructed primarily using basic data types.

Reservation.scala
case class Reservation(
  id: String,
  name: String,
  description: Option[String],
  resource: String,
  interval: String,
  reserver: String
)

Attribute types use basic Scala/Java types or types easily handled by SQL.

The interval attribute is internally an Interval of ZonedDateTime, but is stored as a String (encoded as XML or JSON) for database compatibility.

The read class uses Option types in accordance with the analysis model definition.

Create

Scala class used when creating a new entity.

Required fields must be explicitly provided; optional fields are defined using Option.

Reservation.scala
case class Reservation(
  id: String,
  name: String,
  description: Option[String],
  resource: String,
  interval: String,
  reserver: String
)

Update

Scala class used for updating an entity.

The ID is a required attribute, and all other updatable fields are defined using Option.

Reservation.scala
case class Reservation(
  id: String,
  name: Option[String],
  description: Option[String],
  interval: Option[String]
)

In practice, using only the Option type makes it ambiguous whether a field should be ignored in the update or explicitly set to NULL to delete its value.

Bulk Update

Scala class used for bulk updates based on matching conditions, without using entity IDs.

Reservation.scala
case class Reservation(
  name: Option[String],
  description: Option[String],
  interval: Option[String]
)

It has a structure similar to the Update class, but omits the id attribute.

It is used to update all entities that match conditions other than id.

External Integration

When integrating with external systems, Scala classes must be converted to and from various formats such as XML, JSON, YAML, etc.

  • XML

  • JSON

  • YAML

  • HOCON

  • Properties

  • gRPC IDL

Since manually implementing these conversions is costly, generic data transformation libraries are used whenever possible.

The SimpleModeling reference profile adopts Circe from the Cats ecosystem.

Reservation.scala
case class Reservation(
  id: String,
  name: String,
  description: Option[String],
  resource: String,
  interval: String,
  reserver: String
)

As with database integration, attributes are kept to basic types to simplify conversion mapping across formats.

Even for formats not natively supported by Circe, integration is relatively easy when using these structured Scala classes.

Literate Model-Driven Development

Thus far, we have examined the correspondence between analysis and design models in domain modeling, focusing particularly on entity persistence.

To enable type-safe entity operations, it is necessary to define multiple value objects for a single entity, each tailored to a specific purpose.

Manually coding these classes is a labor-intensive task, but this challenge can be addressed through programmatic code generation.

In SimpleModeling, the model compiler "Cozy" automatically generates the following purpose-specific design model classes (in Scala) from analysis models written in CML:

  • View

  • Logic processing

  • Entity operations

    • Read

    • Create

    • Update

    • Bulk update

  • External integration

Summary

This article focused on the differences between analysis and design models of domain entities, clarifying the structure and roles of purpose-specific value objects through design strategies and concrete Scala implementations.

We demonstrated that by preparing optimized classes for each use case—view, logic processing, operation, and external integration—it is possible to achieve both type safety and development efficiency.

Furthermore, within the framework of Literate Model-Driven Development, we introduced how leveraging automatic generation via Cozy makes this design approach sustainable and scalable.

Looking ahead, further developments such as application to other domains, expansion of generation targets, and integration with UI models and API specifications are anticipated.

References

Glossary

SimpleModeling Reference Profile (SMRP)

This is the reference profile of SimpleModeling. To concretely illustrate Literate Model-Driven Development with SimpleModeling, a reference profile is defined.

value object

A Value Object is an object in a domain model that represents a semantically meaningful group of values, such as attributes or descriptions. It does not have a persistent identity like an entity, is immutable, and equality is based on its values.

type safety

Type safety refers to the property of a programming language or system where operations are guaranteed to be used with values of the correct type. Type-safe code prevents invalid operations by detecting type mismatches at compile time (or runtime), reducing runtime errors and unexpected behaviors. Scala ensures type safety through strong static typing combined with type inference, enabling expressive yet safe programming.

bug

A colloquial term referring to software problems. It has no strict technical definition and is often used broadly to cover Defects, Faults, or Failures.

CML (Cozy Modeling Language)

CML is a literate modeling language for describing Cozy models. It is designed as a domain-specific language (DSL) that forms the core of analysis modeling in SimpleModeling. CML allows model elements and their relationships to be described in a narrative style close to natural language, ensuring strong compatibility with AI support and automated generation. Literate models written in CML function as intermediate representations that can be transformed into design models, program code, or technical documentation.

Analysis Model Up/Down

Analysis Model Up/Down is a bidirectional modeling approach in which the analysis model serves as the central layer, enabling upward derivation into conceptual or design models ("Up") and downward transformation into implementation artifacts such as code or data definitions ("Down").

Literate Model-Driven Development (LMDD)

Literate Model–Driven Development (LMDD) is a software development methodology that integrates natural-language narrative and formal model structure within a unified text-based framework. It extends conventional Model–Driven Development (MDD) by treating documentation and models as a single, consistent source of truth. In LMDD, the descriptive and structural elements of development artifacts are expressed together using the SmartDox language. From this unified representation, ModelDox extracts structural data, CML (Cozy Modeling Language) defines domain-specific models, and Cozy generates executable code, documentation, and configuration artifacts. Artificial intelligence participates in the LMDD process by analyzing the narrative context, validating structural consistency, and supporting the refinement of models and generated artifacts. All artifacts are represented in text form, ensuring traceability, version control, and interoperability within standard development environments. By defining a formally connected and machine-interpretable relationship between documentation, design, and implementation, LMDD provides a foundation for AI-assisted model–driven engineering where human authorship and automated reasoning operate on the same representational layer.