You'll want to use a data manager to abstract and encapsulate access to your data. It's an object that provides a consistent interface to get and set data on the backend. This excerpt from Kyle Loudon's Developing Large Web Applications will show you how to create and extend data managers for your project.
A good approach for creating data managers is to define them for fairly granular sets of data grouped logically from the backend perspective. Backend developers may be in the best position to do this since they have good visibility into details about backend systems. Ideally, these details should be abstracted from the user interface. Once data managers are defined, the user interface can instantiate whichever of them are needed to load and save data for the page.
It’s important to realize that data managers don’t necessarily correspond one-to-one to modules on the page. In fact, this is a key design attribute that makes it easy for multiple modules to access the same data, which is common in large web applications. For example, imagine a postal code stored by the backend for the current visitor. You may need to use this within multiple modules on a page, but ideally there should be a single data manager that defines the interface for getting and setting it.
Because all data managers fundamentally do the same thing (i.e.,
get and set data), it’s useful to define a DataManager base class (see Example 6.6). This base class defines a standard
interface that all data managers implement. For each data manager that
you derive from this base class, implement either or both of the methods
in the interface as needed, and provide whatever supporting methods are
helpful for these methods to manage the data efficiently. The default
implementations do nothing.
Example 6.6. The DataManager base class
class DataManager
{
public function __construct()
{
}
public function get_data($load_args, &$load_data, &$load_stat)
{
}
public function set_data($save_args, &$save_data, &$save_stat)
{
}
}
The get_data method of a
data manager abstracts the process of getting data from the backend. A
key part of implementing a clearly defined data interface for getting
data is to define well-organized data structures for each of the
parameters that get_data accepts or
returns:
public function get_data($load_args, &$load_data, &$load_stat)
$load_argsInput arguments needed for getting the data—for example, configuration settings, a database connection, or the maximum number of items in a list of data to retrieve. Since more than one input argument is frequently required, an associative array works well for this data structure.
$load_dataA reference for where to place the retrieved data. Since more than one data member is frequently retrieved, an associative array works well for this data structure.
$load_statA reference for where to return the status of the operation. A status indication may be a numeric code or a string in the simplest situations, or it could be an associative array that provides more details.
The set_data method of a
data manager abstracts the process of setting data in the
backend.
public function set_data($save_args, &$save_data, &$save_stat)
The set_data method of a data
manager uses the same arguments and internal structures as get_data, except $save_data is the data to save. This
argument is a reference so that a data manager has the option to pass
back some data after saving.
Often, it makes sense to build on existing data managers when creating new ones. For example, you might create a data manager that relies on common methods for working with web services from another data manager or combine access to multiple, finer-granularity data managers within a single data manager that a page can instantiate on its own. The extension of data managers offers more than just a convenience—it also provides the opportunity for certain optimizations. For example, you might encapsulate how you share database connections or file handles. Because data managers are objects, you can extend them easily using either inheritance or aggregation.
Inheritance establishes an “is-a” relationship between data managers. To extend a data manager using inheritance, derive your new data manager class from the data manager class with the characteristics that you desire. The extension of a data manager via inheritance is a good approach when you need a data manager that is a more specific type of an existing one.
Example 6.7 derives the New Car Listings data manager from the Web Service data manager, which provides common capabilities for any data manager that accesses web services. When you extend a data manager using inheritance, the derived data manager has access to all the public and protected members of its parent. You can then add new methods or override methods from the parent to augment functionality.
Example 6.7. Extending a data manager using inheritance
class NewCarListingsDataManager extends WebServiceDataManager
{
// This class has access to all the WebServiceDataManager protected
// and public members to support managing the New Car Listings data.
}
Aggregation establishes a “has-a” relationship between data managers. To extend a data manager using aggregation, create an instance of the data manager class with the capabilities that you desire as a member of the new data manager. The extension of a data manager via aggregation is a good approach to let a single data manager provide access to the data of multiple data managers.
Example 6.8 aggregates several data managers into a New Car Listings data manager so we can retrieve new car reviews as a part of retrieving other data related to new car listings. When you extend a data manager using aggregation, your data manager has access only to the public members of the data manager that has been aggregated.
Example 6.8. Extending a data manager using aggregation
class NewCarListingsDataManager
{
protected $new_car_reviews_dm;
...
public function __construct()
{
parent::__construct();
$this->new_car_reviews_dm = new NewCarReviewsDataManager();
}
public function get_data($load_args, &$load_data, &$load_stat)
{
$this->new_car_reviews_dm->get_data
(
$load_args["new_car_reviews"],
$load_data["new_car_reviews"],
$load_stat["new_car_reviews"]
);
// Get other data needed for the New Car Listings data manager.
...
}
}
Just as we saw in Example 6.3, the use of the
new_car_reviews member (named after
the data manager itself) for each argument of get_data ensures that
the arguments, data, and status for the New Car Reviews data manager
are uniquely identifiable. Assuming the get_data method of NewCarListingsDataManager is passed an
associative array member called new_car_listings for its $load_data argument (per the same
convention), the data structure returned by the New Car Listings data
manager will be similar to the one shown in Example 6.9. This structure
reflects nicely that the New Car Listings data aggregates some New Car
Reviews data.
Example 6.9. Data from a data manager extended via aggregation
array ( "new_car_listings" => array ( // Data from the New Car Reviews data manager, by which the // New Car Listings data manager was extended via aggregation. "new_car_reviews" => array ( "0" => array ( "name" => "2009 Honda Accord", "price" => "21905", "link" => "http://.../reviews/00001/" ), ... ), // Other data retrieved by the New Car Listings data manager. ... ) )<a id="I_indexterm6_d1e8276" class="indexterm"></a><a id="I_indexterm6_d1e8277" class="indexterm"></a><a id="I_indexterm6_d1e8278" class="indexterm"></a>
How do you create a mission-critical site that provides exceptional performance while remaining flexible, adaptable, and reliable 24/7? Written by the manager of a UI group at Yahoo!, this book offers practical steps for building rock-solid applications that remain effective even as you add features, functions, and users. You'll learn how to develop large web applications with the extreme precision required for other types of software.




Help









