in reply to Code factory

Is there a better way to generate all these funcions?

Use closures. This should get you started:

sub make_closure { my ($table, $column) = @_; return sub { my $id = shift; my $dbh = sqlConnect(); my $sth = $dbh->prepare("SELECT * FROM $table WHERE $column=?" +); $sth->execute($id); my $result = $sth->fetchrow_hashref(); $sth->finish(); return $result; }; } local *getCustomerById = make_closure("customers", "cust_id"); local *getUserByUserId = make_closure("users", "user_id");
-sauoq
"My two cents aren't worth a dime.";

Replies are listed 'Best First'.
Re: Re: Code factory
by hmerrill (Friar) on Jul 07, 2003 at 20:07 UTC
    Can you take this a step further and show how I could print out the users name, assuming one of the 'user' columns is 'name'? I understand the closure returns a reference to a subroutine - sort of - so, *getUserByUserId is a typeglob(is that the right term?) containing a reference to a subroutine. I don't know how to take that and actually refer to the user's name. Help me understand please :)
      I don't know how to take that and actually refer to the user's name.

      That local *getUserByUserId = make_closure( 'users', 'user_id' ); simply gives a name to the sub ref returned by make_closure(). You can call it exactly as if you had the code sub getUserByUserId { . . . } instead. To get at the name, you only have to know that the function returns the results of a fetchrow_hashref(). So, something like this should do fine:

      my $user_data = getUserByUserId( $id ); my $user_name = $user_data->{name};

      -sauoq
      "My two cents aren't worth a dime.";
      
      It's now a function. Treat it as such. my %vals = getUserByUserId('foo');

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        my %vals = getUserByUserId('foo');

        It's a function, yes. But it returns a reference to a hash, not a list.

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: Re: Code factory
by Notromda (Pilgrim) on Jul 07, 2003 at 20:03 UTC
    Both flouder99 and sauoq have good answers. The closures method is what I was originally looking for, but simply having a generic function works as well. I'm also trying to look at this from the perspective of who uses these functions. Is it better to have a lot of different function names, or one function that can take a lot of arguments?

    Opinions?

      Is it better to have a lot of different function names, or one function that can take a lot of arguments?

      Generally, reducing the number of functions in your API is a good thing.

      What do you mean by "one function that can take a lot of arguments" though? Functions shouldn't take too many distinct arguments, but it is perfectly fine for there to be many acceptable values for those arguments.

      -sauoq
      "My two cents aren't worth a dime.";
      
        However, is it good for those arguments to be the names of the various tables and columns of the database? Or should that information be hidden/encapsulated by the API ?

        One way or the other, there is going to be a large API. The requirements of the program dictate that. I mean, there are a large number of logical operations to do on the data. Whether there is a different function for each, or fewer functions with different arguments, it's still a large API. The syntactical appearance is different, but the the logical API is still there.

        I think I'm leaning toward different function names, as explained elsewhere. Maybe this would be a good subject for another SoPW post.