|
|||||||
New to SitePoint Forums? Register here for free!
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
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 |
|
|
|
|
|
#2 | |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
|
Quote:
|
|
|
|
|
|
|
#3 |
|
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. |
|
|
|
|
|
#4 |
|
SitePoint Zealot
![]() ![]() 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 Code:
|
|
|
|
|
|
#5 |
|
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.. |
|
|
|
|
|
#6 | |
|
SitePoint Zealot
![]() ![]() Join Date: Jan 2003
Location: Belgium
Posts: 133
|
Quote:
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 |
|
|
|
|
|
|
#7 |
|
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 |
|
|
|
|
|
#8 | |
|
eschew sesquipedalians
![]() ![]() Join Date: Jun 2003
Location: Iowa, USA
Posts: 3,779
|
Quote:
![]() |
|
|
|
|
|
|
#9 | |||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 666
|
Quote:
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:
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:
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 ![]() |
|||
|
|
|
|
|
#10 |
|
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:
PHP Code:
![]() |
|
|
|
|
|
#11 |
|
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 |
|
|
|
|
|
#12 | ||||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() 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:
Quote:
Quote:
Quote:
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. |
||||
|
|
|
|
|
#13 |
|
SitePoint Member
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. |
|
|
|
|
|
#14 | |
|
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:
Here is a link if anyone is interested: http://jakarta.apache.org/struts/api/index.html. JT |
|
|
|
|
|
|
#15 | |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
|
Quote:
|
|
|
|
|
|
|
#16 | |
|
SitePoint Zealot
![]() ![]() Join Date: Jan 2003
Location: Belgium
Posts: 133
|
Quote:
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 |
|
|
|
|
|
|
#17 | ||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 666
|
Quote:
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:
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:
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:
|
||
|
|
|
|
|
#18 | |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
|
Quote:
|
|
|
|
|
|
|
#19 |
|
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 |
|
|
|
|
|
#20 | |
|
SitePoint Member
Join Date: Jan 2004
Location: Middle Finland
Posts: 2
|
Quote:
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:
![]() 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. |
|
|
|
|
|
|
#21 |
|
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
![]() |
|
|
|
|
|
#22 | |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Oslo, Norway
Posts: 895
|
Quote:
|
|
|
|
|
|
|
#23 | |
|
simple tester
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Sep 2003
Location: Glasgow
Posts: 1,685
|
Quote:
|
|
|
|
|
|
|
#24 | |
|
SitePoint Mentor
![]() ![]() Join Date: Jun 2004
Location: Copenhagen, Denmark
Posts: 5,915
|
doing some sitepoint archeology here, are we ?
what did dagfinn btw mean by Quote:
|
|
|
|
|
|
|
#25 |
|
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:
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. |
|
|
|
![]() |
| Bookmarks |
«
Previous Thread
|
Next Thread
»
| Thread Tools | |
| Display Modes | |
|
|
|
All times are GMT -7. The time now is 07:31.














Linear Mode
