0

I am pretty new to software architecture, and I am trying to understand the basic concepts of n-layer architecture and MVP (specifically Passive View).

My current understanding of n-layer architecture:

The point of n-layer architecture (or n-tier architecture if we have a physical separation between the layers) is to separate the presentation, the business logic, and the data management.

The presentation layer is responsible for the visual aspect of the software. It is common to implement it using MVC or derived design patterns (such as MVP in my case).

The business layer represents the real-world context via domain models, which are classes representing aspects of this context.

The data layer is responsible for handling the relationship with the database. It contains data-access classes and repositories.

My current understanding of MVP (Passive View):

MVP is a design pattern for the presentation layer. The View is responsible for showing the visual information to the user. The Model is a specific domain-related class that holds the data showed in the View. The Presenter is responsible for handling all presentation-logic (if(view.x == y) view.ChangeLabelColor()), and for passing View data to the Model.

So let's say I have a form that shows basic employee information. The information I want to show is his ID, his name, his monthly salary, and a computed yearly salary. The View will look something like this:

public partial class EmployeeView : Form
{
    private EmployeePresenter presenter;

    public short Id
    {
        set { idTextBox.Text = value.ToString(); }
        get { return short.Parse(idTextBox.Text); }
    }
    public string Firstname
    {
        set { firsnameTextBox.Text = value; }
        get { return firsnameTextBox.Text; }
    }
    public short MonthlySalary
    {
        set { monthlySalaryTextBox.Text = value.ToString(); }
        get { return short.Parse(monthlySalaryTextBox.Text); }
    }
    public short YearlySalary
    {
        set { yearlySalaryTextBox.Text = value.ToString(); }
        get { return short.Parse(yearlySalaryTextBox.Text); }
    }

    public EmployeeView()
    {
        InitializeComponent();

        presenter = new EmployeePresenter(this);

        idTextBox.TextChanged += presenter.IdChanged;
        firsnameTextBox.TextChanged += presenter.NameChanged;
        monthlySalaryTextBox.TextChanged += presenter.MonthlySalaryChanged;
        calculateYearlySalaryButton.Click += presenter.CalculateYearlySalary;
    }
}

The Model will look something like this:

class EmployeeModel
{
    public short Id { get; set; }
    public string Name { get; set; }
    public short MonthlySalary { get; set; }
    public short YearlySalary { get; set; }

    public EmployeeModel(short id, string name, short monthlySalary)
    {
        Id = id;
        Name = name;
        MonthlySalary = monthlySalary;
    }
}

The Presenter will look something like this:

public class EmployeePresenter
{
    // tightly-coupled to avoid overcomplicating the example
    private readonly EmployeeView view;
    private readonly EmployeeModel model;

    public EmployeePresenter(EmployeeView view)
    {
        this.view = view;
        this.model = new EmployeeModel(view.Id, view.Firstname, view.MonthlySalary);
    }

    public void CalculateYearlySalary(object sender, EventArgs e)
    {
        var yearlySalary = (short)(model.MonthlySalary * 12);
        view.YearlySalary = yearlySalary;
        model.YearlySalary = yearlySalary;
    }
    public void IdChanged(object sender, EventArgs e) => model.Id = view.Id;
    public void NameChanged(object sender, EventArgs e) => model.Name = view.Firstname;
    public void MonthlySalaryChanged(object sender, EventArgs e) => model.MonthlySalary = view.MonthlySalary;
}

In the business layer I would have an Employee class:

class Employee
{
    public short Id { get; private set; }
    public string Name { get; private set; }
    public short MonthSalary { get; private set; }
    // Not necessarily "YearlySalary" because it is
    //calculated specifically for the specific View above

    ...
}

The question is this: assuming my code is fine (which I hardly believe it is), where would I "link" the form to the business logic? Where will I put the information that an id cannot be negative, for example? How will I wire a "Send" button to eventually map the EmployeeModel into an Employee, and register it into the database? All of these are about the interaction between the layers. Where should it be and how should it look like?

1 Answer 1

2

Where will I put the information that an id cannot be negative, for example?

Validation of input data from the user is typically accomplished in two places. You do validation in the UI for the user's convenience, so that they can get the form completed properly without having to make many round trips to the server. Then you do it again on the server-side because you can't trust what the client sends you.

How will I wire a "send" button...

There are a number of ways to do that. In a web application, the browser knows how to do a POST if you put a SUBMIT button on the form. In a desktop application this is going to look different.

One of the reasons multi-layer software exists is to provide a common surface with which disparate clients can communicate. If you stand up a JSON API, that API will work the same way whether your client is a browser, a native phone app or a desktop application.

Sample architecture (yours will vary):

[Database] <--> [Repository] <--> [BLL] <--> [Service/Gateway] <--> [Presenter] <--> [View]
             ^SQL              ^CRUD      ^RPC                   ^JSON/REST       ^EVENTS

| ----------------------- MODEL ---------------------------- | ----- PRESENTER --- | VIEW |

Where BLL is the Business Logic Layer/Domain Layer.

8
  • Thanks! Perhaps I should be a bit clearer. Which component is responsible for communication between layers? Specifically, between the presentation and the business layers? In my case, is that the presenter? the model? Sep 13, 2018 at 15:45
  • The Model contains the business logic. That model can be architected any way you want; MVC doesn't concern itself at all with that. Sep 13, 2018 at 15:48
  • So let's say I press a button on the form, what would be the sequence of method calls until repository.InsertToDB()? Sep 13, 2018 at 15:59
  • That would depend on how your Model is architected. There are many ways to achieve such architecture. Sep 13, 2018 at 16:46
  • 1
    See my answer update. Sep 13, 2018 at 16:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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