I am using Clean Architecture for a rich desktop application since about a year now and it works well for GUI-heavy, event-based applications. It's not a good fit for a "real-time" game like a jump'n'run, but a chess game will work just fine.
Instead of dissecting your question, I will go through a recap of the layers and will end with following the process of moving a figurine.
The Entities Layer
"Enterprise wide business rules". In your case, that means encapsulating the rules of the game. Having the age old game of chess here instead of an actual business gives you an advantage - once you wrote this layer, the only way it will ever need a change is if you found a bug here.
The Use Cases Layer
Think of use cases as application user actions. In this layer, you define these user actions, the input they take, the output they give back and the interfaces they use in order to achieve their goal. Such a use case will not really do any work itself. It's more like a step-by-step description of what happens.
The Interface Adapters Layer
The code you write that does the "grunt work" goes in here.
The Framework & Drivers Layer/Details Layer
This layer is purely an adapter from some external thing to your code (= the inner 3 layers). It consists almost completely of wrappers. This part needs to be so thin/simple that it doesn't need to know about the other 3 layers. It doesn't know about your models, it only works with strings, ints, events, etc.
The exception to this might be your setup code that connects everything, which is also in this layer for practical reasons rather than semantical.
(You called this the "Presentation layer", but that's a bit misleading. On one hand because a DB, some hardware device, internet access etc are also all external things that get their wrappers in this layer. On the other hand because all the "view logic" - like turning a model into strings for the GUI - happens in the previous layer.)
Moving a chess piece
Details layer
- In the GUI, the user drags a chess piece to a different square
- The class listening to that happening is a
BoardView
in the details layer
- The
BoardView
calls a BoardViewPresenter
with the simple info ('A', 1, 'B', 3)
Interface Adapters layer
- The
BoardViewPresenter
translates that into proper models from your Entities layer.
- It finds the
ChessPiece
on A1 and the BoardPosition
B3.
- It puts those into a
MoveChessPieceRequest
from the use case layer.
- It sends that to the
MoveChessPieceUseCase
(obviously also from the use case layer).
Use Case layer
- The
MoveChessPieceUseCase
validates the request according to the rules from the Entities layer.
- It goes through the steps "The target square is free", "The type of chess piece can move like that" and "There's no check to resolve".
- If any of the validation steps would have failed, the use case returns early a
MoveChessPieceResult
with a boolean Succeeded
set to false.
- However, in this example the request is valid, so it changes the Entities in memory and returns a positive result.
Interface Adapter Layer
- The
BoardViewPresenter
now has the MoveChessPieceResult
and reacts to the positive result.
- It gets the
ChessPieceView
and tells it Move('B', 3)
.
Details layer
- The
ChessPieceView
changes its actual position on the screen.
- It also plays a "move" sound
A mobile e-commerce app that talks to a web service is unlikely to have much business logic in the app itself. In this case, it would be overkill to apply clean architecture independently to the app. Rather, you could consider the app to be the outermost layer of your overall architecture, which talks to the web service, which in turn talks to the interactors that contain the real business logic.
All you need in the app is the MVVM portion. The "model" is likely just the DTOs returned by the web service, and the view-model can handle presentation logic and interactions with the web service gateway.
Best Answer
This happens when you follow the Dependency inversion principle.
Your core layer will define an interface, such as
Sender
. Your infrastructure layer will depend on the core layer and provide an implementation of the interface, such as aEmailSender
. Any class in your core layer which requires to send an email will only depend on the interface and remain ignorant of how it is actually implemented. Therefore, the core layer does not have any knowledge of the technical details of sending an email as they reside only in the infrastructure layer.Of course, at some point, you will need to pass a concrete implementation of the interface when constructing your objects. This generally happens in some
main
module, which depends on all your different layers and act as a glue between all of them. It only contains the code require to run your application, leaving the business logic encapsulated and isolated in the core layer.