DEV Community

Cover image for Handling complex MVC applications -  How to scale and avoid Controller chaos

Handling complex MVC applications - How to scale and avoid Controller chaos

Paul Isaris on October 27, 2018

Post cover image provided via undabot.com This article uses Laravel for the code snippets, but the paradigm can be easily adapted to eve...
Collapse
 
cmer4 profile image
Sergio Rudenko • Edited

Isnt MVC now something considered to be a first step while true scalability is with Redux like models? There was a facebook conference video that very clearly demonstrates how mvc alone was still failing facebook to scale and the redux model lead to creation of react?

UPDATE: here is the video: youtube.com/watch?v=nYkdrAPrdcw

Collapse
 
pavlosisaris profile image
Paul Isaris

Can you share with us the video, Sergio? Looks interesting.
Indeed, MVC can be limiting if you contraint your code only in the Controller.
But by mdularizing your code in other classes helps when designing to scale.

Collapse
 
cmer4 profile image
Sergio Rudenko

Yeah I would agree that MVC is a great concept and then I think even more granular - modularization of C + putting some thinking into "source of truth" for data and overall "state management" ensuring there is logic and order.
I think I did 3 major refactors to achieve that.

but I also would say - when I am prototyping (coding fast and dirty) I am actually fine with writing non scalable code as I don't see a problem to refactor it later on.

Collapse
 
cmer4 profile image
Sergio Rudenko
Thread Thread
 
pavlosisaris profile image
Paul Isaris

Cool, thanks!

Collapse
 
alexeevdv profile image
Dmitry Alekseev

All layers in your example are useless because of ORM models(persistent layer) leaking through repository and business logic right into the controller.

If you want to go with layers then you need business level entities to be separated from persistence level. This can be done with data mapper.

There is no point in repository that returns ORM models to you

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for your comment Dmitry. ORM is indeed very handy (and Laravel's Eloquent is very powerful), but you need to know how to use it, or which of it's features will obstruct your app's scalability.

Collapse
 
alexeevdv profile image
Dmitry Alekseev

My point is that if you go with layers then all ORM stuff should end up in persistence layer. Your controllers and business logic should know nothing about ORM

Thread Thread
 
pavlosisaris profile image
Paul Isaris

Hmm I get what you are saying. Do you mean that I shouldn't refer to DB table fields (like author_id) in the business logic layer?

Thread Thread
 
alexeevdv profile image
Dmitry Alekseev

More than that. You should not even have access to the database on the business logic layer. It should be done in persistence. With your current approach you pass ORM models into the view level where everyone will have direct access to the database because of access to ORM model. Somebody can make something like $model->delete() in the view template and mess the things up.

To prevent it you need to decouple persistence level and all other levels. In the persistence level itself you are free to use Eloquent, Doctrine, raw SQL queries, etc...

For more information please refer to fideloper.com/how-we-code

Collapse
 
erebos-manannan profile image
Erebos Manannán

I just spotted the private keyword in your code, which triggered a need to rant.

Personally I really hate code that uses the private keyword even once. It's pretty much always the wrong solution, unless you're delivering code to 100% externals who are intended to have limited access points. At least issues with protected code can be fixed (in most cases) relatively easily by extending the class.

In frameworks, or your own code that is supposed to be used by your own people, it's always wrong.

I can give several examples of issues I've had that are purely due to someone thinking they're smarter than every other programmer and thus using private to lock down their code from modifications (the only reason I've ever figured out for using it).

Just a few that first come into mind:

  • OAuth library, which we needed to reconfigure in automated tests just slightly, and ended up having to use reflection to change a private method to public
  • Frameworks have had bugs that would be easy to work around if the methods were protected or public so I could e.g. manually clear some state, even protected would've allowed extension to fix, but instead had to copy & paste the whole class and change one word from private to public to work around the issue
  • Database layer where someone built an optimization which caches lots of things internally, but in certain cases the cache caused problems and out of control memory use when we tried to batch process a few million entries in the db - it had a method for clearing the cache, which was private

Code should optimally be written with exactly zero attempts to limit what other developers can do with it, but hints as to what they probably shouldn't be using if they don't know what they're doing. The _ prefix for functions and variables, as e.g. Python has standardized, tends to be good enough.

This way, when you're trying to interface with something, you see the methods you're supposed to be calling for normal operation, and when you run into problems with your specific use case you can work around that, and then open an issue to get the issue solved later on.

Collapse
 
pavlosisaris profile image
Paul Isaris

Hey Janne, thaks for your fruitful comment. You are right, I also tend to use protected instead of private in my code, so that I can be able to extend the class and create sub-classes.

However, the point of the code snippets in this article is to provide a view of a layered MVC architecture and modularized classes.

In a more realistic scenario one would have preferred to use protected, for all the reasons you referenced.

Collapse
 
itsmrsammeh profile image
Sam Parton

I dont want to be "that guy" but... usually when we talk about scale-ability, its in terms of load balancing etc.

What you're referencing is maintainability, right? this is something that would confuse a lot of newcomers.

I could be wrong, I'm open to hear how if so.

If its not maintainability, then how does refactoring blocks of code make your project more scalable?

It makes it more readable and ofcourse, better to maintain when we go past a certain stage and our project is no longer a baby.

However, it doesn't reduce database load, improve the amount of connections our application can handle and so on.

Collapse
 
itsmrsammeh profile image
Sam Parton • Edited

However, just to provide some code examples in Laravel.

An unscalable chunk of code(in my opinion) would be this:


$users = User::get();

foreach($users as $user) {
    $user->name = 'Bob'; // We set them all the same name for example
    $user->save(); //This would be a query for each user
}

If we had 100 users, this would be 101 queries.


//Instead, for this example, we could just call this:

User::update(['name' => 'bob']); 

Resulting in just one query.

Collapse
 
pavlosisaris profile image
Paul Isaris

Hey Sam,
I agree with your point of view. By "Scaling", I essentially mean to prepare the app not only for more users and DB rows, but for new client requirements and Business Logic.
Sure load balancing will be a nice solution If you plan to make your 100 usres to be 10000. But will not help you much with new business requirements.
So yes, by "Scaling" I do mean "Easy to maintain and grow in terms of business requirements".

Collapse
 
ghost profile image
Ghost

I've found the Hierarchical MVC pattern a good one for scalability: en.wikipedia.org/wiki/Hierarchical...

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for this - haven't heard it before. Isn't it similar with the MVVM (Model - View - ViewModel)? en.wikipedia.org/wiki/Model%E2%80%...

Collapse
 
ghost profile image
Ghost

Hmmm not that I can tell. I think H-MVC is more like a combo between Chain-of-Responsibility and MVC. In any case, it came in handy with a complex Java/Swing GUI I had to build way back, where my first attempt was to squeeze the whole thing into a single MVC layer, which ended up way too complex and hard to maintain.

Collapse
 
emlautarom1 profile image
Martín Emanuel

What a great post. The way you explained how to separate each layer was concise and clear. Thanks for sharing!

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks for sharing your opinion on my post, Martin! :)

Collapse
 
mungaijosephnduati profile image
mungaiJosephNduati

You really explained it so well! .I have learnt a lot in ten minutes! Thank you.

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks! :D

Collapse
 
davidfrafael profile image
David Fernández

Shouldn't

} catch (Exception $e)

be

} catch (\Exception $e)

?

Relating the article, I agree, though I just leave in the Manager real complex shared logic, I've all the rest in the repo class.

Collapse
 
pavlosisaris profile image
Paul Isaris

You are right! However, the puprose of the code snippets are not to be syntactiaclly correct, but to give an overview of the architecture.

Collapse
 
cesaresaman profile image
Saman Mohammadi

Good explanation of why we should follow SOLID Rules

Collapse
 
pavlosisaris profile image
Paul Isaris

Thanks Alex! :)