4

I have a RESTful API service that has three layers: Application/Domain, Infrastructure, and Presentation.

Application/Domain contain my interfaces and models. I currently have three different types of models:

  1. DTO - These are the models my controllers return to the client as well as the models that are passed around all the layers of my application.
  2. POCO - Domain model that has an instance of the corresponding DTO, it has business rules/validations.
  3. Entities - Persistence models that mirror database objects.

Now, if my RESTful API makes a request to another API service and the request requires both a body and response, I would want to create models for both the body and the response right? What would this kind of model be called and which layer would I put it in?

I guess it would have to go in the Application/Domain layer because that's where the interface for my third party API client would also be. But what would I call these models? Are they entities? Are they DTOs?

Hmmm...I guess they could be considered entities. An entity is a model that represents the data in the database and I guess the third party API could also be considered a database of sorts...

I was initially calling the services that connect with dbs repositories and calling services that connect with other APIs ApiClients. But they really are just facade services. So I guess they are the same?

What do you guys think?

2 Answers 2

5

I guess it would have to go in the Application/Domain layer because that's where the interface for my third party API client would also be.

A third party API is, by definition, not part of your current application domain. It is an external service, after all.


Hmmm...I guess they could be considered entities. An entity is a model that represents the data in the database and I guess the third party API could also be considered a database of sorts...

I am sidestepping your "what should I call it?" question because naming isn't quite the main thing to focus on here, but your comment does hit a nail on the head here: external apis are functionally indistinguishable from a database.

In essence, whether you connect to a database server or a web backend which serves data is an irrelevant distinction in terms of how to categorize this logic in your codebase.

As it stands right now, the code calling the API belongs in Infrastructure, just like where your database logic resides.
That being said, depending on size and complexity, you may want to start subdividing the Infrastructure project into separate projects, if that makes more sense to you. In software development, it's always possible that a particular use case may warrant being broken down into smaller parts further.


However, that only established where you put the services that call the API. But where do you put the models for the in/output of your service?

It somewhat depends on whether you are using inverted dependencies or not. If you aren't, then the models can live together with the service in the Infrastructure layer, since your Application will depend on Infrastructure and have access to all of its services and models at the same time.

However, if you're using inverted dependencies, that means that the Application (or Domain) layer defines the service's interface, which needs access to the in/output models, which means that you can't just plop those models in Infrastructure. In this case, they belong to the service's contract, and should be kept closeby to where you store the service interface itself. I personally would put them in the same directory, since they tend to uniquely belong to each other.

That being said, when working on professional (enterprise-grade) projects, I would strongly urge you to separate the interface models from the actual external service models, as a matter of keeping the external service sufficiently abstracted. This ensures that any changes made to the external service (and thus needing to be made to the external service models) don't necessarily have to cause you to change your interface contract itself, as long as you can simply update the mapping between the external and internal models to remain compatible.

Which means:

  • For normal dependencies:
    • One internal (i.e. assembly-private) model in Infrastructure for the service logic
    • One public model in Infrastructure to be consumed by its dependents (i.e. Application)
    • The service class in Infrastructure will map from one to the other as it needs it.
  • For inverted dependencies:
    • One model with the service interface in Application (just like before)
    • One internal (i.e. assembly-private) model in Infrastructure for the service logic
    • The service class in Infrastructure will map from one to the other as it needs it.
0

The weird thing is, I can't tell the difference between any of your particular Objects, be they DTO, POCO, or Entity.

A DTO is a POCO. Its a data structure containing data. It is the reason why you can send them across a network.

An Entity on the other hand is business logic. Business logic isn't a data structure. It may encapsulate data, in which case why is that being serialised to a repository? It may manipulate data, in which case that Data is in another DTO/POCO.

I think its more accurate to say this:

  • You have DTO objects (just plain old data usually a bunch of named strings and scopes) written in terms of your provided interface, and third-party interfaces. Their job is to serve as the marshalling ground for requests and responses over any given IO system: The API, Third Party Services, The Database, UI, etc...
  • You have Domain objects (just Plain old Data usually in higher level data abstractions like dates, lists, users, etc...) written to support your domain. These are tailored to the algorithms and business logic employed by your own system.
  • You have Domain/Entity objects representing the system that consume, manipulate, and generate Data Structures.
  • You have Presenter objects representing the logic needed to translate between DTO and Domain objects.
  • You have Interactor/Use Case objects whose job is to map a request/response on an API from the incoming DTO through Presenters into an orchestration of Entity behaviours, Domain Data and then back out through presenters to a DTO.

You may want to look into Bob Martin's clean architecture lectures.

4
  • "An Entity on the other hand is business logic." Predominantly, "entity" is used to refer to a database model. What you're referring to (business logic) is generally called the "domain object". From a purely English perspective, you're not wrong that "entity" is very vague and pretty much literally just means "thing that exists" and could be applied to almost anything, but from a developer-centric perspective, "entity" tends to imply datalayer.
    – Flater
    May 31, 2021 at 9:15
  • At an English level yes it pretty vague, I think though it has a much more defined meaning in software. For example: ECS - Entity Component System. It probably depends on the neck of programming you come from. However I am using it coming from the domain/business logic angle. In this case I think the existence of the term ERM (Entity Relational Mapping) undermines your definition. If the Entity lives in the data layer, why is it being mapped from the data layer? Sounds more like the Entity lives above the data layer. In which case the fact that it can be serialised is irrelevant to the Entity.
    – Kain0_0
    May 31, 2021 at 9:32
  • I think you're msunderstanding ERM: "In software engineering, an ER model is commonly formed to represent things a business needs to remember in order to perform business processes. Consequently, the ER model becomes an abstract data model, that defines a data or information structure which can be implemented in a database, typically a relational database." The entities in question represent the data models for the database (which, ideally, mimic the domain objects, but that is not always feasible).
    – Flater
    May 31, 2021 at 9:54
  • @Flater. Thankyou for pointing that out. Looks like I need to spend some time reading up on this.
    – Kain0_0
    Jun 1, 2021 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.