1

In the chapter "Business Rules" of his book "Clean Architecture", Robert C. Martin comments on the relationship between use cases and the UI:

[...] the use case does not describe the user interface other than to informally specify the data coming in from that interface, and the data going back out through that interface. [...] Use cases do not describe how the system appears to the user. Instead, they describe the application-specific rules that govern the interaction between the users and the Entities.

Context

For some context, I'm writing a simple client app (Android) using Clean Architecture + MVP in the presentation layer. Though MVP combines the controller and presenter, I'm still trying to think of them as independent aspects of the "interface adapters" layer in Clean Architecture.

In my app, users can create new events or edit existing events via a simple form UI. Each event has a start date, an end date, and a description. In my "domain" conventions (what I understand to be the convention convenient for doing useful operations uninfluenced by any one framework), an event is a simple Kotlin data class:

data class Event(
  val startDate: LocalDate,
  val endDate: LocalDate,
  val description: String
)

My form has simple behavior:

  • Show a loading spinner while an existing event is loaded from a remote data source.
  • If the selected start date is after the selected end date, then the end date is moved to be equal to the new start date. For example, if the end date was set to 2020-06-01, then I set the start date to 2020-06-02, the end date would now also be/show 2020-06-02.
  • Show a loading spinner while the event is being saved to a remote data source.

My understanding is that Clean Architecture describes the "business rules"/"use cases"/"domain" of an application to be application-specific behaviour implemented using conventions that will not be influenced by frameworks chosen to implement details such as UI. In my case, that means working with events treating dates as LocalDates, even though my UI inputs dates as year, month, and day Ints and ouputs them as Strings.

On one hand, handling the loading state and relationship between date inputs seems like a presentation concern because my use cases shouldn't know anything about the UI. However, leaving the controller and presenter to be interface adapters which simply translate from a framekwork-like conventions to domain-like conventions and vice versa, and leaving them unaware of each other, the domain seems like the only place left to implement these behaviors. That leaves me with a use case output port something like this:

interface EditEventOutput {
  fun showLoading()
  fun hideLoading()
  fun renderEndDate(date: LocalDate)
}

My Question

That looks like a presenter's view interface to me, but my presenter is unaware of this behavior. I tried using more generic terms, like an isLoading Boolean instead of the terms "show" and "hide", but that's not solving my issue.

The interface I've ended up with looks like a UI! It doesn't discuss details about the UI, like what "show loading" means (i.e. it could be a line of text in a terminal, or a fancy UI widget), but it still implies the existence of UI.

So, even though use cases do not describe how the system appears to the user, do they imply the existence of some user interface? If they should not, and we should be capable of implementing the output ports on any sort of interface adapter (maybe it doesn't even output to a UI), then where do I implement behaviors such as handling a loading state and the relationship between my start and end date pickers?

1

Modelling

What are you modelling if not some form of User Interface? The very fact that you are trying to model a UI will make the model look like a UI.

The same as Dolphins look like Ichthyosaurs and Fish. The problem is the same.

The rule of thumb is trying to make it so that you solve the problem, not the framework.

The goal of pulling back from the framework like this is to allow for different UI frameworks, even different UI kinds to be driven by the same underlying logic with only a very thin framework adapter.

That will not only help keep these different UIs consistent, but also go a long way to making the really tricky logic is easily testable.

Design

Personally when thinking through this problem I pick several UI kinds:

  • a Window/Menu Based UI (be that graphical, or a text display with keyboard/mouse)
  • a Command UI (such as a vt terminal, or a REST request/response)
  • a Tactile UI (such as a gamepad, gesture, or voice control)

While you should not over engineer your interface, it helps to consider such disparate control schemes to really force you away from framework thinking, and instead focus on the User Interface to the business logic.

| improve this answer | |

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.