in reply to Re: A First CPAN Odyssey
in thread A First CPAN Odyssey

At present, this is the top level POD I have that describes the module as a whole in an attempt to give a broad view of its purpose and organization. Then there is POD within each class that describes its usage which is not posted here.

As someone else suggested, it would probably be best for me to simply move the top level name to some new unique name, so as to avoid collision with pre-existing things such as SQL::Statement.

Oh, and please don't hesitate to be pedantic and highly critical. Submitting my first CPAN module stems not just from the desire to contribute something useful, but also from selfish motivations to learn the process of doing so. You are explicitly authorized to pull no punches. :-)

Name
    SQL

Description
    This module serves as a framework for object persistence via a SQL
    database. Interaction with an underlying database is accomplished via
    Perl objects that abstract away all of the tedious construction,
    issuance, and processing of SQL queries. Within this framework, users
    may create, modify and delete objects, as well as link them together in
    arbitrary ways, and perform a variety of querying operations.

    Divided into several conceptual components, this module provides several
    well isolated sub-components that are reasonably easy to understand on
    their own. Short descriptions of these modules may be found in the
    following section.

Modules
    SQL::Object
        If any class were said to lie at the center of this module, this
        would be the one. This class serves as the base class for all object
        types, and provides a collection of methods for performing all
        common operations, such as saving, modifying, and deleting it.
        Sub-classes to this class must provide a get_table_name() method,
        and will probably also include various and sundry wrapper methods to
        flesh out the functionality of the class. One can load single
        objects via themselves, or obtain collections of objects by using
        the SQL::Object::Query class.

    SQL::Object::Query
        This class is used to specify a query of a collection of objects.
        Queries of this type are specified with conditions, bindings of
        condition variables to values, and orderings. One may additionally
        specify a list of SQL::Link::Query objects which will specify that
        the objects loaded should be loaded with certain parent and/or
        children objects. When the execute() method is invoked, a
        SQL::Object::ResultSet object is returned.

    SQL::Object::ResultSet
        A SQL::Object::ResultSet object is the result of executing a query
        specified by a SQL::Object::Query object. By repeatedly invoking the
        get_next_result() method until it returns undef, one can iterate
        over the results of a query, getting back instances of classes that
        derive from SQL::Object.

    SQL::Link
        A SQL::Link object specifies a linking relationship in the database,
        and also provides mechanisms for creating, modifying and deleting
        relationships between objects as specified by the link in question.

    SQL::Link::Query
        A SQL::Link::Query object is used to specify a query of a collection
        of linked objects. Queries of this type are specified with a
        SQL::Link object, conditions, bindings of condition variables to
        values, and orderings. When the execute() method is invoked, a
        SQL::Link::ResultSet object is returned.

    SQL::Link::ResultSet
        A SQL::Link::ResultSet object is the result of executing a query
        specified by a SQL::Link::Query object. By repeatedly invoking the
        get_next_result() method until it returns undef, one can iterate
        over the results of a query, getting back instances of the
        SQL::Link::Result class.

    SQL::Table
        A SQL::Table object contains all available information about a
        database table. It holds a collection of SQL::Column objects, and
        indexes them in useful ways. Users will probably never have need to
        create a SQL::Table object directly. Rather, the SQL::Object class
        provides a get_table() method that returns an object of this type.
        The table returned is contingent upon the derived class's
        get_table_name() method. Using the name of the table, SQL::Row
        constructs a SQL::Table object which populates itself with table
        structure information by querying the database.

    SQL::Column
        A SQL::Column object contains all of the attributes of a column of a
        database table. Such information includes name, type, and keying.

    SQL::Statement
        The SQL::Statement class is a base class for several derived
        classes, each of which provides for a certain type of SQL statement.
        This class takes table names, field names, conditions, orderings,
        and other such statement parameters, and then via the stringify()
        method returns a scalar that holds the statement string.

    SQL::Util
        This class holds a collection of static utility methods that allow
        for performing common database tasks.

    SQL::Conf
        The SQL::Conf class is a base class for classes that parse
        connection configuration information for various RDBMS, e.g.
        SQL::Conf::MySQL.

    SQL::DBH
        The SQL::DBH class has but a single static method, create_handle(),
        which creates database handles via calling DBI->connect(...).

Environment Variables
    SQLRDBMS
        This environment variable specifies the default value to be used by
        SQL::DBH in specifying the type of database to which a connection
        will be made. Presently the only supported value is 'MySQL'. This
        value allows SQL::DBH::create_handle() to figure out which derived
        class of SQL::Conf to instantiate, though one may instead pass an
        argument to it to specify the RDBMS explicitly.

    SQLCNXNCONF
        This environment variable specifies the default value to be used by
        SQL::DBH::create_handle() when using a SQL::Conf subclass to parse
        the configuration information for a database connection.

Replies are listed 'Best First'.
Re^3: A First CPAN Odyssey
by jZed (Prior) on Jun 22, 2004 at 21:01 UTC
    You should defintiely read simonm's great node - DBI Wrapper Feature Comparison and figure out how your module relates to the discussion there.

    It seems to me that your module uses SQL to accomplish things but *users* of your module will not be dealing with SQL at all. So therefore you should name the module something more related to what the users will be doing - using objects, persistence, relationships, etc. Take for example your SQL::Column - how is that at all related to SQL? You are providing information about the structure of the table not about the structure of a SQL statement.

    I think your module belongs in the DBIx:: namespace since it is primarily an alternate programming interface to DBI. I'm afraid I don't get any sense from your POD of how your module differs from the dozens of other similar modules (some of which don't do any better of a job at distinguishing themselves in their PODs). Why would someone want to use your module rather than one of the others? I am not at all saying this to discourage you from CPANing your module, rather suggeting you get as good a sense as you can of how a potential user would react to your description of the module - the more you can define what your module does that is unique and helpful and usable, the better the chance that a potential user will look at it. The more you have a defined sense of how your module is unique, the easier it will be to pick a name for it.

      This is an excellent point... DBIx does seem like a much more logical home for this module. Indeed SQL is merely a component of the underlying engine, not something with which the user has much interaction, apart from writing conditions for object lookups. SQL::Column, for example, should become something like DBIx::Foo::Table::Column, where Foo is whatever I end up naming my module.

      Your point about the need to distinguish my module from the myriad others is also well taken. In retrospect, while I think my module's implementation and interfaces are quite good, you are dead on in saying that I've done a poor job selling its uniqueness. I shall take this to heart in the next revision. It doesn't matter how great my module is if people don't take the time to explore its capabilities.