Re: [PHP] php5 oop question

2007-04-12 Thread Tim Stiles
I've seen it referred to as a Fluent Interface.  I built one just  
to see how hard it was, using a standard problem: data validation.   
The results were promising.


I combined it with an object designed to work as a factory for an  
internally stored decorator pattern.


Class Input was the factory, with a private property to hold the  
decorator object in question and a method for adding Decorators to  
the stored object based on a simple switch command.
Class Checker was the root class of the decorator pattern, doing  
nothing but returning TRUE on its check() method.
Decorator Classes for Checker included IntegerChecker,  
NumericChecker, NonEmptyChecker, RegExpChecker, EmailChecker, etc.  
etc.  All of which extended Checker, have their own custom check()  
method and a property to store the Decorator object which they wrap.


Each Checker applies its check(X) method first, then passing a  
successful request along to the Decorator object they store.  Input  
has a check() method that just passes the request along to its stored  
Decorator object.


By using the Fluent style of interface, the end result was

?php
$_input = new Input();

$_input-addCheck('Integer')
-addCheck('Range',3,9)
-addCheck('NonEmpty');

echo ($input-check('4.734'))? 'Pass': 'Fail';
?

It returns 'Fail'.  Why? It passed the NonEmpty test, passed the  
Range test, failed the Integer test.


print_r of $input object:
Input Object
(
[_checker:private] = NonEmptyChecker Object
(
[_checker:private] = RangeChecker Object
(
[_checker:private] = IntegerChecker 
Object
(
[_checker:private] = 
Checker Object
(
)
)
[_min] = 3
[_max] = 9
)
)
)

Validation works from the outside in, responses are passed from the  
inside out, so on first failure, the validation process bails.


I loop through an array of prepared Input objects for validating the  
supplied Post values from a form and get back a simple pass/fail  
response for each.


A bit of work to set up initially, but once the system is built, it's  
pretty elegant.


Tim Stiles
Icomex.com,
DallasPHP.org


On Apr 12, 2007, at 1:29 AM, Paul Scott wrote:



On Wed, 2007-04-11 at 23:22 -0700, Jim Lucas wrote:


Has anybody else seen this style of syntax?

http://5ive.uwc.ac.za/index.php? 
module=blogaction=viewsinglepostid=init_8059_1163957717userid=57290 
61010


I don't think that its really useful for anything, except maybe  
creating

overly complex SQL queries.

--Paul

All Email originating from UWC is covered by disclaimer http:// 
www.uwc.ac.za/portal/uwc2006/content/mail_disclaimer/index.htm


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


Tim Stiles,
WatchMaker,
Icomex.com




Re: [PHP] php5 oop question

2007-04-12 Thread Tim Stiles
I suppose I should have summarized what I learned from that  
experiment, putting myself more squarely on topic:  Simply put, a  
Fluent interface let me move from


$_input-addCheck('Integer');
$_input-addCheck('Range',3,9);
$_input-addCheck('NonEmpty');

to

$_input-addCheck('Integer')
-addCheck('Range',3,9)
-addCheck('NonEmpty');

with almost no effort.  Not a huge timesaver, but I kept it in  
because I find the necessary code that I'll use repeatedly to be less  
cluttered and easier to read.  Less experienced developers who will  
have to work with my code felt the same way.  It just feels like less  
labor.  And as a solution, it suited this problem well, mirroring how  
most people mentally approached the issue - making it easier for them  
to understand the code at a glance.


I elaborated on that problem because it was specifically the nature  
of the problem that led me to Fluent interfaces as being part of the  
solution.  I needed to set up a complex configuration within the  
object, but needed only a very simple response from it.  Like others  
pointed out, a SQL query is a very simple thing, but building one may  
involve many seemingly simple steps that occur in no prescribed  
particular order, and you don't need the result until the  
configuration is complete.  Fluent interfaces can hide complexity.




1) Fluent interfaces seem to work best when most of your methods  
alter the internal characteristics of an object. Setting properties,  
not Getting them.  You can't really use a fluent interface when you  
actually NEED a specific response from your method: they work by  
returning a reference to the object itself instead of returning a  
value - that way, the response they deliver is set up and ready to  
receive a new, unrelated method call.  You can combine the fluent  
with the conventional, but then you have to remember that any non- 
fluent call must occur last in a string of requests.  I could have  
easily written:


$test = $_input-addCheck('Integer')
-addCheck('Range',3,9)
-addCheck('NonEmpty')
-check('4.97');
if($test)? ...

but I found it more legible to stay conventional when using non- 
fluent methods.


Basically, if you have configuration processes that often need to be  
called sequentially, but not always in the same sequence, Fluent  
interfaces can smooth the rough edges.




2) Fluent interfaces probably work better with thrown exceptions than  
they do with error notices.  If you generate a non-fatal error in the  
middle of a string of fluent method calls, how do you cope with it?   
Return the object anyway and let the next method continue? Not return  
the object and get a new error because your error message can't  
accept a method call?  Bail out at the point of error within your  
method instead of pointing where the error was caused?  Exceptions  
move the error handling outside of the predicted flow of the fluent  
interface, making them easier to deal with.  Your errors represent  
what actually went wrong instead of being a side-effect or symptom of  
something that went wrong earlier in the process.



To sum up, Fluent interfaces seem to be a great solution when  
combined with a certain set of well-defined problems and practices.   
PHP5 makes them even more useful.  They save some keystrokes, they  
can improve code legibility, they can make PHP code more intuitive  
for people who weren't the ones who created it.  I don't think they  
make code execution any faster (or slower, for that matter).  It's  
worth knowing about them, but they probably shouldn't change your day  
to day practices.  As with most techniques, it becomes a matter of  
knowing when to apply this particular tool.


Tim Stiles,
WatchMaker,
Icomex.com
DallasPHP.org

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php