4

I am referring to Robert C. Martins book "Clean Architecture" on the top of page 318.

There he states:

In the ports and adapters approach, the OrdersService and Orders interfaces have inbound dependencies from other packages, so they need to be made public. Again, the implementation classes can be made package protected and dependency injected at runtime.

I fully understand the intention of making more components package protected rather than public.

My question is, how can the implementations be made package protected (internal in C#) if they should be dependency injected? How should the composition root access these types to register them with the IoC container?

Or is there a difference between package protected in Java and internal in C#?

Or maybe I am misinterpreting his statement?

1

How should the composition root access these types to register them with the IoC container?

One possible way to deal with this is to use a factory. Take OrdersService for example. In the assembly that implements this, you may have a public IOrdersService interface and a public OrdersServiceFactory that returns an instance of IOrdersService. The composition root then calls that factory to resolve an instance of IOrdersService, and it's supplied an instance of the internal class, OrdersService.

If at a later date, you identify a need for more than one IOrdersService implementation, then you just change the inner workings of the factory. The composition root doesn't have to change. That way you avoid coupling the composition root to the inner workings of other assemblies.

But things may even be further decoupled. That implementation of IOrdersService can be made to be the only place that creates an instance of IOrders when eg myOrdersService.CreateOrder(…) is called. In this case, there is no need to even expose some sort of factory to the composition root. It has no responsibility for creating orders so needs to know nothing about such implementations.

  • Just to clarify: OrdersService is already the interface in Uncle Bob's statement, he doesn't prefix his interfaces with I. So wouldn't that lead to a 'pattern' where we only need to create factories to be used by the composition root and only to not make the implementations public? Whereas the factories need to be public again. – Creepin Dec 20 '18 at 8:43
  • @Creepin using the I- prefix is a common convention in C#, though not in Java. – cbojar Jan 20 at 14:58
0

internal means it can only be accessed within the same assembly. package protected in Java means they can be accessed by other classes in the same package. The meaning is a little different.

Conceivably you could have external libraries using that package which could make use of that service, provided they use the same package name, so there would be no issue with implementations coming from outside the assembly. In C#, I suppose you'd have to declare it as public, as I don't think there exists an equivalent that would work for external libraries.

  • So, if my composition root resides in the host application, this must have the same package name as my component to be able to access these types? I am not that into Java but I think this wouldn't solve the problem, because the main application would not have the same package name as the component where the package protected types reside. Hence, even in Java, don't I need to make these types public if I want to register them in the container from outside? – Creepin Dec 19 '18 at 13:11
  • @Creepin Only the OrdersService and Orders would reside in the same package. External libraries wanting to take advantage of this would need to necessarily create their classes in the same package to be able to "see" Orders in order to derive from it. Of course you could always make it public and drop the constraint, but it is generally preferable to be more restrictive when possible. – Neil Dec 19 '18 at 13:16

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.