4

I am trying to implement Uncle Bob's Clean Architecture in my C# WPF Application. Currently my view (form) calls the presenter and the presenter calls the interactor.

Should the interactor return a value (if any) directly or invoke a presenter method. In the latter case, the presenter is attached to the interactor before the calling the interactor?

I know it's a silly question, but I am confused.

1
  • 1
    Don't try to do this with WPF. It follows the MVVM architectural pattern. Use Winforms if you want to learn the MVP pattern Uncle Bob describes.
    – RubberDuck
    Aug 5, 2017 at 16:15

3 Answers 3

7

Model-View-Presenter architectures try to uncouple the User Interface (view) from the application logic (presenter) and from the business logic (model). The "interactor" typically pulls data from the data storage, and there is hardly business logic associated with it.

With WPF, Model-View-ViewModel is the typical style. The View (user interface) knows its ViewModel (which contains the interaction logic and notifies the view about property changes via INotifyPropertyChanged), and the ViewModel knows its Model (data, business logic, validation). The interaction between View and ViewModel is handled by "binding".

With Asp.net, Model-View-Controller is the typical style. The Controller knows both the View and the Model, and controls the view directly.

1
  • 1
    Yup. Use the architecture that fits, which may or may not be what Uncle Bob says. MVVM is the way to go with WPF.
    – jleach
    Aug 6, 2017 at 17:44
2

It's easier to explain with a short example. It's also better if Presenter and Conttroller are separated as in Uncle Bos's explanation. It's by the way necessary if you want to implement Dependency Injection with an IoC container.

Let's say you have a simple use case where the user can search a client from its Id and display its Name, or an error message if the client is not found.

Your View class gets a Controller and a Presenter in its constructor. It has a TextBox for the Id to search, and a Button to launch the search. It also has 2 TextBlocks for the client's Name and the error message. These 2 are bound to properties in the Presenter.

When the user clicks the Button, the View gets the TextBox content and calls controller.Search(id).

Ultimately, the UseCaseInteractor completely controls the behavior, whether it choose to display the client or an error message (or anything else...).

Some pseudo-code for the C#:

class Controller {
    Controller(IUseCaseInput){ }
    Search(clientId){ input.Search(clientId); }
}

interface IUseCaseInput { Search(clientId); }

class UseCaseInteractor : IUseCaseInput {
    UseCaseInteractor(IUseCaseOutput) { }
    Search(clientId){ 
        client = ...
        if (client == null) {
            output.SetError("Argh!.";
        } else {
            output.SetClient(client);
        }
    }
}

interface IUseCaseOutput {
    SetError(message);
    SetClient(client);
}

class Presenter : IUseCaseOutput {
    string Error { get; set; }
    string Name { get; set }
    SetError(message) { Error = message; }
    SetClient(client) { Name = client.Name; }
}

Not very natural when you are used to MVVM, but does perfectly the job to defer all decisions to the use case. It resembles much more what an MVC framework does for the Web.

2
  • So where is the ViewModel here ? can you provide example of how to use Clean Architecture with MVVM ?
    – IronHide
    Dec 8, 2021 at 16:01
  • There is no ViewModel in this pattern, it’s an alternative to MVVM.
    – Philippe
    Dec 10, 2021 at 17:46
0

As the interactor lives in the "usecases" circle and the presenter is an "interface adapter" the dependency rule answers that clearly: the interactor must NOT call any API on the presenter.

The picture by Uncle Bob - shown in the article linked in the question - shows that the interactor defines input and output ports. that could be classes (DTOs) or interfaces which are then implemented on "interface adapter" layer/circle.

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