Backend Development 9 min read

Domain Interface Design and Its Application in Backend Systems

The article explains how designing domain models as interfaces, rather than concrete classes, improves flexibility in backend architectures by simplifying data exchange, supporting multiple persistence technologies, and enabling seamless deployment across standalone, clustered, and micro‑service environments.

IT Architects Alliance
IT Architects Alliance
IT Architects Alliance
Domain Interface Design and Its Application in Backend Systems

Designing domain models as interfaces instead of concrete classes is a common practice for service and repository layers, but a deeper understanding of full interface‑based design—especially for domain models—can greatly enhance flexibility and maintainability.

Typical domain models are classes; however, they can be defined as interfaces, e.g.:

public interface User { /* ... */ }
public class UserImpl implements User { /* ... */ }

When using JPA, a repository implementation might look like:

public class JpaUserRepository implements UserRepository {
@Override
public Optional
findById(String id) {
UserPO userPO = this.entityManager.find(UserPO.class, id);
return Optional.ofNullable(userPO).map(UserPO::toUser);
}
@Override
public User save(User user) {
UserPO userPO = this.entityManager.find(UserPO.class, user.getId());
userPO.setNickname(user.getNickname());
return this.entityManager.merge(userPO).toUser();
}
}

Because the User is an interface, the data‑exchange overhead of converting between PO and domain objects can be reduced by returning concrete interface implementations directly.

For repositories that rely on specific generic types (e.g., Spring Data Elasticsearch), the interface‑based approach is not directly supported, so a delegating repository is used:

public class DelegatingElasticsearchUserRepository implements UserRepository {
private final ElasticsearchUserRepository elasticsearchUserRepository;
public DelegatingElasticsearchUserRepository(ElasticsearchUserRepository repo) {
this.elasticsearchUserRepository = repo;
}
@Override
public User create(String id) { return new ElasticsearchUser(id); }
@Override
public Optional
findById(String id) {
return CastUtils.cast(this.elasticsearchUserRepository.findById(id));
}
@Override
public User save(User user) { return this.elasticsearchUserRepository.save(ElasticsearchUser.of(user)); }
}

When persisting entities that contain interface‑typed collections, JPA cannot infer the concrete type. The targetEntity attribute solves this problem for associations such as @OneToMany , @OneToOne , @ManyToOne , and @ManyToMany :

@OneToMany(targetEntity = JpaOrderItem.class)
private List
items = new ArrayList<>();

If the persistence framework does not support targetEntity , encapsulation or explicit mapping (e.g., MyBatis resultMap ) can be used to bind interface collections to concrete classes.

Creating domain objects also shifts from using the new operator to factory methods provided by application services, e.g.:

@Test
public void testCreateUser() {
User user = this.userService.createUser(null);
user.setNickname("Nickname");
user.setGender(Gender.MALE);
this.userService.addUser(user);
}

System‑level interface design further enables seamless switching between standalone, clustered, and micro‑service deployments. By exposing domain interfaces through separate modules (e.g., user-api , user-openfeign-client , user-rest-client ), the same business code can run in different environments without modification.

The open‑source Mallfoundry project exemplifies these principles: it is a Spring Boot‑based multi‑tenant e‑commerce platform that adopts DDD, interface‑based design, and modular architecture, allowing it to run as a library, a server, a cluster, or a cloud service.

In summary, interface‑based domain modeling creates a unified contract for business logic, simplifies persistence across various data sources, and prepares the system for future architectural changes, though it demands higher expertise from developers and architects.

backendDomain-Driven DesignSpringRepositoryInterface DesignJPA
IT Architects Alliance
Written by

IT Architects Alliance

Discussion and exchange on system, internet, large‑scale distributed, high‑availability, and high‑performance architectures, as well as big data, machine learning, AI, and architecture adjustments with internet technologies. Includes real‑world large‑scale architecture case studies. Open to architects who have ideas and enjoy sharing.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.