TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Controllers subdivision idea, subfolders & routing
  • Hi,

    I'm starting working on a new project and I'd like to experiment a way to separate each controller in 2 (or even more) different types: - one would handle the presentation layer (would be called 'Controller_X_UI'); - the other would do the processing ('Controller_X_Process').

    Usually I tend to put everything (form/ui & logic/processes) in the same controller, which can lead to pretty big (or not so small) files even though I try to implement as many controllers as my application logic commands. Especially if I go the ORM way, which amplifies code centralization in controllers with most of the database code embedded in.

    I don't know if the 'divide and conquer' strategy applied to these dedicated subcontrollers is a good design really, but I might find some interest in coding that way particularly by introducing inheritance in the loop. Each controller type would then inherit convenient member vars & methods from various parents dedicated to deal with user interfaces or data processing.

    The simplest way I could figure this out is by regrouping subcontrollers in subfolders. I tried to access Kohana urls that way (myAppRoot/x/ui/myForm, or myAppRoot/x/process/myProcess) but it doesn't seem to work (404). So I think I have to get my hand on Kohana's Routing mechanism to make it work. I quickly tried configuring the bootstrap so it would handle the url 'myAppRoot/x/ui/myForm' as 'myAppRoot/x/myForm' but I did not succeed.

    Maybe I'm heading the wrong way though. Before I spend more time on this, I'd like opinions on the whole idea. Sometimes when I start a project my brain simply gets stuck in 'tricky yet fancy... yet trick' ideas I think can be cool and elegant, but somehow I need a 'reality check' to realize it's gonna be a real pain in the arse handling on a day-to-day basis. Feedback/advice would be greatly appreciated. Cheers!

  • You should read http://zombor.github.com/

    Putting business logic into controllers (or even your framework layer) is not a good idea.

  • You should read http://zombor.github.com/

    Don't get me wrong the ideas aren't wrong, but the way you say some things are just very convenient lies or "opinionated truths".

    What follows are quotes from said blog posts

    [Your controllers should only know] How to send that data to your business classes

    This contradicts the premise from which you start your initial argument on.

    If the controller interacts in any way with the business logic then it is part of the business logic; because the business logic depends on it. In a very contrived crude example it's an relatively insignificant interaction so you can (in theory) ignore it, and pretend it's so easily replaced you can stick your business logic anywhere else (even though there's nothing really supporting that's necessarily true). Real world applications have complicated controllers and the controllers might be required to do sophisticated setup based on the http request in question; this means that either they have some meta business logic (so the business logic itself is missing some) or some of the http logic is passed down to the "business logic" (a little convoluted). Both of might be worse then just plain having the controller handle "this http-ish part of the business logic" and the other part "is pure business logic independent of http"—sounds simpler too.

    Technically, the business classes should know how to use a controller, so that the controller doesn't do any interacting; but this is such a unnecessary complexity to consider—if it works it's fine. Much like all the bitching about how you order your files (or name your files) it makes no damn difference at all.

    You can’t test [views created with php templates].

    You can test everything though browser controllers. PHP or whatever else works.

    Where do 90% of (frontend-centric) bugs occur? Ah yes when two things (that independently tested work perfectly) come together and long and behold mess each other up because god forbid anyone consider something else might be manipulating the same thing.

    [You gain] Logicless templates [by using mustache]

    You can't gain something you already (can) have easily with out them.

    Portable templates (you can reuse your same templates in both your server and client).

    You can always take those "reusable" parts (or refactor them out), pass them raw, and have javascript interpret them based on the pattern of php rather then mustache. <?= $variable ?> isn't exactly a complicated pattern to look for.

    Just forcing this very contrived and limited syntax on everything, for what is a net loss in time and effort, if you just have say 2 places in all your site of 40 pages that even make use of it, doesn't make much sense.

    “thin controller, fat model” approach [...], you will end up with an unmaintainable mess of an application.

    This might have been semi-true before the advent of traits, just because you had to do things in a very round about way to achieve the same effect. With traits this is invalid.

    The reason it's invalid is because when programming with traits your classes in an ideal situation (which is fairly easy to come by) are empty of methods. And this applies to all classes, so you would have something like "empty controller, empty model". The only time you would specify behavior is when the default trait behavior just doesn't cut it; so basically you only specify unique behavior; and it literally has to be unique to THAT class. As it happens the applications with a lot of unique code tend to be fairly small generally, while the applications with a lot of code tend to have high repetition (the more code you have, the more patterns emerge). So, you're either not writing much because you have less, or not writing much because it's much of the same.

    Either way, even though "maintainability" might go by different definitions, if it's just this much...

    pseudocode

    class Model_Person
    {
       use mysql_instantiation_method;
       use mysql_collection_methods;
       use sphinx_search_methods;
    
       const single = 'person';
       const multiple = 'people';
    
       $fields = [ 'given_name', 'family_name' ];
    
       function validator($input, $context)
       {
           ...
       }
    
    } # class
    

    It's pretty easily accepted as easy to maintain; just because it's so little code involved to do so much.

    (Also, might seem small but that "little" class can easily have 1000 methods depending on what the traits do.)

  • Continued from last post... (damn post limit)

    A framework of classes that easily let you redistribute your business logic (your application) in a format specific way, over a specific medium.

    You might wish to reword that. I understand what you meant, but from my understanding there are a lot of people that when you say "framework" will immediately assume "something that is calling my code" which obviously breaks (a) the whole notion that it is a separate mechanism (since you can't be an injectable mechanism while behaving as main) and (b) makes the notion of it being "replaceable" falsy, because you're "business logic" has to be built into it, since unlike a library, ie. something which you call, a framework only "might" have your business logic nice and clean; it's all really muddy and ambiguous.

    Probably "collection of classes" is better there.

    So where does your database access come into play in all this? A lot of frameworks make you think about the database entirely too early. The database is just a detail about where/how your data gets persisted.

    I see this view a lot but this is a very idealistic, as in unrealistic.

    The problem is simple: to have this "perfect" abstraction of persistence you have to have perfect abstraction of the structure of the data. And I do mean "abstraction", something like just translating notions like indexes to another language just doesn't cut it (because an index is not really "the data" per se). Unfortunately this whole abstraction business is so complicated you'd be effectively re-inventing it every time you would write a new application, since all your "translation to actually working code" would have to go somewhere—or you would have this very crappy and inefficient generic version.

    A way to cheat this (and what you do there) is to just pretend like the most dumb of dumb data, which completely ignores anything we might recognize in a modern database engine, is somehow representative of all use cases of the planet. Which it is not of course. Quite literally SQL might as well be this...

    SELECT * FROM table
    INSERT INTO table ( ... ) VALUES ( ... )
    UPDATE table SET ... WHERE ...
    

    (and I do mean literally just that)

    IMO, almost all languages have some limitation based on their design. I believe the whole abstraction of persistence to be one of those limitations, and I also believe the entire problem has already been solves (60 years ago), and the solution is the SQL language. What? it's language, and it's adept at persistence. Need to persist your crap on something else, just build bellow the SQL layer, not above the SQL layer. If you build above SQL, you're not getting rid of all the complexity, you're just pretending it doesn't exist (ostrich-syndrom; can't hide your head in the ground forever). You can of course just use a query builder if you want it to look more like your language; god knows you'll end with pretty much some other declarative solution anyway if you try to not use SQL.

    A repository class is an object that persists and retrieves data objects.

    All it's doing is converting longer calls to shorter calls (syntactically).

    As I mentioned before you're likely to just end up with a new adaptor for each and every model, your adaptor only looks different then your $this->_db because it's not complex enough. If you start joining data for example then either your adapter gains a new method for each or becomes more and more like the db class. The more it becomes a db class, the less of a "repository" (as you call it) it will be. In addition management of different adapters becomes more and more a pain in the ass. The only solution available to you seems to be to keep them all stupid, to have them all act the same.

    If you abstracted bellow the SQL layer, you would not have to create 1000 repository classes, or have a unique repository class for every (model, persistence) pair. You would just feed it in as the Database object, so 1 reusable implementation per your persistence-whatnot-nobody-ever-uses for life. Since it talks SQL, the model doesn't care; it's code still works fine as-is.

  • If the controller interacts in any way with the business logic then it is part of the business logic; because the business logic depends on it.

    This isn't true at all. The delivery mechanism is a plugin to the business logic. The business logic does not IN ANY WAY depend on the controllers. The controllers depend on the business logic. This is the correct flow of control we are looking for. Trust me, I have working applications designed in this manner. The results are fantastic. My tests run very fast.

    You can test everything though browser controllers. PHP or whatever else works.

    And your tests will be slow as molasses. Testing your entire application through a browser is just about the worst possible thing you can do.

    I see this view a lot but this is a very idealistic, as in unrealistic.

    It's not. Again, I've developed successful applications in this manner.

    This might have been semi-true before the advent of traits, just because you had to do things in a very round about way to achieve the same effect. With traits this is invalid.

    We've had traits in languages for MANY years. They are used for horizontal inheritance and they don't really solve the fat model approach or make it any better. Fat classes are simply bad.

    Since it talks SQL, the model doesn't care;

    So you are going to convert SQL to syntax MongoDB or CouchDB or Neo4J can understand? Good luck with that.

    You can put your hands over your ears and scream "LALALALALALALA" all you want. The manner I've described is an established and proven way to design maintainable software systems. Of course, there are other methods as well. I'm not claiming what I describe is the only or even the best way.

  • the meaning of business logic is too vague in my opinion. If business logic is function which used many times, I agree business logic should be in Model and it should be tested by Unit test. However I have seen many cases that many function in Model used by only one controller. I could not find any advantage of this. There for I choose single action per controller pattern. http://forum.kohanaframework.org/discussion/11985/single-action-per-controller#Item_11

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion