On Fri, 2002-04-19 at 12:48, Vincent Oostindie wrote:
> 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.
Not in a library? Then where should it be? They certainly are features
in a library, because they provide a quick and easy way to do simple
queries, which makes programmers more productive.
> > 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.
I think we have different perspectives of this: PEAR is not a huge
library where you install everything at once. It is a collection of
independent packages that may and often do use functionality from other
packages. When a package does this, it is expressed through a
dependency declaration that is checked during install. If you have ever
used Perl's CPAN, you may have experienced one of the extreme
consequences of dependencies gone hay-wire: if you have an old version
of Perl and want to install something that uses only part of a big,
bleeding-edge-type of package (libwww-perl for example), you end up
reinstalling Perl. This is extremely annoying, and I don't want to put
PEAR users through the same thing.
So IMHO, re-use has a higher cose if it requires installing a new
package (because that may possible introduce other problems, as well as
affect complexlity and maintainability). But again, in general re-use
is good.
- Stig
--
PEAR General Mailing List (http://pear.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
|