1

Consider that when working on an Application which is modelled using DDD and implemented using Onion Architecture, you come along a following business case:

The Application, as one of its features, allows you to write Movie Scripts. When working with a given Movie Script, you have Characters, to which you can assign Actors, which can be real celebrities (say, Brad Pitt) or someone not known to the general public (your buddy Jon Doe). As a part of your Application, you want to have a separate section which deals with Actors: you want to be able to have a list of all the Actors available within your Application along with some basic info about them and you want to be able to "add" Actors to the list to later assign them to some Characters in your Application. Now, the "add" feature is a bit tricky in the following way: if a user enters a real celebrity (someone whom IMDB API can identify), we want to store some info about them (gender, age etc.) in the Actor entity. Otherwise, if it's some Jon Doe whom IMDB API couldn't identify, we only store their first/last names which are entered by the user of the Application. Either way, we need to make a call to some external API when creating new Actor entity.

It is obvious that ImdbApiFacade needs to be implemented as a part of Infrastructure layer and probably be called from Application layer before creating Actor entity, however it's unclear to me, where should a definition of the underlying interface go. Its not a Repository as it doesn't have persistence. It's not a Domain Service as it doesn't reflect any Domain Logic. It's not an Application Service since it doesn't facilitate interaction with the Domain Entity. We can't put it into Infrastructure as Application shouldn't depend on Infrastructure definitions. What is it then?

Another thing that's bugging me: the real problem with the modelling which I proposed is that, we don't really create Actors. Could this be a problem and should I reconsider my modelling approach?

2 Answers 2

1

You put an interface in the lowest layer that references it, simple as that.

Interface is not an implementation, it is not doing anything, which means that the question "what are objects in this layer are doing" is irrelevant. In other words, you are directing behavioral question towards a structural piece of code. Try asking same question about events and delegates — it just makes no sense.

As for an actual behavior, you already know the answer — I/O implementations belong in the infrastructure. Don't let it distract you.

One last thing. If you're afraid the interface could leak to the outer layers and someone would be tempted to use it — wrongly, causing issues (e.g. IMDB rate-limiting the app). The Onion Architecture imposes only a foundation that may be built upon. So tighten the screws in your DI container.

4
  • Thanks for the concise answer. "You put an interface in the lowest layer that uses it, simple as that" - sounds like something that should be easy to understand and follow. However, what about Repositories being frequently defined in Domain when they're usually used by Application?
    – nix
    Commented Apr 9, 2021 at 19:09
  • 1
    @nicks By using I meant referencing, not actually invoking anything. Sometimes Domain is a skeleton without a single drop of code, and yet we split it away. Honestly, specific scheme of Onion is not a holy grail, and people often slice it differently. The main concern of Onion and friends is dependency management. Commented Apr 9, 2021 at 19:53
  • 1
    @nicks I think you may find this interesting: blog.ploeh.dk/2013/12/03/… Commented Apr 9, 2021 at 19:55
  • 1
    @nicks Here's another interesting read, especially regarding using repositories inside the domain layer: enterprisecraftsmanship.com/posts/…
    – Rik D
    Commented Apr 9, 2021 at 20:47
0

It is obvious that ImdbApiFacade needs to be implemented as a part of Infrastructure layer and probably be called from Application layer before creating Actor entity, however it's unclear to me, where should a definition of the underlying interface go.

The rules of the onion architecture tells you:

The fundamental rule is that all code can depend on layers more central, but code cannot depend on layers further out from the core. In other words, all coupling is toward the center. -- Palermo, 2008

In a design where the infrastructure depends on the application (which is the usual arrangement), shared interfaces belong in the application.

This is, as it happens, the arrangement that agrees with the Dependency Inversion Principle

DETAILS SHOULD DEPEND UPON ABSTRACTIONS -- Robert Martin, 1996

"What is it then?" A contract - defined by the application, and implemented via infrastructure.


we don't really create Actors.

What I've found: if you look very carefully at what people are modeling with their domain models, it is mostly bookkeeping -- manipulating copies of information about interesting things.

So you aren't "creating an actor", you are making a copy of that actor's biographical data.

2
  • Soooo... Where do you put the external data provider then? Commented Apr 9, 2021 at 4:38
  • @Robert Harvey I think VoiceOfUnreason thinks it should go into Application Layer, although I’m not satisfied with the reasoning he provided. Pretty much all the definitions of the Application Layer which I’ve seen, state that its purpose is to orchestrate the business logic which doesn’t sound like what I need IImdbApiFacade to be at all.
    – nix
    Commented Apr 9, 2021 at 8:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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