|
|||||||
New to SitePoint Forums? Register here for free!
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
SitePoint Zealot
![]() ![]() Join Date: Sep 2002
Location: Calgary
Posts: 160
|
PEAR QuickForm
I am currious as to how people find using this module. Does anyone fine it usefull and if so does anyone have any good examples to go with.
|
|
|
|
|
|
#2 |
|
SitePoint Enthusiast
![]() Join Date: Jan 2003
Posts: 61
|
using QuickForm
Actually, I am realling dying to get Vincent's (voostind) input on this library since his points out that a lot of PEAR's libraries are bloat and not true OO design.
It appears to me that QuickForm is (comparingly) proper OO design. The concept is to create a form, which has elements. These elements are all derivatives of the HTML_Common element which has a tag name, attributes and possibly a text node content. You build the form by adding elements to it using the extended objects for each form type. It has extensibility, because you can define your own type by extending either the common form element or a more specific form element. Each element has a toHtml() method as well as generic and specific methods for modifying its properties. The form has methods to add rules, etc. The only downside of QuickForm is that it assumes you want to use a basic internal template when you output it. It would have been better IMHO if QuickForm could allow you do use an include file like Vincent's templates (a php file) that would be used to build out the form. My collegue and I added a method to each element called 'renderElement()' which prematurely spit out the element which we then stored into an element array. Then we would include a file that used this array to populate our PHP template page which would be buffered, then dumped back into the addData() method of the form and then the form was outputed. It would be better if I included some code. Here is what we would do: PHP Code:
Last edited by mojavelinux; Jan 28, 2003 at 14:27.. |
|
|
|
|
|
#3 |
|
SitePoint Zealot
![]() ![]() Join Date: Jul 2002
Location: Portugal
Posts: 143
|
After reading this explaining of how PEAR's QuickForm works i realised the concept is similar to my eBFormGenerator that is almost finished.
My set of classes, despite having similar methods and concepts, works more 'clean'. Without internal templates and without so many methods! If you guys want to have a look just say and i drop my code when is finished ![]() |
|
|
|
|
|
#4 |
|
SitePoint Enthusiast
![]() Join Date: Jan 2003
Posts: 61
|
Alright! I had just came back to ask if anyone wanted to rewrite this class with me to make it clean, get rid of all the junk. Here are a few things about PEAR's quickform that annoys me that maybe we can look into fixing.
1. It auto-assigns $_GET, $_POST values to form elements. I don't like this at all. I do like the idea of $form->setContants() which provides a set of name => value pairs to auto fill, which if necessary you could do something like $form->setContants($_POST)...but having it automatically pull in the global variables makes me pissed. 2. Have functions for $form->start() and $form->end() which prints out the form tag, hidden elements and needed javascript for the start() and the end form tag for the end()...this would solve the problem with templates because instead of having to pass your template into the form, it allows you to place the parts of the form into our own template 3. NO INDENTING...gosh what a WASTE of resources...QuickForm tries to indent to stay clean...but it never works, so what is the point! I can understand a few line breaks here and there were necessary, but forget the indenting, it is not needed. For that you should rely on an indenting engine which takes the output and pretties it up if it is sooooo necessary. 4. Form element iterator...so that if you want to just go through all the elements in the form, you can just do reset(), isValid(), next() and getCurrent()...this is very key for working with any data object. I am sure there are several others, but we can talk about them as we go. Where is your class in relation to these inquires. By the way, please look up voostind if you have not yet and read his posts on OO programming, to make sure your class remains simple. What I don't want is another useless failed class...I believe the PHP world still lacks a good OO form class even though QuickForm came pretty close (too much bloat still). |
|
|
|
|
|
#5 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 592
|
How weird, I posted to this thread yesterday, but it looks like my contribution got lost in cyberspace somewhere... So here's another try.
![]() After reading this thread I opened the file QuickForm.php from PHP CVS into my browser. Just looking at the amount of code (not the contents) my opinion is simple: it is bloated. Looking a bit further, I see this class does a lot of very useful things. But everytime I see a sentence like "This system has the following features: [long list of cool and handy stuff]. The class can be download at [url]" I don't even look at it. So many features in a single class; that's NOT the right idea, IMHO. The class HTML_QuickForm allows forms to be created, rules and filters to be applied on the form elements, contents to be validated, and the entire form to be displayed. These properties are all very different, so why are they in a single class? The first time a form is generated, only a couple of the features in the class are used: the form is build, and the form is shown. The form hasn't been posted yet, so what is the point of having form validation and post-processing code in the system? It isn't used anyway. Conversely, if the form has been posted and processed correctly, it will probably not be displayed; instead some other action will occur. So why load the code necessary for displaying the form? If the class would have been split up in four or five (or maybe even more) small classes, this problem wouldn't even occur. I very much like the idea of applying filters and rules to user input. But, like already mentioned, I would like each filter and rule to be represented by separate classes. There would be two base classes, and these base classes might be related to each other too (what is so different between applying filters and applying rules?). Anyway, I like the idea of having filters, and I'm sure it could be useful for many other things. However, because all code necessary for filtering is present into this one big class, there is no possibility to use this code without using the other QuickForm code. To conclude: I admit I like what the class does, but I don't like its implementation, and I certainly don't think it's 'proper' OO. Proper OO is all about compact, powerful classes and using object composition to make them work together. And I don't see any of that here... Vincent |
|
|
|
|
|
#6 |
|
SitePoint Enthusiast
![]() Join Date: Jan 2003
Posts: 61
|
excellent
Excellent, I hardly expected a different reply as I sensed this class had long since reached the bloat level. But as I had pointed out already, it would be much better if this classed didn't try to do so much. What I do like about this class is that in the very least it does take a simple html tag and extends that class over an over to create the different types of input tags available, as well as letting you create your own. It seems to be that this is polymorphism as it was intended. (Please note that I agree it is one of the few good things it does and that I am getting away from PEAR this minute to start on a new path).
However, it would seem like QuickFormRule should be a seperate class (just as you point out) and can be extended for the different types of rules available and then you can pass the rule into the element when it is created (or rendered) so that it can make use of the rule (assuming it is javascript or whatever). This technique is the one called composition (I believe). Now that you have set the record straight on QuickForm for me, I don't see how I could ever wrongly accept a library as proper OO which is really just procedural bloat again. What I find myself getting better at with each post I read leading up to your response is anticipating what you might say. While I will be the first to admit that I am not a "formally" trained programmer (only a BS), I have faith that if I study and practice the techniques which you have presented by not only studying the numerous books you have mentioned, but by working with others to understand how case studies fit into this model, I will be able to think along the same lines as a "real" programmer like yourself. You have truly given people in this forum hope that they can, with enough effort, break away from the pool of PHP programmers out there and make something better. You are so right about PEAR it almost makes me feel like my heart is now missing, but that is good, because I will replace it with something better. Just tonight I was attempting to use the Auth class and realized something you said earlier to be very applicable. There is no one class that will satisfy everyone's needs and the more you add, the more it becomes crap. If instead you worked on a layered approach, then PEAR would have many, many, many more classes, but they would be classes which could be extended or morphed into something the programmer can use without rewriting much or inheriting useless methods. But you are correct, PEAR was made big and nasty so that the average scripter could just get as much pre-written functionality as possible, without having to consider his/her own design. (It is almost shameful to see O'Reilly's new PHP Programming book delve into PEAR...I guess you throw enough at something and eventually it will gain some sort of backing, justifiable or not...take windows) So one has to ask, dying to ask. PEARII? A fork to start all over with something better? Not that you have nothing to do, but there is no doubt you have been beat over the head with a genius stick and if PHP is going to be taken seriously, like the java community, maybe we need this...Maybe you don't have to do any work, you can just be the GodFather. You have taugh enough people around here already. We don't need to make every class tomorrow, but Eclipse could be the right start. I know you want it to be yours, and perhaps you can still use just your class, but your expertise could at least cycle a development of Eclipse's brother. Sorry to go on so much...if you are interested in gathering some of the very intelligent people that obviously frequent this forum and produce something like eclipse.php.net, perhaps we can start a new thread for that. If you are not interested, would you at least consider being an advisor? Again, let's start a new thread for that and keep this one to quickform. Last edited by mojavelinux; Jan 29, 2003 at 03:39.. |
|
|
|
|
|
#7 | ||
|
SitePoint Zealot
![]() ![]() Join Date: Jul 2002
Location: Portugal
Posts: 143
|
Quote:
For a while i'm using voostind's lib on my projects, and i have to say that being not an expertise on programming after look to eclipse lib i understood what they do and how they work - Thanks Vicent ![]() In my eBFormGenerator i separated each element in classes for example: TextElement extends eBFormInputElements and eBFormInputElements extends eBFormElements I guess this is how PEAR's QuickForm works - just have a quick look on it. But no templates or other stuff, just what we need to generate forms is what i want my eBForm to do. Quote:
![]() And mojavelinux if you want to help me on my form classes it would be very apreciated, i like to have a second opinion and i certainly we would learn more ![]() |
||
|
|
|
|
|
#8 | ||
|
SitePoint Wizard
![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,898
|
PEAR is an interesting subject. For me I think they've let themselves be inspired too much by Perl's CPAN and the concept of a Perl Module (note that's a generalization - many Perl modules such as this simply add a discrete set of functionality wrapped in a class. Others are more complicated and seem to take advantage of inheritance / encapsulation etc. such as DBI.). In PHP the "tradition" has been to provide this type of discrete functionality within an extension. Typically a PHP library offering a limited subset of functionality will act as a fore runner to the development of a PHP extension (as has been the case with XML-RPC, DOM-XML and should soon be the case with SOAP)
Think it would be better if they considered something approaching a class library like Java's but bearing in mind the fact that much of Java's library is effectively implemented in core PHP functions or extensions. PHP is generally used to tackle different kinds of problems to Perl. Developing web applications exposes you to (almost - minus stuff like complex event handling and threading) the full range of issues that face desktop GUI developers. For PEAR to offer real value I think it has to deliver framework solutions to some degree, and have in mind some kind of overall plan for where it's going. One prime example of the problem (or perhaps the symptom), relevant to this discussion is another package in PEAR I just saw Pager_Sliding, which provides a Google like paged result set (it seems). From the change log; Quote:
First there needs to be the realisation that there's a problem. From the Andrei Interview; Quote:
The obvious argument against that is PEAR shouldn't be about offering a single framework for developing apps, with which I'd have to agree, but if we look around the web today, there's only a few approaches to frameworks which have proved themselves. Some, off the top of my head, would be Fusebox, Cocoon (in PHP: Krysalis) and Struts (basically MVC - in PHP: Phrame or Ambivalence). Bearing those in mind PEAR could offer a choice of framework (the Apache group successfully offer a number of alternative web frameworks). Contributed classes can then be required to comply with one of more of the available frameworks. Vincent's Eclipse, for example, could pretty much comply with all as it's focused almost entirely on data related operations. All sorts of other classes could then benefit from Vincents Iterator classes, for example. PEAR has gained acceptance (as OReilly demonstrate) as potential place for PHP development standards to stem from but as yet fails to deliver, IMO. This is a shame because without a standard development approaches, the wealth of PHP projects out there will never be re-usable or "integratable". If PEAR offered a standard library for web site security, for example, phpBB might use it then we'd finally be able to integrate it with other applications on our site. Until then projects like eZ publish will be forced to create their own class libraries. Right now I think phpClasses still offers better value than PEAR... |
||
|
|
|
|
|
#9 | ||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 666
|
I agree that this QuickForm class, and the same goes for any PEAR class, tries to do too many things at once. At first this may seem like it can be reused in many projects, but in the long term it will actually turn out to be unusable. Because it tries to do so much by itself, you can not combine it with other classes.
One obvious disadvantage I can think of, in fact I experienced it myself, is this: by combining the presentation and validation of forms, you can not validate forms coming from a stand alone HTML file. In the class library I developed for personal use, I had to set up all form elements combined with validation rules before I could validate the form. I could not use this to validate form submissions coming from a template file I did not build with the form classes, so I had to do validation the 'old-fashioned way'. Quote:
Quote:
). I think an important reason for PEAR's existance is to create a sort of CPAN for PHP so PHP could compete with Perl on that area. |
||
|
|
|
|
|
#10 | |
|
SitePoint Wizard
![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,898
|
You're right I wasn't being too careful about the use of the word framework but looking at the PHP GTK Hello World example the PHP-GTK connect() method allows you to specify your own callback function to run on an event.
Quote:
Sure for those people that have their server run for them by someone else, having a PHP library as a slower alternative to an extension is probably nice but here's where I think sites like PHPClasses do a better job (offering more choice). In other words by focusing on "one off" solutions to problems, PEAR doesn't have much scope to provide useful code. Back to QuickForm, shouldn't the validation functionality be part of a seperate class (which other classes could use?). Also glancing at the date "element" offered, think there's more which could be elsewhere. What I dont see is how they can take any real advantage of encapsulation, without some kind of overall plan for where they're going? Having mentioned CPAN and talked with the "guy opposite" it seems it is fairly well planned in that modules depend on / re-use others (suggesting encapsulation). So may be CPAN is a good target to head for after all. |
|
|
|
|
|
|
#11 | |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 666
|
Quote:
Just a thought |
|
|
|
|
|
|
#12 | |
|
SitePoint Wizard
![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,898
|
Quote:
Loose coupling yes but complete independence no. If we have an class for parsing remote RSS feeds over HTTP, it's preferable that it doesn't implement HTTP functionality internally but rather uses another class to do that for it. There's a whole ton of stuff you could build into an HTTP client (e.g. how to deal with proxy servers that expect you to authenticate). All this is clearly nothing to do with RSS feeds. It think it's reasonable to have "default" dependencies i.e. other classes that a class was intended for use with. There should be ways round them though, by using Adapters and so on, so you could replace one required class with another. |
|
|
|
|
|
|
#13 |
|
SitePoint Member
Join Date: Oct 2002
Location: Paris, France
Posts: 18
|
This is a bit off-topic, but this thread has more or less moved to a discussion about PEAR.
I see PEAR as a more or less heterogeneous collection of PHP classes, provided to help the wider range of developers getting started fast with several functionalities. Note that if only one package is used, then PEAR may not be the best choice because of the 30kb common PEAR.php code usually required_once(). It is certainly not a framework, and the key word here is "heterogeneous": I don't see much consistency between packages, I see no guidelines or standards (except those coding standards), and no project manager whose role is to make sure everything is homogeneous, elegant as well as performant. Instead, scripts are contributed by different people who probably don't talk too much to each other. You finally end up with a lot of different classes, some of them providing their own solution to already solved problems in other classes. Does that make PEAR suck? I don't think so. Even if some classes suck, some people probably find PEAR useful to them. Those people don't care about how it is written, as long as it works the way it is publicized. Now, should the PHP Group endorse several frameworks, the same way the ASF did? Definitely yes, especially with all this buzz about PHP 5 (being "enterprise ready"). One of them could be written by a group made of some of those talented people here ![]() Now, regarding the original subject, I found this page <URL:http://developer.java.sun.com/develo...amming/struts/> earlier when I was looking for some information about Struts. It includes a chapter from the book "Struts in action" about how it deals with validating user input. You will find it interesting to read, although I thought Struts solution was not simple enough ("KISS"). I already mentioned Struts here: a good thing about this framework is that there's a lot of information available about it, and it's always interesting reading how developers solved those common web "problems". You will also find this article, Making PHP forms object-oriented (<URL:http://www.devarticles.com/art/1/388/>) an interesting reading. |
|
|
|
|
|
#14 | |||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
Quote:
Quote:
Lets look at the iterator class from interator.php. This is a standard pure abstract class. This would be well and good in a statically typed compiled language like C++, but makes little sense in a language like PHP. In some languages like delphi or java, one might formalize Iterator into a interface declaration. In a dynamic language like PHP, this is unnecessary. You can send a "next" message to any class, regardless of type. For example, go to any of the subclasses of Iterator and remove the "extends iterator" and the require_once for iterator.php. Now delete iterator.php. Everything still works the same. This changes the concept of "Interator" from a class to a pattern. (Small P pattern like the java get and set methods) Simply make a convention that any class that ends in the word "Iterator" will support the Rest, IsValid, getCurrent, and next methods. Why not keep the base class? Because PHP code is usually interpreted. More code is slower. Here is a sample code from the StringIterator class documentation: PHP Code:
After removing the base class: 15.07 ms so on my machine it takes about 4 ms to parse iterator.php each request. benchmark was done using ab -n 1000. BTW, You should always benchmark using ab when you have differing code sizes in PHP because it takes into account the file parsing time. Very often in PHP simple small algorithms that parse quick and run slow (tortoise) will beat out more complex algorithms that run quicker (the hare). I picked string iterator for a reason. I have no idea what one would use it for. I do not see what value it has except as an example of how to make an iterator. Here is the same code using built in PHP functions: PHP Code:
So not only is this code smaller, but it is faster. For comparison purposes: PHP Code:
Iterators are useful in the right circumstances, but I feel they are overkill for most cases in PHP. I do like the database classes in eclipse. They are deliciously spartan. They could use some performance tuning, though. Two more benchmarks: PHP Code:
PHP Code:
I played around with the eclipse code for about 10 minutes and was able to get the execution time down to 22.40 ms without changing the essential interfaces by putting a MyQueryIterator into mydatabase.php, folding the database.php functionality into mydatabase.php, and eliminating some methods of questionable utility by applying the YAGNI principle. This surprised me a bit because the DB class that I normally use took 25.51 ms. Quote:
|
|||
|
|
|
|
|
#15 | |||
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 592
|
Quote:
Saying that abstract base classes make no sense in dynamic languages is a bit crude; it depends on your point of view. Clearly, yours is different than mine. For example, class Loop implements an algorithm on an 'Iterator'. By putting a base iterator in the code, it immediately becomes clear what it is and what it should look like. You don't need to read the documentation for any other iterator class. But then I admit I have a purist kind of view. Quote:
All comments you made are valid, but they all apply to constant overhead costs: reading PHP files from disk and parsing them. On a single page, any class in the library will be loaded at most once, so this is a constant overhead. It's pretty easy to get this overhead down: - Buy decent hardware - Put the library in shared memory instead of on disk. Again, my point of view is that the design and implementation of a program should never suffer just to tweak performance. A good design already leads to compact and fast code. IMHO, further gains in efficiency should not be achieved by tweaking the software, but by optimizing the hardware. Quote:
Vincent |
|||
|
|
|
|
|
#16 | |||||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
Quote:
Quote:
Quote:
Quote:
Quote:
I just meant that I didn't see that they would add value in the specific case mentioned in PEAR Quickform. Just as I don't see how they add value in the string encryption example in my last post.I've attached an alternate implemention for QueryIterator, MyDatabase, and MyQueryResult. I've combined them into a single class which is about 90 lines of code. It implements the eclipse interator interface and I think it can be used anywhere in eclipse that an iterator can be. There are a few functions that it does not implement, but I doubt those were ever called anyway. It has the same functionality, except I did not include the transaction constructor. It also only returns assoc arrays and does not give you a persistant connection choice. It has a very different way of connecting to the database. It is about twice as fast as the eclipse implementation. |
|||||
|
|
|
|
|
#17 | |||||
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 592
|
Quote:
Quote:
![]() Quote:
In the PEAR Quickform there could be many uses for iterators. For example, a form is typically constructed by adding a set of fields to it, each field having a number of properties. For example (I picked this line from a random piece of code in this thread): PHP Code:
PHP Code:
PHP Code:
Similar techniques using iterators could be applied to the filters and validation rules. Or, you could use an iterator simply because it's so easy. Remember that using 'foreach' on an array is typically not a good idea, instead you have to use the built-in array methods. You might not like that (I certainly don't). Quote:
Another thing you did is tightly couple the query result with the iteration. Most of the time there would be no problem, but using a separate iterator it is possible to do this: PHP Code:
All in all: nice try, but no dice ![]() Quote:
Vincent |
|||||
|
|
|
|
|
#18 | |
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2002
Location: Ottawa, Ontario, Canada
Posts: 215
|
Quote:
A Google search using "AB PHP benchmark" got me a bunch of MySQL AB hits ![]() I would like to use a benchmark other than time2-time1 at the bottom of a page ![]() Cheers, Keith. |
|
|
|
|
|
|
#19 | |||||||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
Quote:
Is a QuickSort faster than a bubble sort? Which implementation is bigger? Which is simpler? Quote:
Ok, I can see what you mean in PHP QuickForm. My hunch is that iterators would be overkill for most things there, but I will conceede that they might have a use somewhere. I suspect in conjuction with creating a form that allowed you to edit several records in a database at the same time. Quote:
There is nothing wrong with making assumptions as long as they are good ones.Quote:
Quote:
![]() Quote:
Quote:
I think some of these may only be used from within the library itself and some may only be there for the sake of completeness. (like the StringIterator) |
|||||||
|
|
|
|
|
#20 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
ab - Apache HTTP server benchmarking tool
http://httpd.apache.org/docs/programs/ab.html |
|
|
|
|
|
#21 | ||||
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 592
|
Quote:
Quote:
Your example code could be in a library, but that would be a personal one, meant for specific purposes (supporting web sites developed by yourself). That's an important difference. Quote:
![]() I'm not saying I have a specific example in mind of where this ability might prove useful. But consider this: 1. It is possible now. 2. It costs little. So why remove the ability from the library, gaining nothing and disabling some of its possible uses, in fact even crippling it? Quote:
PHP Code:
The getErrorMessage() and isSuccess() methods are there for a reason too. The first allows you to report a message as generated by the database to the client. The second allows you to implement specific behavior when something goes wrong. For example: PHP Code:
![]() Vincent |
||||
|
|
|
|
|
#22 | ||||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
Quote:
It could just as easily implement your style of connections as mine. This would not really change its performance characteristics, although it would change the way that you call it. Just because a library only supports one database at a time, doesn't make it not a Library (note the capital L). Its merely a different set of assumptions. For example, you state on your web site that your library does not implement many database features. You assume that your library should not attempt to homogenize disparate databases, unlike PEAR. I happen to like this assumption. Assuming that you will only support one database at a time is not wrong. just different. I am not suggesting that you give up your support for multiple database. I AM suggesting that you could implement the exact same functionality a little bit differently and get significantly better performance without sacrificing any generality. Performance is a legitimate characteristic for evaluating a general purpose library. Quote:
Circa 1996, I was asked to analyze the development processes of two different development teams. Team A's project had a half a million lines of code, 500 tables, and over a dozen programmers. Team B's project was roughly 1/6 the size. Over the course of several months, management noticed that team A was roughly twice as productive as team B. One would think that the smaller team would be more productive. I spent several months analyzing the code from both projects, working on both projects and interviewing programmers. Finally I did an exercise which lead to an epiphany. I counted each line of code in both applications and assigned them to one of a half a dozen categories: Business logic, glue code, user interface code, database code, etc. If one considers that in these categories, only the business logic code had any real value to the company. It turned out that Team A was spending more time writing the code that added value, while team B was spending more time gluing things together. In the 70s an AI researcher named Doug Lenat (?) wrote a program called AM that could discover mathematical proofs. One of the arguments against this actually being an example of computer creativity is that AM used a very rich notational language in his problem domain (mathematics). Even generating random symbols in this notation made it hard not to come up with a proof of some kind. Team A had a set of libraries which was suited to the task which they were performing. Team B had a set of Much more powerful and much more general purpose libraries. So, Team A was more productive because the vocabulary that their tools provided spoke "Their problem domain," while team B was always translating. In addition, team A had uses several patterns and conventions for doing common tasks, while Team B left things up to the individual programmers, so there was much more variation. (especially because their powerful library had so many different ways to everything.) This is why I prefer PHP for web development. PHP is crappy language. however, I feel it "speaks" web development better than more general purpose languages do, so I put up with some of its idiosyncrasies. There would be no shame (in fact I recommend it) to make the assumption with eclipse that your developers will be developing web applications. That the most common type of iterator to use will be a database one. That they will read from the database more than write to it. One thing I learned from this exercise is that when designing a library you should make the common case easy. Your libraries and tools should form a vocabulary in your problem domain. One thing that I look at when designing a library is how simple is the common case. This is where I don't care for eclipses iterator interface. So I look at this common case: PHP Code:
PHP Code:
reset() next() getRow() Having worked on this an example of the most common simple case, I would then go develop the library that would make this happen. I am not suggesting that you change your iterator interface. I am just trying to show why I thought it was bloated when I originally evaluated it. There is nothing wrong with eclipse. it is well written and elegant from a certain perspective. Its just not what I would like. Quote:
The seek is unnecessary except in your iterator implementation. In a typical web application, it is not really necessary to move around in the db cursor randomly. Top to bottom usually suffices. in fact it is really only here because your iterator class works on an "indexed" or "array" conceptual model, rather than on a "sequential access" or "database cursor" conceptual model. This is one of the things I don't like about the eclipse iterator implementation. The interface does not provide for an indexed access mode, yet internally it uses an index model versus a sequential model. The consequences are illustrated by code snippets above. I would also ditch the ASSOC, NUM, and BOTH choices. go with either ASSOC or BOTH. I would go with ASSOC, but your default of BOTH is fine. The ability to choose is unnecessary. ASSOC would be good for 99% of the cases. for the other 1%, you can provide a converter function which resides in a separate file, outside of the commonly included files. Do you see how getRow in QueryResult is really just getCurrent in the Iterator class. If your iterator was DB aware, then getRow would be unnecessary. Do you ever call getRow, from outside the eclipse library itself? Quote:
|
||||
|
|
|
|
|
#23 | |||||||
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Oct 2001
Posts: 592
|
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Vincent |
|||||||
|
|
|
|
|
#24 |
|
SitePoint Wizard
![]() ![]() Join Date: Nov 2000
Location: Switzerland
Posts: 2,898
|
If I can just inject a comment, it seems Selkirks original criticism of the Iterators was that each one inherits from a parent that doesn't "do anything" itself, resulting in a performance hit.
That in itself exposes a discussion that seems to divide many PHP coders (and also seems to relate to a current Java vs. .NET Petstore debate regarding use to design patterns, which is raging all over). PHP is in many ways a special case as a language, as much of it's native library is implemented in a procedural form (with a few exceptions like the Dom XML Extension and the dir class). Other features, like GET and POST data being accessed via global variables blur the case for particular design practices in PHP. My own view these days (after having wasted alot of time on code that was extremely hard to maintain) is that anything which improves a developers performance far outweighs any associated hit in application performance. Vincents Iterator classes strike exactly this nerve. PHP doesn't have an "abstract" or "interface" keyword so the common argument against his Iterators is either why inherit from a class that "serves no purpose" or why bother having an Iterator at all, given it's possible to implement this is native PHP. What I like about them, in their present form, is for a developer provided with Vincents API documentation and some code acting as a client to Eclipse, reading the client code will "make sense". The naming of the methods makes code that uses them intuitive to read. Any Iterator used will be clearly identifiable. Should it be necessary to swap one for another, for example moving the source of some data from a text file to a database table, the developer understands the "contract" that DataFileIterator and QueryIterator both come with and can predict the results of the change. Furthermore should it be necessary create a new Iterator for some other purpose (such as walking a XML structure which will be parsed using SAX), the task of the developer is easy, knowing exactly the rules the have to comply with. These may seem like trivial benefits and perhaps I'm just a slack developer but while working on a project that takes a few weeks / months, I find I tend to change styles and adopt different approaches to solving the same problem. What's more I may not even realise I'm solving the same problem. Having a framework like Vincents which identifies common problems I face every day and provides a uniform solution is extremely beneficial. Of course to gain that benefit I have to commit myself to using Eclipse and it's approach to solving problems but given that Eclipse focuses on data related tasks, I haven't tied myself to something that will limit my ability to do unusual things with the rest of my application. For me, the true value of the Iterators becomes apparent when you have to go back to some old code at a later date. Illustrating this with a thought experiment, that makes good sense to me, is to consider whether it's possible to replace a database with a web service as the source of data in the application (something that I might concievably want to do). Fetching data from a web service is a different problem to fetching from a database. One problem is you want to make as few "calls" to a web service as possible (avoiding the significant performance overhead of using HTTP over an unreliable network). It's necessary to fetch as much data as possible in a single call and store is somewhere locally so I don't need to repeat the call. The specifics of a class I use to do this will be quite significantly different from a database class performing a similar data fetching operation. If I directly used the API of the database classes throughout my application, there'll be much re-writing when switching to a web service. If instead I used the QueryIterator, I can create something like a SOAPIterator and simply instaniate this instead. Going back to the question of code bloat, although you may argue that Eclipses use of abstract / interface classes constitutes bloat, but if you look at any concrete classes in the library, their methods and coding is highly discrete and minimalistic. It may not provide code that executes faster but it does make it very easy for other developers to understand. |
|
|
|
|
|
#25 | |||
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Nov 2002
Posts: 846
|
Quote:
The first time I evaluated eclipse, I downloaded it straight from hotscripts, looked at the code for 5 minutes, drew my conclusions and deleted it. When I saw this thread, I searched for eclipse, found your website, read it, and then looked at the code. The reason I decided to comment was that I agree with many of the things you say on your website. There are a lot of other things that aren't even worth commenting on. (Like the event handler stuff) Quote:
I honestly thought my code example would be enough. Let me go into more detail regarding the iterator implementation. Your iterator implementation works on an "indexed" conceptual model. Your iterator interface works on a sequential access model: reset() next() IsValid() getCurrent() You cannot arbitrarily access elements using this interface. You cannot even find out what position you are at. furthermore, all of the things that you attempt to iterate over have native sequential access functions in the style of: move to the next position, return the element there or indicate that there are none left. arrays: next() databases: mysql_fetch_array() files: fread() directories: readdir() So, the native PHP functions use a sequential access interface. Your iterator class presents a sequential access interface. Yet, its internal implementation uses an indexed conceptual model. It maintains an index. It accesses the rows by index from the QueryResult. Eclipse has an impedance missmatch between conceptual models. This is bad. Client code (Sequential) => eclipse (indexed) => PHP (Sequential) There are two problems with the indexed model. First, it is less efficient. Second, it is less safe in a multi user environment. It is less efficient because it maintains an index which doesn't really serve an external purpose. It also requires that you get a count of the elements at the beginning. The sequential access model does not require that you get this count of records. It is less safe because when you get the count of elements at the beginning, and another user in another process adds or deletes records, your count is not longer correct. Some databases like mysql will protect you from this by caching the query results. Some won't. Take for example, the function mysql_unbuffered_query. With this query, you cannot access mysql_num_rows(). This mean that your QueryIterator implementation cannot work with queries generated from mysql_unbuffered_query. A QueryIterator that followed a sequential access conceptual model would. You shouldn't assume that I might not want to use this type of query. ![]() My code was supposed to illustrate how you can implement your Iterator interface using a sequential access model. The performance gain was supposed to be the "hook" that got you to pay attention to it. (oh, well.) There is one hurdle to your understanding. (Partly why you think you would lose functionality.) Quote:
There is an activation energy. Implementing a sequential access query is harder given the current relationship and implementation of QueryIterator and QueryResult. QueryResult becomes the natural place to implement a QueryIterator. The QueryIterator class becomes superfluous. If you stop thinking of QueryIterator as a class and start thinking of it as an interface, these problems melt away. (I feel zen like. Clear your mind. release your hangups and inhibitions.) Think of the QueryResult as the wrapper for the result resource from the query. When the result is multiple rows, you use the QueryResults iterator interface to access them. Now, for compatibility purposes, You implement QueryIterator as a pass-through adapter. Each method simply calls the equivalent method on the QueryResult that you pass to it. This maintains complete backward compatibility. You then deprecate the QueryIterator class. Its there, but you should not use it in the future. I have a bit more to say, but people are dragging me away from my computer to go eat lunch. |
|||
|
|
|
![]() |
| Bookmarks |
«
Previous Thread
|
Next Thread
»
| Thread Tools | |
| Display Modes | |
|
|
|
All times are GMT -7. The time now is 21:09.










). I think an important reason for PEAR's existance is to create a sort of CPAN for PHP so PHP could compete with Perl on that area.


Linear Mode
