Does MVC discourage OOP

I’ve given this more thought after reading Yegor Bugayenko’s analysis of MVC vs OOP, and now I’m questioning whether Lucee would have been much better off by now if its community had not been led astray from OOP.

1 Like

Indeed, though I have never dabbled with MVC and I still have much to learn about OOP, my gut instinct has always been that MVC is only popular because it’s a brute force means for execs/managers to corrall inexperienced programmers into enforced separation of business logic vs presentation, and also because too few of them have made the effort to learn OOP.

The CFML community has resisted embracing OOP over the years, but let’s be very clear-- it wasn’t the “framework” crowd doing that. Every CF framework I can remember including FuseBox 4+, MachII, ModelGlue. ColdBox MVC, and FW/1 all encourage OOP design and most of those frameworks are built internally on OOP concepts (FW/1 being the notable exception). It was always the “I don’t need a framework because I’ve been coding procedural CF code for 20 years” crowd that struggled to embrace OOP.

As far as that article, I couldn’t disagree with it more. I’ve never heard of anyone considering MVC and OOP to be mutually exclusive! The “M” in MVC assumes you are using a model layer built of objects. The examples Yegor used also don’t really wash. His assertion that any native datatype coming out of a model is “naked” seems to assume the developers of the model wrote no documentation and the API docs don’t discuss return types, or that the developers of the controller are too stupid to read them.

component name="engine" {
  /**
  * Returns speed of engine in MPH
  */
  public numeric getSpeed() {}
}

There is no ambiguity here. The data (speed) is encapsulated inside a class until the point of use, in which case its value is clearly documented on the class’ getter method. You could return a Speed object which contained the numeric value, but now you’ve just kicked the can down the road since you still have to get the actual number from the Speed object. In Yegor’s example, he suggest this:

    new FormattedSpeed( // controller
      new SpeedFromEngine() // model
    )

But here his “controller” class also uses the same knowledge that the speed will be an integer representing MPH so he’s done the same thing, just in a different order. His assertion about code being “procedural” is a bit of a semantic game. ALL code is procedural to the extent that lines of code are executed one after another. The example also doesn’t even translate well to a proper MVC framework-- he just has three classes which he’s arbitrarily labeled M, V, and C.

In CF, your V is going to be a CFM file, not a class for starters-- if there’s one thing CFML does well, it’s templating as a first-class citizen. So at the end of the day, you’re passing something to the view. So it’s either going to be like this (borrowing Coldbox-esque patterns)

// controller
prc.speedMPH = engine.getSpeed();

and then your view does

<cfoutput>#prc.speedMPH# MPH</cfoutput>

Or, you could do this and pass the entire class instead of “naked” data:

// controller
prc.engine = engine;

and then your view does

<cfoutput>#prc.engine.getSpeed()# MPH</cfoutput>

So, now you’ve avoided Yegor’s so-called “naked” data, but you’ve also

  • scored a strike against the Law of Demeter by forcing your view to have more knowledge about the model
  • unnecessarily tied your view directly to the model’s API
  • Robbed your controller of the opportunity to do intermediate things like applying a caching layer to the data
  • Made the view less re-usable for a scenario in which the speed comes from the RadarGun class.

The name of the game with frameworks is to be low in coupling and high in cohesion. You can still have a robust model utilizing all the OOP principles you want and MVC is there to prevent coupling where you don’t want it, and encourage cohesion where it belongs.

In the CF world, the desire for MVC is usually driven by developers who understand their legacy spaghetti code is crap and they want organization that the whole team can understand that promotes maintainability and improves on-boarding new devs. MVC is not a replacement for OOP and OOP is not a replacement for MVC. I really don’t even understand how those two wires have gotten crossed here.

You (Lionel) recently said that the lack of uptake of CF Script was a detriment to the image of CFML in the greater community space. I agree with you there, and I’ll take it a step farther and say the lack of uptake in frameworks in the CF space is even more of a detriment to our image. :wink:

7 Likes

I moved this to a new thread. It is an interesting discussion, but far far off topic from the original post of the previous thread.

1 Like

Because they didn’t learn OOP? :stuck_out_tongue:

Lol, I don’t even know where you’re getting that. That’s like telling someone studying martial arts that the only reason they learned a system like Kempo or Taekwondo is because they never learned to lift weights. It’s a total non-sequitur. You lift weights to build and tone muscles. You learn a specific martial art to form a comprehensive system of patterns for how you fight. Sure, you can just lift weights and then go out on the street and flail your fists about-- you may even win some brawls, but being strong is unrelated to the system of fighting and self defense.

So with programming OOP is a set of low level design patterns of building up your code in which you enable re-use of business logic, encapsulation, and polymorphism via inheritance, interfaces, and composition of your basic re-usable unit: the class.

By the same token, FP (Function Programming) has a unit of reuse of a function.

CFML is considered a Multi-paradigm language, which basically means it has classical OOPs constructs, functional constructs (higher order functions) and procedural constructs (cfinclude, custom tags, etc).

A framework, however, enforces a set of high level conventions for how an app is structured on disk, how requests are routed, how security is applied, how errors are handled, how layouts are applied, and how external modules are loaded. Whether or not OOP code is used for any of this is strictly orthogonal, however, you’ll find the vast majority of MVC frameworks assume at least an OOP or FP approach to your code.

ColdBox MVC uses both OOP and FP internally so it would actually benifit the developer to have a solid understanding of these concepts first. That’s why our ColdBox master class covers basic OOP on day one! We teach it as part of the framework because you’ll do better if you have that understanding. Never is the framework a crutch to not learn the basics of the language.

1 Like

What I’m getting at is that because MVC solved their spaghetti code problem, they have much less incentive to learn OOP.

Brad, I am wary of the potential for confirmation bias since you are employed by Ortus, but I appreciate your detailed reply and I do see many other comments on Yegor’s article disputing his arguments. Then again, there’s a long history of so called heretics being vehemently opposed by those who are so deeply invested in the status quo. I need lots more time to digest and fully comprehend what both he and you have so thoroughly presented. :heart:

2 Likes

Holy crap! The comment section of that MVC vs. OOP post is ridiculous…

2 Likes

You should respond to it and maybe Yegor will add you to his hilarious list of haters! :sweat_smile:

The following is ad hominem so it doesn’t prove anything, but the Editorial Reviews for his books Elegant Objects Vol I & II caught my attention because one of them is our very own @bennadel!

“Yegor Bugayenko’s books, Elegant Objects I & II, show you how to correctly and elegantly implement the object concept in code; while all other books show you how to use code to warp and corrupt the object concept.” - David West, Author of Object Thinking.

“Probably the most practical book about OOP I’ve read so far.” - Anton Arhipov, Java Champion, Developer Advocate at ZeroTurnaround.

“I definitely enjoyed this book and will be re-reading it again soon.” - Ben Nadel, Co-founder at InVision.

“This book is amazing. It’s really changed the way I think of OOP. It’s very actionable and easy to understand,” says Andrew Shell.

“Well-written, entertaining, practical, bold and marginal at times.” - Eduards Sizovs, Co-founder of DevTernity.

“It is one of the best books if you have a lot of experience in different projects.” - Anton Chernousov, Founder of “The Art of Programming” podcast.

Also here is a full review from Ben published on his website in 2016:

I haven’t looked at the other article you’re all referring to yet, but I will say that Yegor has ideas that I both agree and disagree with. But, as with all things that I read, I simply try to take-away the parts that feel like they add value, and discard the parts that don’t seem relevant. The biggest mistakes that I’ve made in my career have been around trying to adopt something I read without understanding why I was adopting it and then subsequently not know why to change it later, or even how to properly maintain it.

For the most part, my ColdFusion code consists of cached, single-instances of Component that process the business logic procedurally. This is very simple, very easy to understand, and very easy to maintain. But, to be clear, the type of applications that I build are fairly low on the business logic. I think most applications are actually like that.

I’m actually in the middle of trying to build a little feature-flag system; and it’s the first time in a long time that I’m actually considering creating transient Components (as opposed to cached one). We’ll see how it goes.

4 Likes

I agree: comparing a design pattern like MVC with OOP sounds to me like comparing a cooking pattern recipe (e.g. that simplifies cooking) with cooking per se.

Oh dear, it seems his readers are prone to ad hominem fallacies instead of arguing against his points, lol. I tend to disagree with people in a much more civil manner which wouldn’t likely be worth of his wall of hate.

I’m with Ben on this. A great example would be Uncle Bob’s books like Clean Code. I think there’s some really good stuff, and some rather silly stuff in there. But all of it is worth at least considering why he suggests it and seeing how you can apply the concept, even if your outcome doesn’t match his.

As with Yegor’s post, I can see that code organization and separation of concerns are important for him which I can respect. That’s the mark of a good software engineer-- not just asking “does it work?”, but does it form a system which is consistent and well-maintained. He and I just have some very different viewpoints on what constitutes valid MVC and OOP patterns :slight_smile:

2 Likes

Maybe there’s a misunderstanding of his definition of “naked data” and other reasons why MVC allegedly violates OOP principles. Both arguments are better comprehended by simply following his links.

Perhaps, but I think I have a pretty good idea of what he means. There is general OOP advice that says good object design means you don’t get data from an object, perform an operation on that data, and then set it back in or do something else with it. Instead, ask the object to do it for you. This seems to be what he’s hitting at, though the issue is that axiom largely applies to so-called business logic, not presentation!. For example, instead of

if( car.getEngine().getType() == 'electric' ) {
  car.getChargerPort().charge();
} else if( car.getEngine().getType() == 'gas' ) {
  car.getFueldTake().fill();
}

Here you’re not allowing for polymorphism within the object because you’ve pulled out logic that belongs to the car. Instead, something like

car.reFuel( FuelFactory );

Now the details of the type of car and the differing behaviors are encapsulated inside the class. This is all well and good, but I think he takes it too far. There’s nothing wrong with getting raw data at some point from a class where you need it. Yegor seems to be a Java developer where EVERYTHING is a class, even his examples of rendering output involve objects. In CFML, we have an actual templating language, so if you want to output a value from class, there’s nothing wrong with getting that value and using it IMO. Calling it “naked” because it leaves the class is a little silly.

Like I said above, a class provides an API/contract for what data it will give you. His straw man argument of “what if we suddenly and randomly decide to change Fahrenheit to Celsius overnight” is just absurd. Firstly, you’d be a dick to do that to your coworkers by introducing a breaking change to the API of your class. And secondly, it’s a poor example because it would also break the toString() method in his example unless it was also updated. Also pretending all data rendering can be solved with a toString() method is a little silly as well. This is not a real world example. You don’t create a view by creating a class to represents the entire page on your website and then calling toString() on it. Pure insanity. This is the very definition of mixing presentation with data!!

No, we use a templating language called CFML tags, which live in a .cfm file, and need the “naked” data and should have no issues relying on the public API of a class to not have sudden breaking changes overnight. If APIs are broken without warning, that is a process issue within your programming team, not a lack of encapsulation.

I already discussed the first link, but it’s basically a copy of the blog post that started this thread, but he used an incredibly simplified example of outputting a temperature instead of an engine speed.

The second link is interesting, but not compelling. It seems he manages to keep nearly the the same code with only some semantic differences.

List<Apple> sorted = new Sorted(apples);
Apple biggest = sorted.get(0);

instead of

List<Apple> sorted = new Sorter().sort(apples);
Apple biggest = sorted.get(0);

I love theoretical discussions as much as the next guy, but this seems to be a huge exercise in overthinking things-- at least with no real tangible benefit outside of the class name. Yegor would seem to believe that every getter method is a break in encapsulation.

Take CFML as a language–it’s not Java. It’s designed with a few simple yet powerful “naked” data structures such as arrays, structs, and query objects. CFML is for rapid prototyping of web apps and much of its power lies in NOT making everything a complex object graph. I see Yegor’s points, but I have to temper it with the knowledge that I can build an app that is objectively easier to maintain by having my service pass an array of structs via my MVC’s request collection to the view instead of creating a complex system of objects working on objects that never allow the array to ‘escape’ into the real world.

I say, don’t be afraid of data. Don’t be afraid to get it and use it. The rule of thumb should not be a legalistic check of whether data is ever allowed to escape the object, but rather if data and behavior are sequestered in a manner that makes sense, creates a clean API, and promotes manageable code.

2 Likes

Ha, indeed he does! :smiley:

1 Like

Ha, that’s hilarious. I’m beginning to think he’s one of the internet’s best trolls. :rofl:

1 Like

That thought did cross my mind, but his resume is quite impressive (assuming it’s all true), the new “pure OOP” language he founded is compelling, and his philanthropy is refreshingly secular. :wink:

1 Like

On a related note, I found another critic of MVC: David Connelly. I’m curious what your take is on this, and if what he’s claiming is true (primarily the violation of DRY), does CodeBox solve that issue?

In addition to his video, David added this comment:

Not sure if anybody even watches these videos from start to finish but - just to say - my final ‘endpoint’ in this video is still not ideal. It’s not ideal because some modules are complex and they may require modules within modules. Therefore, the absolutely holy grail of web development structure would be as described at 18:30 but with the ability to have modules contained within modules. The only framework I can find that has this feature is Trongate - and it happens to have benchmarks that leave other leading PHP frameworks behind."

Full Disclosure: He appears to be the founder of Trongate (PHP framework they claim to be 20 times faster than Laravel).

1 Like