Go Back   SitePoint Forums > Forum Index > Program Your Site > PHP > PHP Application Design
Newsletter FAQ Members List Calendar Mark Forums Read

New to SitePoint Forums? Register here for free!

SitePoint Sponsor
 
Reply
 
Thread Tools Display Modes
Old Jan 29, 2004, 23:24   #1
mwmitchell
SitePoint Guru
 
Join Date: May 2003
Location: virginia
Posts: 993
Class Methods as Request Actions in MVC

I recently checked out Ismo and liked the idea of having a class, that handled requests, that were all related to the model/application. A lot of times, I have action classes that have a few lines, and it's more of a pain to open them up and change things. With all of them in the same class, it seem like it would be easier to handle small to medium sized classes (action groups).

I built my own mini version, that handles views differently. Each action returns the type of view (success, init, fail etc...), the application controller intreprets it, and loads the correct view class. But the view class is set up the same way. It's a class that uses it's methods for the different types of views. so if your action class was called 'ProductAdmin_controller', and returned a view of 'add_success', the view class would be 'ProductAdmin_viewer' and the method in the view class would be 'view_add_success()'. I really like the way it all feels, and it's easy to see what's going on throughout the code.

Does this present any problems that I'm not seeing? How would you handle alternative content using this method?

Matt
mwmitchell is offline   Reply With Quote
Old Jan 30, 2004, 01:18   #2
dagfinn
SitePoint Guru
 
dagfinn's Avatar
 
Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
Quote:
Originally Posted by mwmitchell
I recently checked out Ismo and liked the idea of having a class, that handled requests, that were all related to the model/application. A lot of times, I have action classes that have a few lines, and it's more of a pain to open them up and change things. With all of them in the same class, it seem like it would be easier to handle small to medium sized classes (action groups).

Matt
I've also used what you call "action groups", and I like it. It's easy to refactor. Typically related commands will have some duplicated code, and you can deal with that by extracting methods and classes.
dagfinn is offline   Reply With Quote
Old Jan 30, 2004, 02:31   #3
mdsjack (ITA)
SitePoint Member
 
Join Date: Jan 2004
Location: Bologna (ITALY)
Posts: 7
hi, i'm interested in what you say...

will you paste here an example, please?

tnx.
mdsjack (ITA) is offline   Reply With Quote
Old Jan 30, 2004, 02:45   #4
prefab
SitePoint Zealot
 
prefab's Avatar
 
Join Date: Jan 2003
Location: Belgium
Posts: 133
Being involved in the development of Ismo, I would suggest the following approach: create your Ismo_Core_State_HTTP as usual. I think it might not be clear from the current documentation (it's being rewritten: http://ismo.sourceforge.net/manual/), but if your execMethod returns a string that corresponds to a show<string> method within the state, that view is executed (of the view returns a string also, show<string> is executed recursively: showHeader > showBody > showFooter). You pass your model to the view indirectly to the view through a property.

To further use the Ismo state approach, you can now take advantage of pre- and post- methods (see docs), which let you add a usefull common layer to a baseState for example. On top of that, we're working on an AOP like approach where you can have specific aspects and global aspects.

- prefab

PHP Code:

<?php


require_once('Ismo/Core/State/HTTP.php');

class
example extends Ismo_Core_State_HTTP
{

    var
$nsModel; // the model property

    
function example()
    {
        
parent::Ismo_Core_State_HTTP();
    }

    function
execDefault()
    {
        ....
        ....
        return
'welcome';
    }

    function
showWelcome()
    {
        echo
"<h1>Welcome</h1>";
    }

    function
execEdit()
    {
        ....
        ....
        ....
        return
'success';
    }

    function
showSuccess()
    {
        echo
"<h1>Done</h1>";
    }

}

?>
Now, if you were to use seperate view classes instead, one could do this:

PHP Code:

<?php


require_once('Ismo/Core/State/HTTP.php');
require_once(
'Ismo/Core/View/Loader.php'); // pseudo code

class example extends Ismo_Core_State_HTTP
{
    
    var
$nsModel;

    function
example()
    {
        
parent::Ismo_Core_State_HTTP();
    }

    function
execDefault()
    {
        ....
        ....
        return
'welcome';
    }

    function
execEdit()
    {
        ....
        ....
        ....
        return
'success';
    }

    function
_showMethodMissing($name) // overrides the basic method saver
    
{
        
// this is not ready yet, so pseudo code ahead
        
$view = &Ismo_Core_View_Loader::factory($this->_stateName);
        if(
is_object($view) && is_a($view, 'ismo_core_view_plain')) {
                
$view->setModel($this->nsModel); // hand over the model
                
$view->execute($name);
        }
    }

}

?>

<?php

require_once 'Ismo/Core/View/Plain.php';

class
exampleView extends Ismo_Core_View_Plain {

        function
showWelcome() {
                echo
'<h1>Welcome</h1>';
        }

        function
showSuccess() {
                echo
'<h1>Done</h1>';
        }

}

?>
prefab is offline   Reply With Quote
Old Jan 30, 2004, 09:51   #5
Captain Proton
SitePoint Guru
 
Join Date: Oct 2001
Posts: 666
What you are saying does not go against the MVC principle. However, I think that it looks very 'procedural', you could hardly call it really object oriented.

Ismo_Core_State_HTTP subclasses are really just a namespace with functions disguised as an object with methods. For large 'action groups', there could be a dozen or more exec_myaction() methods, one for each action of the application. That means that one class is trying to do way too much, it is bloated and it really is just a 'procedural class'.

What is wrong with one object for each action of the application? Call it an Action or ActionController or whatever you want to call it. You gain the advantage of small and simple classes, you can use inheritance, composition, and all the other benefits of OOP. You can't do that with a class like Ismo_Core_State_HTTP.

There are other ways to group "action groups" together.

PS, the prodecural class thing is even an anti pattern, I just can't find the link for it..
Captain Proton is offline   Reply With Quote
Old Jan 30, 2004, 10:35   #6
prefab
SitePoint Zealot
 
prefab's Avatar
 
Join Date: Jan 2003
Location: Belgium
Posts: 133
Quote:
Originally Posted by Captain Proton
What is wrong with one object for each action of the application? Call it an Action or ActionController or whatever you want to call it. You gain the advantage of small and simple classes, you can use inheritance, composition, and all the other benefits of OOP. You can't do that with a class like Ismo_Core_State_HTTP.
I beg to differ. Ismo_Core_State_HTTP is more than a 'namespace' for grouping actions together. Ismo_Core_State_HTTP extended classes are real classes and its instances are 'real' objects. This means you have all of the benefits of OOP at your disposal. In fact, the first thing you should do is subclass Ismo_Core_State_HTTP to setup your base state(s). From there you proceed with your specific logic. That way you have a common layer, which you usually require anyway. It allows you to share a certain behaviour throughout the state or even throughout any state you subclass.

The goal is to use composition and inheritance to share behaviour while letting you override it if necessary. The key is to discern into which parts you should split and group that behaviour. That way you avoid states that try to do too much. With the new developments, it should become clear that the object nature of states is a powerfull, yet easy to use, concept.

- prefab
prefab is offline   Reply With Quote
Old Jan 30, 2004, 11:27   #7
mwmitchell
SitePoint Guru
 
Join Date: May 2003
Location: virginia
Posts: 993
Too me it still looks like OOP. But I find myself learning from people here everyday, always realizing that I don't know much. So this only my opinion and my way of thinking at this point.

If you look at most examples/tutorials for OOP, they all use example, real world objects. Like the car example. The car example shows that each of the cars 'actions' are grouped within the car. If you want to go faster, you would ask the car to go faster. That's how I'm seeing the Ismo approach.

With the other approach (a class for each action) it seems to me that you would call a ChangeSpeed object, that would ask the car to go faster. Which may be more clean and separated. But could be overkill depending on what you are doing. Right?

I created an application last night that would allow you to CREATE a 'product', EDIT the product and DELETE. And of course VIEW all products. I had an action class for each one. And a view class for each one. That's 8 classes. It seemed like a lot of code, and I always feel proud to look lots of lines of code, that actually works and makes sense. But then I converted it all to the Ismo method, and I was amazed at how small it all was, and I could make sense of everything at once. It was so much easier to look at and read.

But I still want to know what the possible side effects are? I mean I know with everything in life, there are trade-offs

Matt
mwmitchell is offline   Reply With Quote
Old Jan 30, 2004, 11:43   #8
sweatje
eschew sesquipedalians
silver trophy
 
sweatje's Avatar
 
Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,779
Quote:
Originally Posted by mwmitchell
I created an application last night that would allow you to CREATE a 'product', EDIT the product and DELETE. And of course VIEW all products. I had an action class for each one. And a view class for each one. That's 8 classes. It seemed like a lot of code, and I always feel proud to look lots of lines of code, that actually works and makes sense. But then I converted it all to the Ismo method, and I was amazed at how small it all was, and I could make sense of everything at once. It was so much easier to look at and read.
BTW: The technically correct acronym to use when expressing this concept is CRUD (Create,Retrieve,Update,Delete)
sweatje is offline   Reply With Quote
Old Jan 30, 2004, 12:31   #9
Captain Proton
SitePoint Guru
 
Join Date: Oct 2001
Posts: 666
Quote:
I beg to differ. Ismo_Core_State_HTTP is more than a 'namespace' for grouping actions together. Ismo_Core_State_HTTP extended classes are real classes and its instances are 'real' objects. This means you have all of the benefits of OOP at your disposal. In fact, the first thing you should do is subclass Ismo_Core_State_HTTP to setup your base state(s). From there you proceed with your specific logic. That way you have a common layer, which you usually require anyway. It allows you to share a certain behaviour throughout the state or even throughout any state you subclass.
Alright, but it is still comparable to a namespace, even though it subclasses are instanciated as real objects.

But you cannot deny that Ismo_Core_State_HTTP is a class that basically has a function for everything that can be done with a part of the application's domain. Like sweatje says, it's responsible for the CRUD of something that is (usually) related to a single database table.

Quote:
Too me it still looks like OOP.
Exactly, it looks like OOP and it is very easy to grasp the concept of how it works, because it is in fact procedural code disguised in a class and that is what most programmers are familiar with.

When people coming from a procedural programming (PP) background and switch to OOP, they often group together a lot of functions from a procedural library into a class as methods. It seems logical and it is an easy conceptual step to make from the PP code to the OOP code, because the methods on that class areof an object look a lot like procedures. Because it looks so understandable when you relate it to PP, it seems like it is "the right thing".
Quote:
But then I converted it all to the Ismo method, and I was amazed at how small it all was, and I could make sense of everything at once. It was so much easier to look at and read.
Like you said, you're new to OOP, and the structure of the code that you make in ismo looks very understandable and familiar, because you are thinking procedurally. That is not meant as an insult or anything, it's a very understandable thing in fact. When I first started to use some OOP in my scripts, I did the exact same thing. I created Modules, very comparable to Ismo's states, with methods like addNews(), editNews(), deleteNews(), listNews(), etc: CRUD objects. That lead to classes that sometimed spanned over 400 lines of code! Now that is by definition a bad code smell: one class trying to do waay to much, split it up into larger classes.

If you split each ismo State with methods for each action into an Action object for each action, you will see that you will have lots of small classes that are focused on only one part of the CRUD. Of course there will be the problem of duplicated code at first. With Ismo's State classes, you can simply wrap this duplicated code inside a method on the State class that can be called by all action methods, if needed. Very easy to do, very logical but also very procedural. It's just like a library of PP code where one function calls another helper function to execute code that is common to more than one function.

So how do you handle this when you want to split the large State class into multiple Action classes? You can either make smart use of inheritance or of object composition. Inheritance is the easiest solution. Say you have these classes: AddNewsAction, EditNewsAction, DeleteNewsAction, ViewNewsAction. AddNews and EditNewsAction have a lot of functionality in common, they must both insert or update to the database, validate the fields submitted via a form, etc. You could create a parent class for the AddNews and EditNews actions, like ManipulateNewsAction. This would be an abstract base class.

Of course each CRUD section of your application will also have a lot of common behaviour. Each Add[something]Action will follow the same steps (validating, redisplaying form, saving to database, etc) so you can even create a base class for all add actions and one for all edit actions: BaseAddAction and BaseEditAction. Now, these classes will also have common functionality, like all Add and Edit actions, so you can create a parent class like BaseManipulateAction.

Try doing something similar in Ismo without stuffing lots and lots of common methods inside parent God classes. It will lead to bloated classes that are responsible for way too many things.

Just found something. This anti-pattern is called The Blob on [url=http://www.antipatterns.com/dev_cat.htm[/url]this site or God Class here.

Well, I hope my attempt at convincing you has at least partially succeeded. In any case, I think it's always good to discuss things
Captain Proton is offline   Reply With Quote
Old Jan 30, 2004, 12:54   #10
Captain Proton
SitePoint Guru
 
Join Date: Oct 2001
Posts: 666
Here's an example that (I think) demonstrates how Ismo State objects are simply a library of functions disguised as an object.

First here we have the procedural code. A file with a switch statements and a function responsible for each 'Action'. I believe this will look familiar to a lot of PHP programmers. It is how I structured my 'large' programs, with one of these files for each CRUD section of my application.
PHP Code:

function exec_add() { ..... }

function
exec_edit() { .... }

switch (
$_GET['action'])
{
    case
'add':
        
exec_add();
        break;
    
    case
'edit':
        
exec_edit();
        break;
}
Now compare this with the way Ismo does this:
PHP Code:

/**

* This class is basically the switch statement in the procedural example.
* I know it does a lot of other important things
* but those are not really important for proving my case
**/
class IsmoApplication
{
    
// Get a state object somehow
    
$state = ...;
    
    
// I know this is simplified, but it is the core of what's going on.
    
$method = 'exec_' . $_GET['action'];
    
$state->$method();
}

/**
* This is the file responsible for a CRUD section, except that now it has got a
* class statement around it.
**/
class SomeIsmoStateSubclass
{
    function
exec_add() { ... }
    function
exec_edit() { ... }
    function
exec_whatever() { ... }
}
See the similarity between the two?
Captain Proton is offline   Reply With Quote
Old Jan 30, 2004, 13:44   #11
mwmitchell
SitePoint Guru
 
Join Date: May 2003
Location: virginia
Posts: 993
Captain Proton,

I do see what you are saying and I appreciate your input. This is exactly why I posted this topic

So, the thing that I'm not sure about is how they can be 'god' classes when they are usually dealing with only one model. With only 3-4 methods. And so far, I see all of the signs of being object oriented. Inheritance, Polymorphism, Overriding methods, Composition. I would think that it would be more up to the programmer on whether or not it would be a bloated action class. And the same for whether or not the methods contain a lot of procedural code.

In your example with the switch statement, that looks more like an example of a front controller possibly? In frameworks that have seperate action classes for each request, there is still that same logic happening somewhere within the front controller right? They are just calling a class method instead of a function (like in your example).

Also, with these state classes, they are all working with class variables. For instance the same model is being manipulated via the methods. That's another sign of it being OOP right?

Ha, I'm not sure if I should even being going out on a limb like this! But I figure this is the best way to learn. Also, I'm not sure if I was trying to figure out if this is OOP or not. I guess more if it presents any unforeseen problems. Regardless... Your arguments are valuable to me.

Matt
mwmitchell is offline   Reply With Quote
Old Jan 30, 2004, 14:14   #12
dagfinn
SitePoint Guru
 
dagfinn's Avatar
 
Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
(My comment are not based on Ismo, which I've only looked at briefly, but on my own "framework" which appears to be similar.)
Quote:
Originally Posted by Captain Proton
Alright, but it is still comparable to a namespace, even though it subclasses are instanciated as real objects.
I agree with you that it's basically just a function library wrapped inside a class, but I don't necessarily think that's a bad thing. I don't think we should rule out the possibility that procedural code is sometimes the best solution.

Quote:
Originally Posted by Captain Proton
Like you said, you're new to OOP, and the structure of the code that you make in ismo looks very understandable and familiar, because you are thinking procedurally.
I'm not new to OOP, and I still prefer it. Not because it looks familiar, but because I find it easy to refactor.
Quote:
Originally Posted by Captain Proton
With Ismo's State classes, you can simply wrap this duplicated code inside a method on the State class that can be called by all action methods, if needed. Very easy to do, very logical but also very procedural. It's just like a library of PP code where one function calls another helper function to execute code that is common to more than one function.
Again, you're right that it's procedural, but that's OK by me if it's the simplest design that works. I'll extract classes from it, too, but only if the code is telling me to do so.

Quote:
Originally Posted by Captain Proton
So how do you handle this when you want to split the large State class into multiple Action classes? You can either make smart use of inheritance or of object composition. Inheritance is the easiest solution. Say you have these classes: AddNewsAction, EditNewsAction, DeleteNewsAction, ViewNewsAction. AddNews and EditNewsAction have a lot of functionality in common, they must both insert or update to the database, validate the fields submitted via a form, etc. You could create a parent class for the AddNews and EditNews actions, like ManipulateNewsAction. This would be an abstract base class.
I admit I've never tried exactly this approach to this problem. But from your description it looks unnecessarily complex to me. It seems you are using inheritance and composition, and probably Template Method to do something which would be simpler with plain method calls.

You see, I believe that when I start out with the quasi-OO class and refactor to remove duplication, I'll end up with a simpler design that if I add complexity to begin with by making all those classes. But I realize I won't be 100% sure until I try both with the same code and compare the two.
dagfinn is offline   Reply With Quote
Old Jan 30, 2004, 17:04   #13
tyrak
SitePoint Member
 
tyrak's Avatar
 
Join Date: Jan 2004
Location: Middle Finland
Posts: 2
It seems to me that the approach Captain Proton advocates is the way the Struts framework (the leading Java web application framework, http://jakarta.apache.org/struts/) works. However, Ismo's design resembles more the WebWork framework (another not so leading Java framework, http://www.opensymphony.com/webwork/) which obviously makes it different.

The major principle of WebWork is the ease of use, which makes it possible to be very productive right from the beginning. The small concentrated API is quick to grasp yet extendable and powerful when used correctly.

It is hard to say which way is the better one as there are zealots in both camps arguing that theirs is the right one...

It can be argued that the Struts approach is purer OOP, and that WebWork is more pragmatic. However, in my opinion idealistic OOP is something to aim for but good enough OOP can be a reasonable compromise.
tyrak is offline   Reply With Quote
Old Jan 30, 2004, 17:46   #14
seratonin
SitePoint Evangelist
 
Join Date: Dec 2003
Location: Arizona
Posts: 418
The Struts Framework uses the Command Pattern as Captain Proton has described, however, Struts also has a class named DispachAction which is an Action class that has it's methods invoked via reflection. From the API documentation:

Quote:
This Action is useful for developers who prefer to combine many similar actions into a single Action class, in order to simplify their application design.
It seems to me that the Command Pattern would appeal more to the OO purist and this method would appeal more to the procedural programmer.

Here is a link if anyone is interested: http://jakarta.apache.org/struts/api/index.html.

JT
seratonin is offline   Reply With Quote
Old Jan 31, 2004, 00:10   #15
dagfinn
SitePoint Guru
 
dagfinn's Avatar
 
Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
Quote:
Originally Posted by prefab
To further use the Ismo state approach, you can now take advantage of pre- and post- methods (see docs), which let you add a usefull common layer to a baseState for example. On top of that, we're working on an AOP like approach where you can have specific aspects and global aspects.
I have the equivalent question to this as to Fowler's claim that the Command pattern with one class per command is good for adding common behavior. Why use pre- and post-methods instead of just adding the code at the beginning or end of the exec method? Can you give me an example, not just of how it works, but of how it's useful?
dagfinn is offline   Reply With Quote
Old Jan 31, 2004, 01:02   #16
prefab
SitePoint Zealot
 
prefab's Avatar
 
Join Date: Jan 2003
Location: Belgium
Posts: 133
Quote:
Originally Posted by dagfinn
I have the equivalent question to this as to Fowler's claim that the Command pattern with one class per command is good for adding common behavior. Why use pre- and post-methods instead of just adding the code at the beginning or end of the exec method? Can you give me an example, not just of how it works, but of how it's useful?
Of course you would add the code within the execMethod if it were unique to that particular action. If it's an action that has a certain behaviour in common with (all) the other actions of that state, the (global) preExec and postExec methods are the right place to put it. Especially if you are defining a base class, it's logical to put it there, since the subclass shouldn't have to call it explicitly IMHO. If you're familiar with Ismo's _exposeDefaultVariables(), it's similar, in the sense that it's used to clearly setup the state-wide behaviour.

You could setup some other objects in preExec; a template engine and some global template variables for example. Another use is to setup a page caching mechanism, where preExec would check for a cached version. If there's a cached version, the action wouldn't get executed, but the cache would be served. If not, preExec starts the buffer, the action is executed, while postExec saves the buffer to disk. (note that you could alternatively use preShow/postShow if the task needs it). Remember that you're not forced to use it, you can do and use whatever you like, since Ismo doesn't prescribe anything. In fact, it's our philosophy.

There are two types of preExec/postExec methods, global ones, and specific ones. The specific preExec<action> and postExec<action> methods are especially usefull if you have simillarly named actions throughout the states. The usefullness becomes apparent when you apply (global) aspects to states. The state is completely unaware of the aspect, while the aspect let's you perform 3 basic techniques: preprocessing (preExec/preShow), postprocessing (postExec/postShow) and overriding the method entirely (you can also add actions/methods at will). You can imagine that this is quite powerfull. So to implement the examples above one could just create an aspect for that behaviour (you can apply multiple. ordered, global state aspects) and let the Application handle it (currently, the Application interacts with a factory class that will supply aspects if defined). This is not taken from thin air, as it's currently implemented (as a draft) and working wonderfully.

- prefab
prefab is offline   Reply With Quote
Old Feb 1, 2004, 04:22   #17
Captain Proton
SitePoint Guru
 
Join Date: Oct 2001
Posts: 666
Quote:
It seems to me that the Command Pattern would appeal more to the OO purist and this method would appeal more to the procedural programmer.
Fully agreed here, but that is because the Command pattern is more object oriented. But forget about Struts, it's for Java and following it's principles blindly leads to IMHO frameworks that don't work very well for PHP *caugh*.. Phrame.. *caugh*

The Ismo State class is just asking to be decomposed into several smaller classes. From the last paragraph of the previous post, I have assumed that it is possible for an Ismo_State subclass to look something like the below code. I admit that it might be a worst case scenario, but you have to admit that from your own description it is made possible, right?
PHP Code:

class Ismo_State

{
    function
preExec_add() { .. .}
    function
preExec_edit() { ... }
    function
preExec_delete() { ... }
    function
preExec_list() { ... }}
    
    function
preShow_add() { ... }
    function
preShow_edit() { ... }
    function
preShow_delete() { ... }
    function
preShow_list() { ... }
    
    function
exec_add() { ... }
    function
exec_edit() { ... }
    function
exec_delete() { ... }
    function
exec_list() { ... }    
    
    function
postExec_add() { .. .}
    function
postExec_edit() { ... }
    function
postExec_delete() { ... }
    function
postExec_list() { ... }}
    
    function
postShow_add() { ... }
    function
postShow_edit() { ... }
    function
postShow_delete() { ... }
    function
postShow_list() { ... }
}
That is one class with over 20 methods that all do something else! Now you try to convince me that this is not a bloated class and that it does "only one thing and is good at that one thing" according to OOP filosophy.

The Ismo_State class is literally asking to be split into several classes! Instead of one State class with over 20 methods, what about 4 Action classes with only 5 methods each?
PHP Code:

class Ismo_Action

{
    function
preExec() { ... }
    function
preShow() { ... }
    function
exec() { ... }
    function
postExec() { ... }
    function
postShow() { ... }
}
This is the way the Ismo_State class would be done in OOP, period.

I'll even try it from another perspective, that of object oriented analysis. That is the process of identifying the objects that make up a system.From your own wiki:
Quote:
A state is a logical grouping of actions. And an action is one function invoked by the application user. For example, an action can be add, preview or update and these kinds of actions could maybe belong to a forum posting state.
What are the objects you can identify from this text? State, Action and Application User. Application User is not relevant here, so what remains are State and Action. So why do you completely forget about the Action object and put all of it into a State object? Exactly, because it is such an easy step to make from procedural coding.
Captain Proton is offline   Reply With Quote
Old Feb 1, 2004, 06:28   #18
dagfinn
SitePoint Guru
 
dagfinn's Avatar
 
Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
Quote:
Originally Posted by Captain Proton
The Ismo_State class is literally asking to be split into several classes! Instead of one State class with over 20 methods, what about 4 Action classes with only 5 methods each?
I agree with you that the Ismo_State class looks bloated, but I think that's a different discussion than the Command vs. Command Group discussion. That is, whether you have one command per class, or several. The Command Group pattern (it's a pattern if it's been used three times, and this one apparently has) doesn't require a bloated superclass. My implementation of it has no superclass at all. It might require a superclass at some later time, but so far I haven't seen a need for it.
dagfinn is offline   Reply With Quote
Old Feb 1, 2004, 07:02   #19
mwmitchell
SitePoint Guru
 
Join Date: May 2003
Location: virginia
Posts: 993
I can see how that would get a little overly complex for one class yes. What do you think, if (for example) the command class held only the execute methods. Those methods return a view name (string) and then the controller (framework) would then get the view class needed according, and call the appropriate showMethod()? The view class would be completely separate.

Matt
mwmitchell is offline   Reply With Quote
Old Feb 1, 2004, 09:08   #20
tyrak
SitePoint Member
 
tyrak's Avatar
 
Join Date: Jan 2004
Location: Middle Finland
Posts: 2
Quote:
Originally Posted by Captain Proton
That is one class with over 20 methods that all do something else! Now you try to convince me that this is not a bloated class and that it does "only one thing and is good at that one thing" according to OOP filosophy.
I disagree, the Ismo_State class can be made bloated, however, if used correctly that will not be the case.

You show a class having 20 methods, and even though that is possible, it is indeed something to be frowned upon. The intended usage is more along the lines of:

PHP Code:

class BaseState extends Ismo_Core_State_HTTP

{
    
// base state for the application
}

class
CachingState extends BaseState
{
    function
preExec()
    {
        
// cache if not cached otherwise show cached version
    
}

    function
postShow()
    {
        
// save output in cache
    
}
}

class
ShowLatestPostsState extends CachingState
{
    function
execDefault()
    {
        return
$this->execShow();
    }

    function
execShow()
    {
        
// retrieve and show the latest posts
    
}
}
However, if one still wants to have each action in an own class it is possible to get that kind of behaviour by overriding the Ismo_Core_State_HTTP::execute() method in for example a BaseState class. This might seem like an overly complex way to get Ismo to work in your desired way, but as I tend to prefer having multiple action methods in one state class adding better support for action classes is not one of my priorities. Patches for this is gladly accepted


To support show/view classes one has to currently override the Ismo_Core_State_HTTP::_showMethodMissing() method as prefab described in an earlier post. Patches to better to support this would also most certainly be applied.


Captain Proton, I agree with you that using action classes is better OOP. But in my opinion using action methods in the state classes is a reasonable compromise. It gets the job done in an easy and efficient manner. Yes, it's procedural, but so what? I've been using OOP for six years now and I've come to understand that OOP is not always the best solution.

I hope that in the future the Ismo framework will have the same amount of built-in support for both alternatives and a developer using Ismo can then freely choose which alternative to use, or use both! For example go with the action methods approach for states having just a few simple actions, and use action classes for the states with many complicated actions.
tyrak is offline   Reply With Quote
Old Feb 1, 2004, 09:24   #21
Captain Proton
SitePoint Guru
 
Join Date: Oct 2001
Posts: 666
Ok, then let's settle the argument by saying that we're both following different philosophy's in our frameworks
Captain Proton is offline   Reply With Quote
Old Feb 1, 2004, 12:12   #22
dagfinn
SitePoint Guru
 
dagfinn's Avatar
 
Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
Quote:
Originally Posted by tyrak
Captain Proton, I agree with you that using action classes is better OOP. But in my opinion using action methods in the state classes is a reasonable compromise. It gets the job done in an easy and efficient manner. Yes, it's procedural, but so what? I've been using OOP for six years now and I've come to understand that OOP is not always the best solution.
I might add that Fowler's Table Data Gateway pattern from PoEAA is similarly procedural.
dagfinn is offline   Reply With Quote
Old Sep 15, 2004, 02:49   #23
McGruff
simple tester
 
McGruff's Avatar
 
Join Date: Sep 2003
Location: Glasgow
Posts: 1,685
Quote:
Originally Posted by dagfinn
You see, I believe that when I start out with the quasi-OO class and refactor to remove duplication, I'll end up with a simpler design that if I add complexity to begin with by making all those classes.
Here's an interesting link about that: http://www.refactoring.be/thumbnails/cycle/cycle.html.
McGruff is offline   Reply With Quote
Old Sep 15, 2004, 04:56   #24
kyberfabrikken
SitePoint Mentor
silver trophy
 
kyberfabrikken's Avatar
 
Join Date: Jun 2004
Location: Copenhagen, Denmark
Posts: 5,915
doing some sitepoint archeology here, are we ?

what did dagfinn btw mean by
Quote:
Table Data Gateway pattern from PoEAA is similarly procedural
it is obvious that querying a RDB has to be procedural at some point, or ?
kyberfabrikken is online now   Reply With Quote
Old Sep 15, 2004, 06:23   #25
JaskaS
SitePoint Enthusiast
 
Join Date: Jul 2004
Location: Finland
Posts: 73
All ideas seems to be taken already. I have made almost similar "Action group" system (I was inspired by Delphis Action system. Never heard about Ismo before.), and I've been quite happy how it works in practice. But it's still under developemen.

Here's a little example.

PHP Code:

class Controller_formviewer extends JMVC_ActionController{


//initialize variables, register action and instantiate class Objects here
    
function initialize(){
        
session_start();
        
$this->model = new Model_formviewer(new adminDbConnection());
        
$this->view = new View_formviewer($this->model);
        
//1. parameter is name of the action, 2. is request method, and 3. is array of parameters that are passed to action.
        
$this->registerAction('show_form','GET',array('form_name'=>false));
        
$this->registerAction('save_content','GET');
    }
        
    
//Main method is called after all requested actions are executed.  
    
function main($action,$req,$res){
    }
    
    function
action_show_form($req){
        
$formAction = $_SERVER['PHP_SELF'].'?module='.$req->getAttribute('module').'&action=process_form';
        
$this->model->loadForm($req->getAttribute('form_name'),$formAction);
        
$this->view->display($req);
    }
    
    function
action_save content($req){
        if (!
$this->model->getForm()) throw new UserException('Choose a form!');
        
$saved = $this->model->saveFormContent();
        
$req->setAttribute('form_name',$this->model->getForm()->getName()); //set form_name attribute neened by show_form action.
        
$this->action_show_form($req); //You can call show_form action from here, so you don't need action chains.
        
$saved && $this->model->setForm(false); //Destroy form after it's content is saved.
    
}
}
This code is from dynamic form building system that i'm workin on (uses PEAR quickForm). But I think it should show the idea clearly enough.

I dont't think that classes are going to be too bloated if you desing your application well enough and do only necessary things in action methods. But one disadvantage is that you cannot reuse actions, though I don't see it as a very bad thing.
JaskaS is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread | Next Thread »

Thread Tools
Display Modes

 
Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Sponsored Links
 
Forum Jump


All times are GMT -7. The time now is 07:31.


Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 1998-2009, SitePoint Pty Ltd. All Rights Reserved