2

I've recently started applying the Clean Architecture while developing an Android application. And so I divided my application in 4 different parts.

enter image description here

Data layer

Contains the implementation of repositories.

Device layer

Contains implementation of android related stuff like AlarmManager, not related to storage of entities.

Domain layer

Use cases (interactors) are implemented here and interfaces for repositories are defined here.

Presentation

UI related stuff, fragments, view models, activities.


This application is not in isolation, it exists in a system with a backend and a frontend (web app) where some users use the mobile app and some use the web app.

Now, according to the clean architecture, the business logic should reside in the domain layer. But in this scenario I feel like it does not belong there. Let's take an example.

Let's say a User can purchase MovieTickets from different type of cinemas.
In this scenario, we would have a use case called PurchaseMovieTicket.

Now the question is. Where should the actual logic on the purchase be implemented? There are two ways this can be done.

Type 1

Most examples on clean architecture on android only consider the Repository as something to do CRUD operations on whether its on the cloud or local storage (eg. Android Room). This would mean the PurchaseMovieTicket use case would include logic such as.

  • Remove money from user
  • Add the movie ticket to the user
  • Call update on the repository with the User as parameter

Now the drawbacks here is obvious. What if the backend needs to do other things related to purchasing of movie tickets, perhaps communicate to other systems even, then all this would also need to be implemented in the app. You can almost see how this is not possible.

Type 2

The Repository contains a method called purchaseMovieTicket which takes a MovieTicket and a User. This method would do the necessary logic on the backend or wherever it is implemented.

Drawback here is well, the use case becomes almost unnecessary because it just forwards the call from the view model to the repository. And there is no business logic to talk about.

Question

  • Which type would be the best to use in this system? Why?
  • Is it good to put the business logic in the backend?
  • If you go with implementation type 2, does the repository break the clean architecture principles?
5

It should be on a case-by-case basis but I would expect most of the logic to go in the backend.

Your interactor might still contain several methods ("Check ticket availability", "Add ticket to basket", "Checkout") but yes the implementation could be expected to be very simple in some cases.


You might want to consider:

  • Security. Any code that you need to trust, implement on the backend. Assume a hacker can change the client code to do what they want. In your type 1 example, what if they changed it to only call "Add the movie ticket to the user" and not "Remove money from user"?

  • Communication coupling. As you mention, for anything that needs to communicate with other systems, prefer the backend so that the client only needs to communicate with your backend.

  • Responsiveness. Things on the client end (aside from heavy computation) will generally have better performance for the user than communicating with the backend. Something like computing a total basket price might be better on the client end for this reason.

  • Duplication. If you have two clients, implementing the logic in the client will require it to be duplicated, so prefer the backend.

  • Data location. Prefer to put the logic with the data that it operates on. For example, if it requires computing on a lot of data from the backend database, but only sends a small result to the user, put that logic in the backend. Or the opposite might apply.

  • API. Prefer to place the logic so that the backend's API feels cohesive and consistent.

  • Race conditions. Placing logic in the backend makes use of transactions and similar techniques much easier, decreasing the risk of concurrency issues.

  • Resource requirements. On mobile, I'd suggest heavy computation should be done on the backend. If this was a desktop app known to run only on decent machines, it might be better to prefer the client end to reduce server load.

Note this isn't an exhaustive list.

  • Could you perhaps elaborate a bit more on why most examples on Clean Architecture only mentions CRUD repositories? And would it be against repository pattern to have such a method like purchaseMovieTicket() or should repository pattern only have CRUD operations? – Ludvig W Jun 28 at 21:11
  • @LudvigW to be honest I don't have much knowledge of Clean Architecture in particular. This answer comes from constraints and considerations for software in general. But if you want to keep things in a CRUD format, what about turning "purchase movie ticket" into a CREATE on a MovieTicketPurchase repository? Just a thought, not sure if it's applicable to your case. – just me Jun 28 at 21:22
2

The very definition of the terms "front end" and "back end" comes from the separation of business logic (back end) from the user interface (front end). So yes, business logic should be in the back-end, whether that is a remote service or simply a different layer in the same application.

Given that you already have a separate back-end system, you should apply Clean Architecture primarily to this system, which should house all the business logic. The mobile app can be thought of as an extension to the UI layer of the back-end system, and therefore does not have any business logic of its own. All the use cases and repositories live in the back-end, and the mobile app simply uses a gateway to talk to the back-end.

  • Im not sure i agree with your definitions of front/back end and that it leads to "business logic should be in the backend". Its a model. Its an approach. Its a choice. – Sir Swears-a-lot Jul 1 at 1:48
  • @SirSwears-a-lot: It's certainly a choice, and indeed many codebases mix business logic with UI code. But then it's no longer obvious what the front/back end is, it's just a monolithic structure. – casablanca Jul 1 at 3:23
0

Im a DBA not a developer, so i will offer you a pro db perspective.

Implementing logic using a combination of Stored procs and table driven values in the db that can be shared by both the web app and mobile app means you get security, performance and consistency.

It has the added advantage that when you want to make a change that change is rolled out immediately to all users irrespective of interface.

It also means changes to behavior can be made by the business without having to redeploy software.

  • 1
    All the same things could be true of logic written in a service as well. – Ben Cottrell Jun 30 at 6:59
  • @BenCottrell what about table driven configuration? A way of allowing the business to update the rules without having to recompile or redeploy software? – Sir Swears-a-lot Jun 30 at 22:17
  • Configurability for complex business rules is something to be avoided in my opinion. To me that implies a number of risks including lack of source control for those changes, lack of automated testing, lack of visibility for the development team who wouldn't have those changes available in their Dev/QA environment, changes being made by users outside of the development team who are probably less aware of technical implications of their changes. But also, If the release process is done well, then needing to recompile and redeploy software should be fairly trivial anyway. – Ben Cottrell Jul 1 at 9:07
  • 1
    For the most part i agree with you. I think this is grey area. I wouldnt consider changing a price a business rule, but enforcing product package options i would. Ive worked on systems where the business could do that. – Sir Swears-a-lot Jul 1 at 9:23

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.