Re: Some PEAR remarks

From: Date: Fri, 19 Apr 2002 10:48:33 +0000
Subject: Re: Some PEAR remarks
References: 1 2  Groups: php.pear.general 
Request: Send a blank email to pear-general+get-1207@lists.php.net to get a copy of this message
On Thu, 18 Apr 2002 13:11:40 +0200, Stig S. Bakken wrote: > Public properties are useful sometimes, I'm not in the "encapsulate or > die!" camp, even though I always almost encapsulate. In my humble opinion: that's just too bad. Maybe when implementing an application I could slightly agree, but when implementing a library - intended to be used by many, many programmers you don't know - you should definitely encapsulate everything. But that's just my opinion :-) > The PEAR class is really not a base class like Object in Java, but a > place where we can emulate functionality that is still missing from PHP > (such as destructors and exceptions). Alright, I understand that now. But it could be nice for a programmer to be able to choose: destructors only, error handling only, or both. > PEAR is very much geared towards ZE2 and PHP 5. PEAR errors are a poor > man's exceptions, and they will be replaced completely by exceptions > when using PEAR with PHP 5, so using them will become easier. I've read the ZE2 plans, and I'm anxious to see them implemented! >> Class DB is a class with static methods only, and the two most >> important ones (factory and connect) either return an object of the >> requested type, or an instance of class 'PEAR_Error'. Again, I think >> this is not a good separation of 'normal' code and 'error' code. Also, >> whenever some code calls one of these methods, it should always check >> whether the object returned is the one they wanted, or something else. >> This raises a question: how often is this done by your typical lazy >> programmer? And what about production-state code? That kind of code >> doesn't contain any programming errors, so then there's no need to >> check for them. > > Uhm, programming errors? PEAR can't help you with those I'm afraid ;-) But it does! When you supply class DB with a 'hard-coded' DSN that's incorrect, class DB will return a PEAR_Error. Maybe it's not a programming error at the lowest level, but it's still a programming error in my book :-) >> Much of the error handling can be simplified by introducting 'Null' >> objects. These are objects of a class that simply do nothing. For >> example, you could have a class DB_null that is just like any >> DB_common-derived class, and is returned whenever a requested database >> class doesn't exists (when calling DB::connect). It simply returns >> default values from its methods instead of doing anything useful. This >> trick makes using the library a lot easier, and of course it applies to >> much more than just the DB class. > > Using existing values for errors is very difficult in a large scale. > What if you actually want to return NULL from a function? There are no > simple, scalar values available for this, that's why we use objects. I think I didn't make myself very clear: I didn't mean the value 'NULL' should be returned, but a 'Null Object' instead. I'll explain it below, but I have to say first that they are mostly useful for 'default values' and not for error handling. Doing that is probably not a good idea, contrary to what I said first... (Sorry!) Imagine you have a class User that stores information on the current user in a web application. However, this user is only available if he/she actually logged in to the system. This often leads to code like this: // Print the name of the user if (!$user->isLoggedIn()) { echo $user->getName(); } else { echo 'none'; // or something } These if-statements tend to be repeated all over the code, in various guises. An elegant solution is to create a NullUser, which could look like this: class NullUser extends User { function getName() { return 'none'; // or something } } Now, at the start of the application, it is checked exactly once if the user is logged in. If he/she is, a normal object of class User is instantiated (or restored from a session or whatever), or else an object of class NullUser is used. This greatly simplifies the remainder of the code, as you'll hopefully agree. Often, these 'null objects' return other null objects. Imagine class User has a method 'getFavorites' that returns an object of class Favorites with favorite products in the web application specific for that user. (Like Amazon.com can store your personal book list.) Class NullUser would likely implement method 'getFavorites' to return another an instance of class NullFavorites, if class Favorites can't be used for that. It might make sense to implement all null objects as singletons. >> If I - as a user of the PEAR library - wish to use PEAR to create a >> connection with a MySQL database, the following files will be included: >> 'PEAR.php', 'DB.php', 'DB/common.php' and >> 'DB/mysql.php'. That's 793 + >> 874 + 1281 + 847 = 3795 lines of code (in PHP 4.2RC4). For fairly >> trivial tasks like making a database connection and executing SQL >> queries, I think that's a bit much... > > I agree, there's too much code in there right now. Yeah! I finally convinced someone! :-)) > When user-space overloading and aggregation is finally declared stable > in PHP, DB will be rewritten to use it. I plan to partition out (and > auto-load) big chunks of code that will make the basic connection class > much lighter. But that doesn't really solve the problem, does it? The code will still be there. As I said in another post in this thread, I think classes DB and DB_common are too feature-bloated. Methods like 'fetchOne' and 'fetchAll' simply shouldn't be there, because they do not add a new feature to the library; they only combine a couple of existing features to make using them easier to use. That kind of code shouldn't be in a library, or at least not at that level. > As with encapsulation, I don't think people should be religious about > re-use. Sometimes, avoiding too many dependencies is a valid tradeoff > for code reuse. Re-use is good, but not something to get religious > over. If you can avoid installing/using a whole new package with 5-6 > lines of code, those are well worth it from a maintenance standpoint. When writing an application, you're right. A library or a framework is a whole different ballgame, not comparable in the slightest to implementing an application. If a (big) library isn't able to re-use itself in its implementation, it generally stinks. You might want to read up on some literature on building libraries or frameworks to see what I mean. I don't mean to say that you don't know what you're doing, certainly not! (Who am I to say that?) It's just that writing a library is a very large and complicated discipline, too large for me to explain here. (And I don't consider myself qualified for the job anyway.) Also, enabling re-use isn't the same as adding many dependencies, as you imply here. It's perfectly possible to re-use a lot of code without having too many dependencies. Finally, re-use is definitely something to get religious over when you're writing a library! In an application, re-use is nice to have, but not a requirement. In a library (or framework) it certainly is. Vincent

« previous php.pear.general (#1207) next »