class with only static functions

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

class with only static functions

Post by jonathant »

In my application I am performing lots of random search queries. I need to run these queries without actually instantiating objects, for example "how many users have last name 'Smith'". In this case it seems like static functions are my best option, other than just creating a query right there on the page.

Some could probably be thrown into existing classes as static functions, but those classes are starting to get pretty big. So, I'm thinking about creating a class called "datasearch" or something like that, and just putting all these random static functions in it. Is this good/bad practice? Should I stick to trying to find the closest matching class and putting the static functions in it? I'm still learning how to do oop, so am I missing something fundamental?

Also, I'm curious to know how big (loc, or filesize) are your biggest files? Some of my scripts are getting pretty big, but I'm a beginner so I don't know what really big is. Maybe, they're still relatively small?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

I get the sense from your comments about static calls, the size of your code and wondering where methods should go that you are perhaps coding in a procedural fashion using the OO constructs in PHP. And, just my opinion, but I try to stay away from static calls because they really eliminate polymorphism -- although there are uses for them.

Maybe if you showed some example code we could give some specific comments.
(#10850)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

PEAR::DB can be used statically as well as instantiated.

In other words, there are no problems creating methods that are specifically for static purposes. One of those reasons can be adhoc SQL statements.
jonathant
Forum Commoner
Posts: 32
Joined: Sat Jan 07, 2006 3:13 pm

Post by jonathant »

Jenk wrote:In other words, there are no problems creating methods that are specifically for static purposes. One of those reasons can be adhoc SQL statements.
Yes, this is what I was getting at, and adhoc SQL statements is exactly the reason I need the class. Lets say, for example, I have a User class that is getting pretty bulky. I need a way to find all users with the last name "Smith." So, rather than add yet another function to the User class, I want to create a whole new class that would just have a static function search_last_name(). And because there are many more random searches, I want to be able to add these as more static functions to the class, for example, search_first_name(). In the end, I have a class that is built entirely of static methods. I guess I was just wondering if there were any pitfalls to this, or if there was something I was overlooking that would make it bad practice.

Also, what about file sizes?
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Jenk wrote:PEAR::DB can be used statically as well as instantiated.

In other words, there are no problems creating methods that are specifically for static purposes. One of those reasons can be adhoc SQL statements.
As you can tell I'm not a big fan if static methods, so I don't think much of PEAR DB's design.
jonathant wrote:Also, I'm curious to know how big (loc, or filesize) are your biggest files? Some of my scripts are getting pretty big, but I'm a beginner so I don't know what really big is. Maybe, they're still relatively small?
It sounds like there are somelarger problems with the design of your classes. I'd be interested to see some code. Perhaps another approach might work better than to keep adding functions.
(#10850)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Why, may I ask, are you not a fan of them?

The good thing to a static class, with static methods is that they are "grouped" together.. need a method for abstracting data from a DB? Look in the DB class.. etc. :)
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

If a method can be called statically though surely its limited in how it can interact with the rest of the package - can't say I've looked at PEAR::DB closely (being an ADOdb fan) but it would seem having too many methods static would limit their overall functionality for purposes aside from the core "do sql, return results"...

I can't see such a design being too popular in most places... Smells too much like procedural.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Jenk wrote:Why, may I ask, are you not a fan of them?
I think Maugrim_The_Reaper give a sense when he says. "Smells too much like procedural." For me, the main thing I have against static calls is that they eliminate the possiblity of polymorphism, which for me is one of the best things about OO. I have found over the years that I tend to get rid of static calls because, though they seem simpler at first, eventually they are an inflexible point in the code that I start designing around. I know there are cases where they simplify the code a little -- so I don't want to sound like some OO zealot saying they are verboten. But for me they are ususally an example of where I haven't got the design right yet because I can't see the bigger picture. For others they may fit in better with the way they code.
Jenk wrote:The good thing to a static class, with static methods is that they are "grouped" together.. need a method for abstracting data from a DB? Look in the DB class.. etc. :)
I'm not sure about "grouped together" but it sounds like a function library to me. Nothing wrong with helper functions. Other languages with namespaces allow you to group things without creating a class.

As for PEAR DB, I am not a fan of the static factory that they use. It's just unnecessary overhead that allows for something that I have never done -- switch types of database servers on the fly. For me, because that code is only is one place in my applications, there is no difference between class DBConnection('MySQL', ...) and class DBConnectionMySQL(...) except less overhead.
(#10850)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

They don't eliminate polymorphism at all:

Code: Select all

class WhatEver
{
    function StaticSomething ()
    {
        if (func_num_args() > 2) {
            return self::doSomethingA(func_get_args());
        } else {
            return self::doSomethingB(func_get_args());
        }
    }
}
With PHP5+ you can declare a method static, thus it doesn't become part of your instantiated objects, so the overheads are not increased much, if at all..

If anything, it's the collaboration of related functions that make static classes worthwhile, as said earlier, you group the functions together that perform similar tasks so you know where they are (Separation.. Layers.. Patterns..) Take a look at feyd's SHA256 class for a good example.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Jenk wrote:They don't eliminate polymorphism at all:
Not sure if different return values is polymorphism.
Jenk wrote:If anything, it's the collaboration of related functions that make static classes worthwhile, as said earlier, you group the functions together that perform similar tasks so you know where they are (Separation.. Layers.. Patterns..)
Again, that sounds like a function library not a class to me. I get te sense that "static" is mostly used to create Singletons which I try to stay away from as well.
Jenk wrote:Take a look at feyd's SHA256 class for a good example.
I would like to -- where can I see it?
(#10850)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

it's in Code Snippets.. :)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

feyd wrote:it's in Code Snippets.. :)
I have to say that the code is really excellent. And, I think it is an example of how you can use classes to namespace helper functions. However I think it overdoes the interface a little. There is too much of the following for my taste:

Code: Select all

$func = 'hash' . $mode;
        $ret = SHA256::$func($data);
//and 
        $type = 'SHA256Message' . $type;
        $this->message =& new $type( $str );
Separate, simpler, direct interfaces for strings, files and URLs would be preferable to me. I think it would make the code clearer.
(#10850)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

arborint wrote:Separate, simpler, direct interfaces for strings, files and URLs would be preferable to me. I think it would make the code clearer.
Ahem.

Code: Select all

*    Function:
*        SHA256::hash()
*
*    Syntax:
*        string SHA256::hash( string message[, string format ])
*
*    Description:
*        SHA256::hash() is intended to hash a single string, of nominal length
*        (memory permitting.) The entire string is loaded into memory, broken
*        into chunks and appended with the hashing fill algorithm.
*
*        SHA256::hash() is a static function that must be called with `message`
*        and optionally `format`. Possible values for `format` are:
*        'hex'    default; hexidecimal string output (lower case)
*        'HEX'    hexidecimal string output (upper case)
*        'bin'    binary string output
*        'bit'    bit level output (256 character '1' & '0' string)
*
*        Failures return FALSE.
*
*    Usage:
*        $hash = SHA256::hash('string to hash');
*
*  ---------------------------------
*
*    Function:
*        SHA256::hashFile()
*
*    Syntax:
*        string SHA256::hashFile( string filename[, string format ])
*
*    Description:
*        SHA256::hashFile() is intended to hash a local file _only_. STDIN is
*        not supported at this time, nor is any other protocol other than 'file.'
*
*        SHA256::hashFile() is a static function that must be called with a
*        `filename` and optionally `format`. Possible values for `format` are:
*        'hex'    default; hexidecimal string output (lower case)
*        'HEX'    hexidecimal string output (upper case)
*        'bin'    binary string output
*        'bit'    bit level output (256 character '1' & '0' string)
*
*        Failures return FALSE.
*
*    Usage:
*        $hash = SHA256::hashFile('/path/to/file.ext');
*
*    Note:
*        This function will not accept any other protocols other than 'file'.
*        This is due to the use of fstat(), among other reasons.
*
*  ---------------------------------
*
*    Function:
*        SHA256::hashURL()
*
*    Syntax:
*        string SHA256::hashURL( string url[, string format ])
*
*    Description:
*        SHA256::hashURL() is intended to hash a url. 'http://' is optional, if
*        you want to use it. The function checks if allow_url_fopen is enabled.
*        If it is, the url is passed through fopen(), so all protocols supported
*        your installation of PHP are supported automatically. If allow_url_fopen
*        is off, fsockopen is attempted to be used. This version only supports
*        http requests through fsockopen. So beware.
*
*        SHA256::hashURL() is a static function that must be called with a `url`
*        and optionally `format`. Possible values for `format` are:
*        'hex'    default; hexidecimal string output (lower case)
*        'HEX'    hexidecimal string output (upper case)
*        'bin'    binary string output
*        'bit'    bit level output (256 character '1' & '0' string)
*
*        Failures return FALSE.
*
*        If a protocol is not specified, 'http' is assumed.
*
*    Usage:
*        $hash = SHA256::hashURL('http://www.site.com');
*
*    Note:
*        The protocol used _must_ be registered with your PHP with
*        allow_url_fopen enabled, or must be 'http'.
:lol:
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

feyd wrote:Ahem.
I know, I know. What I meant was that I probably would of implemented it as:

SHA256String::hash()
SHA256File::hash()
SHA256URL::hash()

That way you actually get polymorphism and I think it would simplify the code somewhat.

However I should say that I have a lot of respect for your abilities and it is easy to nitpick complex code, so it is quite possible that yours is the best solution to problem. As I have said above, a lot if this has to do with ones opinion of statics, Singletons, etc.
(#10850)
Post Reply