Introduction to .NET Architecture Patterns: MVC, MVP, MVVM, Domain Driven Design

MVC (Model-View-Controller)

When to Use MVC?

MVC is ideal for web applications with a clear separation between user interface and business logic. It is beneficial in websites with multiple pages and functionalities that require structured management of user-application interaction.

Concept

The MVC pattern separates the application into three main components:

  • Model: Represents the data logic and state of the application. It handles data access and manipulation.
  • View: Represents the user interface. Its role is to display data from the model to the user and receive user interaction.
  • Controller: Manages the communication between model and view. It receives user input through the view, processes these inputs, and updates the model and/or view accordingly.

Implementation in .NET

In .NET, especially with ASP.NET MVC, MVC is implemented natively. ASP.NET MVC allows developers to create web applications where HTTP requests are handled by controllers that interact with models and select appropriate views to generate responses.

// MVC
public class HomeController : Controller
{
    public IActionResult Index()
    {
        var model = new HomeModel { Message = "Hello, Codú!" };
        return View(model);
    }
}

Detailed Example: Task Management Application

Imagine a simple task management application. The controller would handle user requests to view, add, and delete tasks, while the model would manage the business logic and data storage. The view would display the task list and allow user interaction.

public class Task
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsCompleted { get; set; }
}

public class TaskController : Controller
{
    private static List<Task> tasks = new List<Task>();

    public IActionResult Index()
    {
        return View(tasks);
    }

    [HttpPost]
    public IActionResult AddTask(string name)
    {
        var newTask = new Task { Id = tasks.Count + 1, Name = name, IsCompleted = false };
        tasks.Add(newTask);
        return RedirectToAction("Index");
    }

    [HttpPost]
    public IActionResult CompleteTask(int id)
    {
        var task = tasks.FirstOrDefault(t => t.Id == id);
        if (task != null)
        {
            task.IsCompleted = true;
        }
        return RedirectToAction("Index");
    }
}

Benefits

  • Separation of Concerns: Improves code maintainability and testability.
  • Flexibility: Facilitates modification of one part of the application without affecting others.

Pros and Cons

  • Pros: Clear separation of roles, easy to understand and adopt.
  • Cons: Can become complex with large teams and big projects.

Next Steps

To delve deeper into MVC, consider exploring the official ASP.NET MVC documentation and implementing a small personal project to apply these concepts in a controlled environment.

MVP (Model-View-Presenter)

When to Use MVP?

MVP is useful in desktop applications where presentation logic can be complex and needs to be independently tested. It is an excellent choice for enterprise desktop applications.

Concept

The MVP pattern is similar to MVC but is more commonly used in desktop and mobile applications. Its components are:

  • Model: Handles data and application logic.
  • View: The user interface.
  • Presenter: Acts as an intermediary between the model and the view. The view communicates with the presenter to update data, and the presenter updates the view.

Implementation in .NET

MVP is common in Windows Forms applications. The pattern allows presentation logic to be separated from UI logic, facilitating code testing and maintenance.

// Example of a Presenter in MVP
public class MainPresenter
{
    private readonly IMainView _view;
    private readonly IMainModel _model;

    public MainPresenter(IMainView view, IMainModel model)
    {
        _view = view;
        _model = model;
        _view.Load += OnLoad;
    }

    private void OnLoad(object sender, EventArgs e)
    {
        _view.DisplayData(_model.GetData());
    }
}

Detailed Example: Task Management Application

In a task management application using Windows Forms, the Presenter would manage view interactions and update model data.

public interface ITaskView
{
    event EventHandler Load;
    void DisplayTasks(IEnumerable<Task> tasks);
}

public class TaskPresenter
{
    private readonly ITaskView _view;
    private readonly ITaskRepository _repository;

    public TaskPresenter(ITaskView view, ITaskRepository repository)
    {
        _view = view;
        _repository = repository;
        _view.Load += OnLoad;
    }

    private void OnLoad(object sender, EventArgs e)
    {
        var tasks = _repository.GetAllTasks();
        _view.DisplayTasks(tasks);
    }
}

Benefits

  • Ease of Testing: Separation of presenter and view allows more effective unit testing.
  • Flexibility: Views can be swapped out without modifying presenter logic.

Pros and Cons

  • Pros: Facilitates testing and maintenance, good separation of presentation logic.
  • Cons: Can introduce additional complexity in architecture.

Next Steps

To delve deeper into MVP, check out the MVP guide in Windows Forms and try implementing your own example.

MVVM (Model-View-ViewModel)

When to Use MVVM?

MVVM is perfect for applications with rich user interfaces that benefit from data binding, such as WPF and Xamarin applications. It is ideal for mobile and desktop applications with dynamic user interfaces.

Concept

MVVM is an evolution of the MVC pattern and is especially popular in WPF (Windows Presentation Foundation) and Xamarin development. Its components are:

  • Model: Contains business logic and data.
  • View: The user interface.
  • ViewModel: A view model that exposes data and commands that the view can bind to.

Implementation in .NET

WPF and Xamarin are platforms where MVVM shines due to their data binding capabilities. In MVVM, the view is directly bound to the ViewModel, allowing automatic bidirectional communication between view and model via ViewModel.

// ViewModel in MVVM
public class MainViewModel : INotifyPropertyChanged
{
    private string _message;
    public string Message
    {
        get { return _message; }
        set
        {
            _message = value;
            OnPropertyChanged(nameof(Message));
        }
    }

    public MainViewModel()
    {
        Message = "Hello, Adrian!";
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Detailed Example: Task Management Application

For a task management application in WPF, the ViewModel would manage logic and data, while the view would bind to properties and commands of the ViewModel.

public class TaskViewModel : INotifyPropertyChanged
{
    private string _taskName;
    public string TaskName
    {
        get { return _taskName; }
        set
        {
            _taskName = value;
            OnPropertyChanged(nameof(TaskName));
        }
    }

    public ICommand AddTaskCommand { get; }

    public TaskViewModel()
    {
        AddTaskCommand = new RelayCommand(AddTask);
    }

    private void AddTask()
    {
        // Logic to add task
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Benefits

  • Data Binding: Facilitates automatic synchronization between view and model.
  • Separation of Concerns: Increases maintainability and testability of code.

Pros and Cons

  • Pros: Powerful for applications with complex user interfaces, facilitates maintenance and testing.
  • Cons: Can be overkill for simple projects, steeper learning curve.

Next Steps

To delve deeper into MVVM, explore the MVVM documentation in WPF and experiment with a personal project.

Domain Driven Design (DDD)

When to Use DDD?

DDD is best for complex systems where the business domain is extensive and well-defined. It is ideal for large enterprise applications and e-commerce systems.

Concept

Domain Driven Design is a software design methodology that emphasises focusing on the business domain and logic. Rather than focusing on technology, DDD recommends that software design aligns with the actual domain model. The main components of DDD include:

  • Entities: Objects with their own identity that persist over time.
  • Value Objects: Objects without identity defined solely by their attributes.
  • Aggregates: Groups of objects treated as a unit.
  • Repositories: Interfaces for accessing aggregates from the database.
  • Domain Services: Operations that don't fit well within entity or value objects.

Implementation in .NET

Implementing DDD in .NET typically involves using Entity Framework for data persistence, along with building services and repositories that encapsulate data access logic. Projects are often structured into layers such as domain, infrastructure, application, and presentation for clear separation of concerns.

// a Repository in DDD
public interface ICustomerRepository
{
    Customer GetById(Guid id);
    void Save(Customer customer);
}

public class CustomerRepository : ICustomerRepository
{
    private readonly DbContext _context;

    public CustomerRepository(DbContext context)
    {
        _context = context;
    }

    public

 Customer GetById(Guid id)
    {
        return _context.Set<Customer>().Find(id);
    }

    public void Save(Customer customer)
    {
        _context.Set<Customer>().Add(customer);
        _context.SaveChanges();
    }
}

Detailed Example: E-commerce System

In an e-commerce system, entities like Customer, Order, and Product would exist, with domain services handling complex business operations.

public class OrderService
{
    private readonly IOrderRepository _orderRepository;

    public OrderService(IOrderRepository orderRepository)
    {
        _orderRepository = orderRepository;
    }

    public void PlaceOrder(Order order)
    {
        // Business logic to process the order
        _orderRepository.Save(order);
    }
}

Benefits

  • Alignment with Business: Facilitates collaboration between developers and domain experts.
  • Scalability: Allows applications to grow in a structured and coherent manner.

Pros and Cons

  • Pros: High alignment with business domain, facilitates handling of complexity.
  • Cons: Can be overkill for simple projects, requires more initial effort.

Next Steps

To delve deeper into DDD, it's recommended to review the introduction to Domain Driven Design and consider reading the book "Domain-Driven Design: Tackling Complexity in the Heart of Software" by Eric Evans.

Practical Comparison of Patterns

  • MVC: Ideal for web applications with clear separation between user interface and business logic.
  • MVP: Useful in desktop applications where presentation logic can be complex and needs independent testing.
  • MVVM: Perfect for applications with rich user interfaces that benefit from data binding, such as WPF and Xamarin applications.
  • DDD: Best for complex systems with extensive and well-defined business domains, such as large enterprise applications and e-commerce systems.

Practical Comparison of Patterns

  • Performance: MVC tends to be lighter in web applications, while MVVM may be more resource-demanding due to data binding.
  • Ease of Maintenance: MVVM and DDD offer better maintainability in long-term projects due to their separation of concerns and focus on business domain.
  • Scalability: DDD is highly scalable for complex systems, while MVP scales well in desktop applications with complex presentation logic.

Conclusion

The use of .NET architecture patterns such as MVC, MVP, MVVM and DDD allows developers to create more robust, maintainable and scalable applications. Each pattern offers advantages and suits different types of projects and requirements. Choosing the right pattern depends on factors such as the nature of the application, business requirements and the preferences of the development team. With a solid understanding of these patterns, you can design and build more efficient systems aligned with business goals.

Resources

MvcMvpDotnetMvvmDdd
Avatar for Adrián Bailador

Written by Adrián Bailador

🚀 Full-Stack Dev 👨🏻‍💻 .NET Engineer 👾 Geek & Friki 💡 Talks about #dotnet, #csharp, #azure, #visualstudio and a little bit of #nextjs.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.