DEV Community

Cover image for MVC Sucks, and We Should Learn from It
aymane aallaoui
aymane aallaoui

Posted on

MVC Sucks, and We Should Learn from It

Introduction:

Countless framework designers and programmers have found that MVC (Model-View-Controller) is the most successful way of organizing code in web development. It has been used in various frameworks and projects guiding the arrangement of applications by developers. However, let’s be honest, MVC is not perfect. This means that it contains multiple weaknesses that make coding complex; maintainability can turn into a nightmare and may lead to disappointments among the developers. When we are building a web application, it will be important for us to learn from such weaknesses without completely dismissing MVC. In this blog post, we shall discuss some of these shortcomings associated with MVC.

The Problem with MVC:

According to its proponents, Model should manage data while View should render UI and Controller should act as an intermediary between both of them. At first sight, this separation seems reasonable enough but at practice it results in bulky controllers, thin models and tight coupling components.

Let's take a look at a typical MVC setup in PHP:

class PostController {
    public function index() {
        $posts = Post::getAll();
        require('views/posts/index.php');
    }
}


class Post {
    public static function getAll() {
        // Fetch posts from the database
    }
}

// View 
foreach ($posts as $post) {
    echo "<h2>{$post->title}</h2>";
    echo "<p>{$post->content}</p>";
}

Enter fullscreen mode Exit fullscreen mode

It is the controller’s responsibility in this example to retrieve information from the model and pass it on to the view for rendering. Nonetheless, with the growth of an application, a controller tends to become overloaded with logic for handling various requests thereby adding onto its difficulty of maintainability and testing.

The Proposal: Going beyond MVC

Instead of blindly following MVC, we could adopt a more elastic architecture that addresses the inadequacies of MVC. One of them involves blending Domain-Driven Design (DDD) with CQRS (Command Query Responsibility Segregation).

DDD puts greater emphasis on what are referred to as domain-driven models rather than the technical frameworks used when building applications. By defining richly structured domains that include distinct entities, value objects, and aggregates, we can confine most business rules within applications.

CQRS helps split our application into read or write operations thus optimizing read and write models independently such that they improve performance and scalability.

Let's refactor our previous example using DDD and CQRS principles:

// Controller
class PostController {
    private $postService;

    public function __construct(PostService $postService) {
        $this->postService = $postService;
    }

    public function index() {
        $posts = $this->postService->getAllPosts();
        require('views/posts/index.php');
    }
}

// Service
class PostService {
    private $postRepository;

    public function __construct(PostRepository $postRepository) {
        $this->postRepository = $postRepository;
    }

    public function getAllPosts() {
        return $this->postRepository->getAll();
    }
}

// Repository
class PostRepository {
    public function getAll() {
        // Fetch posts from the database
    }
}

// View 
foreach ($posts as $post) {
    echo "<h2>{$post->getTitle()}</h2>";
    echo "<p>{$post->getContent()}</p>";
}

Enter fullscreen mode Exit fullscreen mode

So in this in example, we have introduced a service layer responsible for orchestrating business logic and a repository layer responsible for interacting with the data store. This separation of concerns makes our code base more maintainable and testable.

Conclusion:

So, the end point of this discussion will be that while MVC has been used as a model for web based applications for years, it is important to realise its inadequacies. By taking lessons from MVC’s flaws as well as embracing other flexible architectures like DDD and CQRS we can come up with web applications that are easier to maintain, scale up and follow clean code and good design principles. Thus let us go beyond MVC and embrace the changing structure of web applications.

Top comments (4)

Collapse
 
xwero profile image
david duymelinck • Edited

You have good points, just be aware you don't drown yourself in design patterns just for the sake of it.

In your example the first code you wrote is good enough. The service is an extra function call that adds nothing. And you created another layer you have to debug.

If you want testable controllers and models dependency injection will do the trick without adding too much code.

class PostController {
   // gets Post and View object
    public function index(IMPost $post, IView $view) {
        $posts = $post->getAll();
        return $view->render('views/posts/index.php', $posts);
    }
}

class Post implements IMPost {
   public __construct(private IDbConnection dbConnection)  {}

    public function getAll() {
          return $this->dbConnection->query('select * from posts');
    }
}

class View implements IView {
   public function render(string $path, $data) {
      return ''; // string based on $path and $data variables
  }
}

interface IMPost {
  public function getAll(); 
}

interface IView {
   public function render(string $path, $data);
}

interface IDbConnection {
   public function query(string $sql);
}

Enter fullscreen mode Exit fullscreen mode

The (test)framework you use will instantiate the object for you, as long as it follows the interface you are good to go.

About the controllers maintainability, that depends on how you structure them.

MVC is just one of the tools you can use to structure your code, it does not suck. If you hit your finger with a hammer , it is not a bad hammer.

DDD is good but it requires a lot of preparation and communication. If you create a domain on your own, you have to explain it to everyone else and that can be a lot of extra work.

CQRS is only needed if you experience a lot of deadlocks because the database can't handle all the manipulations. Most databases are fast enough for most sites.
What most developers want is the message bus architecture, which can be a part of CQRS.

Collapse
 
firecrow8 profile image
Stephen Firecrow Silvernight

Good thought provoking article, my experience has been that MVC tries to be a one-size-fits-all, and more discussion about the application can probably lead to a better custom approach.

I see that you've taken DDD as an inspiration, it's almost like M, V, and C are each a DDD domain, and that actually makes more sense sometimes. That way you can have two or more domains, and focus on what they do more than what they are.

Data locality and ownership can be a concern in the Controller as well as the Model and the View.

Collapse
 
daelmaak profile image
Daniel Macák

Adding service and api layer doesn't change anything about the MVC architecture you criticize. It only abstracts away certain kind of operations the controllers were doing themselves in your example, but doesn't change anything about the underlying architecture.

I'd also say that DDD doesn't have much effect on the MVC architecture. You can have MVC both with and without DDD.

Collapse
 
rohiitbagal profile image
Rohit

But bro now a days views are now used...