8 ms·
Everyone who has done MVC long enough would also know that the controller is the very thin layer where services are injected and models are passes to. The cont
by danielovichdk 7y ago
Everyone who has done MVC long enough would also know that the controller is the very thin layer where services are injected and models are passes to.
The controller should have and only have logic which absolutely cannot be moved to a service layer.
Too many developers use controllers as part of their logic layer, instead of simply using it as a router for where models should be directed on a service level.
- bryanlarsen 7y agoEvery Rails app I've seen has been MV, not MVC. The app/views directory contains the template part of the view code and the app/controllers directory contains the meat of the view code. You can tell that this is happening because there is a 1:1 mapping between foos_controller and views/foo. There's nothing wrong with MV code and it's a great paradigm for a simple app. But lots of rails apps are no longer simple...
- chao- 7y agoIn a Rails context, there are a dozen pattern-esque buckets that folks advocate putting non-template, non-persistence, non-validation logic into. Yet as often as seeing benefits from "service objects" or similar generic, I have also seen benefit from adding an actual View layer. Rails has done so much to move application development forward, but if I had two nits to pick, they are the same today as they were in 2007: 1. Assuming/requiring a folder structure named after the pattern an object fits, rather than conceptual domains of an application. 2. Naming its templates "views", and not hinting to people that presentational logic should belongs in a full instance of a class, rather than in-line in template code. Partials help but insufficiently, and helpers have too many gotchas. The sprawl of gems that attempt to address #2 this is evidence of its impact. While I appreciate the "omakase" argument, it still leads a lot of smaller or less-experienced teams to make a big mess before realizing they have better options. Anyway, as often as I see "service objects" solutions helping a team tame their Model-View-Mess, just as often I see the solution lying in adding an actual View layer (or adding Presenters if that fits better). I like ActiveRecord, ActiveRecord::Relation, ActiveSupport, and all the other things people tend to gripe about in Rails-land, but the specific folder structure has always been a stick in my craw.
- caymanjim 7y agoYeah, Rails confused an entire generation of developers by combining views and controllers into one messy, bloated, unencapsulated object, calling that a controller, and calling templates views. Rails models are also full of both view and controller logic, via validations, and full of higher-level business logic, and hacks to deal with the lack of a multi-model, transactional persistence layer. It's possible to implement a proper separation of concerns and clean architecture using Active* modules, but Rails actively encourages bad design. I still like Ruby, and there's a lot of good software within the Rails ecosystem, but Rails itself is poorly-architected and encourages bad design.
- deleted 7y ago[deleted]
- bcrosby95 7y agoI don't know, I err towards validation in or close to the model. You shouldn't be able to construct an invalid model and that usually involve the model validating the data you're passing to it. Rails certainly doesn't go about it in a great way though and tends to leak view based concerns into the model. How you achieve this depends upon the language. One thing I like to do in statically typed object oriented languages is to use classes for basic data rather than spread primitives everywhere. This makes it obvious where to put validation - e.g. the PhoneNumber class in the model will necessarily ensure the data its passed isn't bad. Repeating that logic in a controller or view tends to be a poor decision.
- elsurudo 7y agoI find the rest of Trailblazer a bit over-engineered and prescriptive, but I really like cells (http://trailblazer.to/gems/cells/ http://trailblazer.to/gems/cells/). IMO these are good for encapsulating view state. It more replaces the "helper" layer than controller layer, but it also helps you write controllers that just focus on HTTP stuff and nothing else (together with service objects, of course).
- hombre_fatal 7y agoAren't services just the DRYing up of controller code into functions? Like moving ad-hoc 3rd-party API code into a 3rdPartyApi.fetchItems() namespace? Or your inline database calls into a db namespace? Seems kind of a stretch to come up with a distinct name for such an elementary software design concept. Just like I think it would be silly to call the helper functions I write for my view layer "ViewServices", and then act like its some novel thing that the newbies aren't doing enough of.
- femiagbabiaka 7y agoWell yes. All (good) software design patterns are simple abstractions over basic SOLID principles. And of course simple here does not mean easy.
- tabtab 7y agoSOLID is subject to too much personal interpretation and language differences.
- jmull 7y agoNo, not just DRYing (at least, not in my opinion). There should be a real separation of concerns/division of responsibility. So the direct controller "only" coordinates the model, view, and services. I put it in quotes because there's still a lot in there (which should be organized as well): changes coming from the model, UI events from the views, and events from each of the services involved. Well, I guess you can call all of that DRYing, but it is definitely a deeper activity than just factoring out repeated code. There's real design to be done, to determine what the key concerns are exactly and how they compose to form your app. (Put another way: you can superficially factor out repeated code and still end up with a soup of interconnected services, controllers, models and views with a variety of communication mechanisms between them.)
- alexbanks 7y agoControllers abstract transport-layer functionality away from application logic. It's not really about "DRY" as it is about "Why should my services have to care about HTTP status codes?"
- oaiey 7y agoThat is right. And having service layer which dictates model changes, db ops and with its result a view change is pretty close here. This move pattern also reflects a bit the reflux idea of events and actions on models (with my limited redux knowledge).
- rcruzeiro 7y agoOne of the biggest problems with iOS development is that most of the official coding samples include quite a lot of logic inside the controllers (called a View Controller in Apple lingo) which in turn causes novice developers to assume this is the correct way of doing it. It's such a common thing to find in codebases that the iOS community calls this the Massive View Controller pattern. After people realise that the controller is actually the plumbing that just connects stuff, you can easily use MVC with services as described on the Eric Evans book for example and your codebase gets neatly organised, modular and testable.
- bsaul 7y agoit's not just code samples. i remember wwdc conferences at the time of ios3 where apple people used to officially say "we know it gets you worried, but having massive vc is actually just fine"
- jamil7 7y agoiOS architecture takes a bit of a while to feel out and see what works for you and your team. It's extremely overwhelming the last few years with how many alternative patterns are being pushed around and touted as the one true way.
- deleted 7y ago[deleted]
- megablast 7y agoOf course, since it is the easiest way to do it, and it makes sense. That is where viewdidappear, etc. is.
- emeraldd 7y agoYup, This is a pattern I've come to call MVCS. I want to see I saw that in a bit of documentation somewhere but I haven't been able to find it again. The C layer should be as thin as possible and have logic in it that pertains to routing and whatever kinds of transforms your "wire"/"transport" layer needs while the Services do all the heavy lifting and contain most of the business logic.
- j45 7y agoMVCS is a very nice way to describe this, especially for Dev teams that have to manage change but not need a new paradigm entirely. If you come across the doc I’d be happy to read it.
- jmull 7y agoAgreed! I describe it as MVC+S (same idea, just trying to highlight the S since it's routinely neglected).
- dmux 7y ago>The C layer should be as thin as possible and have logic in it that pertains to routing and whatever kinds of transforms your "wire"/"transport" layer needs while the Services do all the heavy lifting and contain most of the business logic. I believe Trygve Reenskaug (the inventor of MVC) would agree with this point. After MVC he went on to invent "Data, Context, Interaction" (DCI) [0], which aligns with what you're describing. [0] https://en.wikipedia.org/wiki/Data,_context_and_interaction https://en.wikipedia.org/wiki/Data,_context_and_interaction
- sfvisser 7y agoWhere a service could be something external or just a library, module, class or function. I always think service is a bit of vague term describing a bunch of related functionality packaged in some reusable abstraction so you don’t need to reimplement this logic every time high up in your app. But yes your comment makes sense. It also applies to the react world, where I have seen many apps with a ton of logic inside the lifecycle methods of react components. Lifecycle methods are the new controllers.
- abvdasker 7y agoYeah, the Rails community noticed this a while ago. Put the business logic doing transformations on models and interacting with external dependencies in service classes, which accomplishes three things: 1) Avoids bloating model objects. 2) Avoids creating complicated controllers. 3) Makes it much easier to move to a microservices architecture when the time comes, because business logic has already been grouped into isolated components. https://multithreaded.stitchfix.com/blog/2015/06/02/anatomy-of-service-objects-in-rails/ https://multithreaded.stitchfix.com/blog/2015/06/02/anatomy-... https://www.toptal.com/ruby-on-rails/rails-service-objects-tutorial https://www.toptal.com/ruby-on-rails/rails-service-objects-t...
- dep_b 7y agoI always say the Controller knows "what" not "how". But after a few years in iOS I kind of settled for a very fine-grained MVC pattern with Repositories, Reactive ViewModels and a separate Layout class per ViewController. Navigation is abstracted away but it's just a protocol implemented by a UINavigationController, nothing special. The ViewController doesn't do anything anymore except holding and wiring up the labels buttons etcetera and respond to events like viewDidLoad. Just chopping up every single part (even table view cells) into view controllers made everything so simple that not only Controllers are super thin and dumb but also ViewModels remain really thin, but not to the point where they start feeling like a unnecessary abstraction. Making a split between "more like a View" ViewControllers and UI code free ViewModels really helps, but I guess it's also the dirtiness of UIKit MVC that kind of forces you to abandon the ViewController.
- majormajor 7y agoI've rarely seen people fail to realize that having at on of code in a really fat layer is a problem. I've seen lots of people fail to separate that code in a clean and extensible manner. The result is a still-fat layer that's split across a bunch of different files and methods. But every piece is still concerned with almost every piece of context that was originally passed into the controller. Composability and separation of concerns are the answer, but it's much more of an art than something I've ever seen a simple tutorial for. It's gonna look different for different business cases.
- tabtab 7y agoRe: It's gonna look different for different business cases. Conway's Law rules. We need constructs that easily help us fit the stack to our teams and shop conventions. MVC allowed a shop to throw masses of people and code at a problem instead of removing the need for masses of people and code. The web made a mess out of CRUD app programming and MVC was a first step in taming the mess, but it requires fat staffing and lots of specialists to manage the screwy parts.
- jerf 7y ago"Everyone who has done MVC long enough... The controller should have and only have logic which absolutely cannot be moved to a service layer." Sorry, which letter in MVC is the "service layer"? One of the reasons I don't buy into MVC is that MVC doesn't mean anything any more, and hasn't ever since the web people got their hands on it. If you ask ten developers what MVC is and get 13 different answers (see half the sibling replies to this comment), well, that's not itself a problem, but it does mean that running around telling people that they should or should not do "MVC" has been pointless for a long time. I still like MVC for its original purpose: Multiple views in a CAD/CAM program. Makes perfect sense there. I don't think I've yet seen a place where it belongs other than that, though.
- nck4222 7y agoMVC does not comprise all layers of an application. You might as well be asking which layer represents the repository layer while you're at it. You can add other layers and frameworks in addition to using MVC. That doesn't mean MVC is pointless.
- samatman 7y agoThis strikes me as a good argument for the MOVE paradigm discussed in the Fine Article. It's quite possible, I would think, to define an entire application in terms of Models, Views, Operations and Events. I'd have to try it for awhile to determine if it's a good idea. It's pretty compelling however. I may give this a spin next time it comes up.
- wwweston 7y agoSeems to me that what people usually think of as the "Model" layer actually has "Operations", but we usually call them "methods." And "Events" is essentially Controller code. (There might be an argument that this describes a "fat" model vs some devs/frameworks choosing "thin" models that are just state rather than state + logic. )
- 7y ago
- jillesvangurp 7y agoThat and the notion that global variables or state are not a thing in modern software explains most failed UI projects built by juniors initializing things as global variables from controllers that also contain logic, layout, and other stuff that does not belong there (aka. an untestable & disgraceful mess). The same pattern applies to MOVE. Events are data and operations should do nothing else than hand off to a service layer; if it's more than 1 or 2 lines of code, it probably is mixing concerns and should therefore be refactored. Otherwise you just moved the problem (bad pun, sorry) and made it even harder to test because now your business logic is a side effect of an event that is processed asynchronously. Service layers are easy to test because it's just easily mockable constructor/initializer injected dependencies + a bunch of stateless functions that take input and produce output (and side effects). Classic mistakes here are to make the dependencies global variables and/or making the service layer initialization actually initialize dependencies.
- hinkley 7y agoWhere I've seen this done well, All of the data for rendering a view was pulled at the beginning of the action. The database transactions are over and done with, the cost of each request is very clear, and frequently caching is un-needed because you know that 3 different parts need the same data so you just give it to them instead of waiting for somebody to ask. There are a few frameworks that work this way, but many don't and developers have to constantly add caching layers to get anything done (and then spend tons more effort fixing cache invalidation well enough that nobody notices it's still broken)
- vbezhenar 7y agoUnless you'll re-use that service in another controller, it makes little sense to me.
- tus88 7y ago> Too many developers use controllers as part of their logic layer And views for their presentation and models for their data abstraction? The horrors!!
- jressey 7y agoThis simple concept pretty much bridges all design philosophies in practice. You have MVC and OOP, you have functional services, and you are free to create the appropriate amount of layers you need. To address another comment, MVC does not mean only MVC, it's just a framework that allows you to add layers where appropriate.