1

I am writing a service and a library that I need to make framework agnostic because it will be used by some client services. The client services will be written in both Micronaut and Spring frameworks. So I must probably avoid DI in a container.

The library wraps the communication to the service, giving the client services Domain objects to use. So the Domain Context spans between multiple services.

The problem is I cannot use DI in a container. Is it still within Port And Adapters architecture to create and configure adapters implementations in the Application layer (without a container DI) and give them to Domain layer (of course using port interfaces for the Domain layer) ?

Certainly the crucial part in P&A is to use Ports in Domain Layer . But do I need to or should I create another layer just for creating and configuring adapters due to P&A architecture ?


edit: To the down-voters: Could you specify in the comments what is wrong with the question ?

edit2: Edited question title and contents to avoid opinion sounding phrases like "Is it ok".

1 Answers1

6

Separate use and construction.

When you say “without DI” I suspect you mean without a DI container. DI existed long before containers were a thing.

DI done with containers has become popular. So popular that Mark Seemann had to make up a word for DI without containers. He calls it Pure DI. But I can assure you, the idea is much older than that. Back in the day we just called it reference passing.

With that cleared up let's get to your question:

Is it ok within Port And Adapters architecture to create and configure adapters implementations in the Application layer

Construction doesn't have to be done in any layer. Construction is what creates the layers. When you're looking at a diagram of ports and adapters you're looking at an object graph. It shows you what knows about what. It doesn't show you what built what. Every long lived thing in that diagram could have been built in main.

Some objects aren't long lived. Some are ephemeral. They must wait until something happens before they should exist (timestamps). These are the ones that must be constructed deep in the call stack. If your adapter fits this description then not only is it ok. It's a must.

But that'd be a fairly weird adapter. Most adapters can be built with all the other long lived objects at the beginning. I mean, unless your adapter is some bloated thing that needs lazy loading.

As for your frameworks, yes, they work very hard at stealing main from you to make you dependent on them. There is a host of tricks to undo that damage. Mark Seemann taught us one called the composition root.

If you can be disciplined about how you use frameworks you can hold them at arms length and keep them from taking over how all objects are constructed. That doesn't mean you can't let them build some. Just that you shouldn't let them bully you into doing everything their way.

Key to that is making sure you have a way to inject things you built yourself into things they built for you. And vice versa. That all comes back to the composition root.

Finding out how to do this isn't easy with most frameworks precisely because they don't want you to be independent of them. Remember, DI is just passing references around. It's not that fancy.

Most DI containers move construction code out of your native language into something else. That helps you separate use and construction. But if you're not careful it also robs you of control over construction.

POJO's can be built without any container annotations by both PureDI and ContainerDI. POJO's with container annotations that can't be constructed by PureDI are all to easy to create. Be aware of what you're loosing before you commit to this style.

But also, be aware that holding a framework at arms length like this comes with a cost. They don't make it easy to stay independent. You have to decide for yourself if the fight is worth it.

Anyway, strictly speaking, since Ports and Adapters doesn't talk about how to construct its object graph there's nothing telling you it's not OK to construct an adapter in the application layer. Any wisdom about that must come from elsewhere.

Separate use and construction

candied_orange
  • 119,268