0

Talking about gateways from the Clean Architecture, it is required to distinguish:

  • The interfaces
  • The implementation of these interfaces

The TypeScript example:

// === Interface ======================================
interface UsersGateway {
 
  retrieveSelection: (requiestParameters: UsersGateway.SelectionRetireving.RequestParameters) => 
       Promise<UsersGateway.SelectionRetireving.ResponseData>;

}

namespace UsersGateway {
  export namespace SelectionRetireving {

    export type RequestParameters = Readonly<{
      paginationPageNumber: number;
      itemsCountPerPaginationPage: number;
      fullOrPartialName? string;  
    }>;

    export type ResponseData = Readonly<{
      totalItemsCount: number;
      filteredItemsCount: number;
      itemsForCurrentPaginationPage: ReadonlyArray<User>;
    }>;
  }
}


// === Implementation =======================================
class UserMySQL_Gateway implements UserGateway {
  retrieveSelection(
    requiestParameters: UsersGateway.SelectionRetireving.RequestParameters
  ):  Promise<UsersGateway.SelectionRetireving.ResponseData> {
    // Implementation including SQL code here
  }
}

Now the question: in below image from Clean Architecture book, the "Gateways" in the green ring are interfaces of their implementations? If one of them, there is another?

enter image description here

My assumptions

Although the frameworks must be in the outer (blue) ring and, I have not seen the framework-independent Controllers and/or Presenters before. Thus, the "gateways" in the green ring could be the implementations which depends on some framework or RDBMS (matching with Interface adapter concept).

If so, there is the gateway interfaces? The table of contents of Chapter 20 Business rules is:

  • Entities
  • Use Cases
  • Request and Response Models
  • Conclusion

Are mentioned above Request and Response Models the gateway interfaces?

3 Answers 3

1

Without seeing more code than what you provided in your Typescript example, it's impossible to be 100% certain, but I'd wager that the following is roughly correct (if not, just mentally shift it by one layer).

The Request and Response Models are just your RequestParameters and ResponseData. Your UsersGateway interface, RequestParameters and ResponseData all belong to the red UseCases Layer (they are "owned by", or serve the needs of, some Interactor - that presumably has something to do with users). The UsersGateway interface is similar to the Output Port (depicted in the inset) in that it is callable by the Interactor, except that it is used to retrieve data instead (the Interactor decides when to initiate the retrieval; in contrast, an Input Port is called by things in the next layer out). The constructor of the Interactor would polymorphically take a concrete gateway as a UsersGateway parameter.

The RequestParameters and ResponseData types are associated with the UsersGateway, so in some sense they together define a broader interface (or an API) to the gateway (that is, an class that implements UsersGateway must also make use of these request and respons types). This is why they are all listed under the "Interface" section in the code snippet.

The UserMySQL_Gateway implementation is in the green interface adapters layer - it "adapts" the UsersGateway interface required by the Interactor and connects it to the interface (API) exposed by whichever data access library you're using. You'd inject the UserMySQL_Gateway instance as the aforementioned UsersGateway parameter. The fact that the UsersGateway interface is itself defined inside an inner layer (and for the specific needs of the Interactor) is what leads to dependency inversion.

Now, Clean Architecture doesn't mandate the exact number of layers - you can use more or less than depicted, depending on your needs. In your TypeScript example, UserMySQL_Gateway directly depends on the framework/library; this is fine, because the Interactor itself is decoupled via the UsersGateway interface. So in some sense, the dependency rule is broken in the outermost layer, but that's always going to happen in the outermost layer - you have to call your frameworks/libraries at some point. Alternatively, you can think of the blue Framework & Drivers layer being merged into the green one, maintaining the dependency rule globally. You could in principle decide to decouple UserMySQL_Gateway by applying dependency inversion in a similar fashion, if the logic is particularly complicated, and you wanted to introduce a UserMySQL_Gateway-owned interface that'll (1) help simplify the code and make it more readable, and (2) enable you to unit-test the gateway.


See also my answer to this question - it discusses how someone who's more familiar with writing procedural and/or CRUD-y code might arrive to a Clean Architecture–like design.

1

OK wait I'm changing my answer.

Its clear that interfaces in the code sense are used to fudge the dependency direction in all cases. ie Everything has interfaces not just Gateways where as "interface" in the common sense just means a bit of code that provides an interface between two other bits.

So a Gateway is an "interface" (green layer) and has an interface (green/blue and or green/red depending on what is using it)

Basically they are just saying "avoid circular dependencies by using interfaces"

Request and Response models are business rules because unless you convert them to multiple different but identical DTOs all over the place, everything is going to have to depend on their definition

0

From my understanding, the clean architecture model has each layer knowing nothing about the one above it but using entities (yellow) from layers below if needed (as per the arrows). This way, any layer can be swapped out without affecting anything below it, making it 'clean'.

With this in mind, the use-case layer would only use entities or collections of entities from the layer below in the parameters of methods. (such as orders=List[Orders], etc.). This makes the gateway layer (green) where the repository interfaces are, along with presenters for UI, etc. These are all things on the boundary edge of the system.

The repository implementations are in the final layer above, where everything speaks to the outside world.

Your Answer

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

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