1

I'm building an Android application, and trying to follow the Clean Architecture pattern.

I am a little confused on what my entities should look like regarding some of my use cases.

Example

I have a list of channels, and each channel have programs. I want to display a list of the current program for each channel, and when an element is clicked, I display a channel page with the channel detailed info and the current program info.

Entities

I can see here that I should have a Channel and a Program entity. But should Channel have a field List<Program> programs (as there are mutiple programs during the day)? And another Program currentProgram? Or should Channel be separated

Use case

Should they return entities, or some dto object? Currently, my use cases return entities, but are mapped to some dto objects in the presenters.

TL;DR

Which of the proposition below is the way to go?

Pseudo-Code propositions

Case A

Entities

Channel
{
  id()
  name()
  logo()
}

Program
{
  id()
  name()
  thumbnail()
  start_date()
  end_date()
}

Use Cases
List<Channel> GetChannelsUseCase()
Program GetCurrentProgramForChannel(channelId)

Presenter

fetchChannels()
{
    // Builds a List<CurrentProgramViewModel> based on
    // GetChannelsUseCase composed with GetCurrentProgramForChannel for each channel
}

Case B

Entities

Channel
{
  id()
  name()
  logo()
  programs()
}

Program
{
  id()
  name()
  thumbnail()
  start_date()
  end_date()
}

Use Cases
List<Channel> GetChannelsUseCase()

Presenter

fetchChannels()
{
    // Builds a List<CurrentProgramViewModel> based on
    // GetChannelsUseCase and filtering the programs()
    // to extract the 'current' program
}

Case C

Entities

Channel
{
  id()
  name()
  logo()
}

Program
{
  id()
  name()
  thumbnail()
  start_date()
  end_date()
}

Repository
List<Channel> GetChannelsUseCase()
Program GetCurrentProgramForChannel(channelId)

Use Cases
List<ProgramDto> GetCurrentProgramUseCase()

{
    // The Use Case requests the repository to get the entities
    // and builds a ProgramDto object
}

Presenter

fetchChannels()
{
    // Maps a List<CurrentProgramViewModel> based on the
    // List<ProgramDto> returned by GetCurrentProgramUseCase
}

ps: I'll ask about the datasource and repository later / in another topic if necessary

2

In my experience, a Program isn't permanently tied to a Channel. In fact, a Program can appear on several Channels sometimes even at the same time!

I think you're missing a Listing entity which takes care of associating Programs with a specific time. This means that your Programs should no longer track their start and end times anymore but they probably should track their duration. You might benefit from a Schedule as well to link a Listing with a Channel.

Pseudocode:

Channel
{
  id,
  name,
  logo,
}

Program
{
  id,
  name,
  thumbnail,
  duration,
}

Schedule
{
  channelId,
  date,
  listings = Collection<Listing>
}

Listing
{
  program,
  startTime,
  endTime = () => startTime + program.duration,
}

You would then have a service that allows you to query Schedules base on the channel and date.

  • What about the usecases though? Can/should they in fact return the entities? – w00ly Feb 7 '18 at 13:13
  • I'm confused about this use of the term "use case". A use case isn't a class or grouping of code in your application. Rather, it's an example of how your application is used to accomplish something. – MetaFight Feb 7 '18 at 14:06
  • I meant "Interactor" :) – w00ly Feb 7 '18 at 14:09
1

I believe that a Presenter should have as little logic as possible, and only interact with a single UseCase.

In Uncle Bob's sample, he actually passes the Presenter to the UseCase as a parameter. (The UseCase accepts an interface OutputBoundary.) The UseCase passes a ResponseModel to the Presenter which contains all of the information that the Presenter needs to know to build the ViewModel. Overall, this is closest to your Case C.

Note: I'm a bit unsure if that ResponseModel should contain entities or properties.

And I second MetaFight's recommendation about the missing entities and avoiding the composed entity.

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.