I am building some classes (in PHP, although this question extends to other OOP languages as well) which hold information from a database. As such, I want to create an Interface: "syncable".
interface syncable{
protected function _pushToDB();
protected function _pullFromDB();
}
The problem I am encountering is that I want "syncable" to also have a method which (probably) never changes and variable to go with:
protected $sync = 0;
public function sync(){
if($this->sync == 0){
// DB in sync with class; Do nothing.
}
if(this->sync == 1){
$this->_pushToDB();
$this->sync = 0;
}
if(this->sync == -1){
$this->_pullFromDB();
$this->sync = 0;
}
}
As variables are changed in an implemented class, or the database is updated elsewhere, the $sync variable is updated to properly reflect the type of sync needed, then sync() can be called at some point which in turn calls the proper implemented method. While _pushToDB() and _pullFromDB() are very specialized per class, sync() will remain constant between most, if not all, classes.
Since the classes implementing "syncable" such as "users", "foo", and "bar" have no real relation to "syncable" and may need to extend other classes, "syncable" should be an interface rather than an abstract class.
So my question is, what is the best way of accomplishing this? Must I copy-paste my sync() function into every class which implements "syncable"? Do I create an abstract class and hope no class which extends "syncable" ever needs to extend anything else? (Since PHP and many OOP don't support multiple-inheritance) Is there some other PHP solution which would better fit this situation? Are there any generic OOP solutions for this problem?
You should have a look at php traits, you can create this traits and then use them whereever you want/need to use them, is a part of the multi-inheritance principle:
http://php.net/manual/en/language.oop5.traits.php
Related
Sorry if this is a duplicate question or a common design principle, I have searched around but was unable to find any answers to this question. I'm probably just searching with the wrong keywords.
I have been looking at a popular library Sabre/Event (https://sabre.io/event/) and in the code there is a simple class/inheritance model that I am trying to understand:
The class EventEmitter implements EventEmitterInterface and uses EventEmitterTrait (see below for code).
There is a comment in EventEmitterTrait above the class which says:
* Using the trait + interface allows you to add EventEmitter capabilities
* without having to change your base-class.
I am trying to understand why this comment says this, and why it allows adding capabilities without changing the base class, and how that is different from just putting the routines into EventEmitter itself.
Couldn't you just extend EventEmitter and add capabilities in the derived class?
Simplified code:
// EventEmitter.php
class EventEmitter implements EventEmitterInterface {
use EventEmitterTrait;
}
// EventEmitterInterface.php
interface EventEmitterInterface {
// ... declares several function prototypes
}
// EventEmitterTrait.php
trait EventEmitterTrait {
// ... implements the routines declared in EventEmitterInterface
}
You're basically asking two questions here.
What are interfaces and why are they useful?
What are traits and why are they useful?
To understand why interfaces are useful you have to know a little about inheritance and OOP in general. If you've ever heard the term spaghetti code before (it's when you tend to write imperative code that's so tangled together you can hardly make sense of it) then you should liken that to the term lasagna code for OOP (that's when you extend a class to so many layers that it becomes difficult to understand which layer is doing what).
1. Interfaces
Interfaces diffuse some of this confusion by allow a class to implement a common set of methods without having to restrict the hierarchy of that class. we do not derive interfaces from a base class. We merely implement them into a given class.
A very clear and obvious example of that in PHP is DateTimeInterface. It provides a common set of methods which both DateTime and DateTimeImmutable will implement. It does not, however, tell those classes what the implementation is. A class is an implementation. An interface is just methods of a class sans implementation. However, since both things implement the same interface it's easy to test any class that implements that interface, since you know they will always have the same methods. So I know that both DateTime and DateTimeImmutable will implement the method format, which will accept a String as input and return a String, regardless of which class is implementing it. I could even write my own implementation of DateTime that implements DateTimeInterface and it is guaranteed to have that method with that same signature.
So imagine I wrote a method that accepts a DateTime object, and the method expects to run the format method on that object. If it doesn't care which class, specifically, is given to it, then that method could simply typehint its prototype as DateTimeInterface instead. Now anyone is free to implement DateTimeInterface in their own class, without having to extend from some base class, and provide my method with an object that's guaranteed to work the same way.
So in relation to your EventEmitter example, you can add the same capabilities of a class (like DateTime) to any class that might not even extend from DateTime, but as long as we know it implements the same interface, we know for sure it has the same methods with the same signatures. This would mean the same thing for EventEmitter.
2. Traits
Traits, unlike interfaces, actually can provide an implementation. They are also a form of horizontal inheritance, unlike the vertical inheritance of extending classes. Because two completely different class that do not derive from the same base class can use the same Trait. This is possible, because in PHP traits are basically just compiler-assisted copy and paste. Imagine, you literally copied the code inside of a trait and just pasted it into each class that uses it right before compile time. You'd get the same result. You're just injecting code into unrelated classes.
This is useful, because sometimes you have a method or set of methods that prove reusable in two distinct classes even though the rest of those classes have nothing else in common.
For example, imagine you are writing a CMS, where there is a Document class and a User class. Neither of these two classes are related in any meaningful way. They do very different things and it makes no sense for one of them to extend the other. However, they both share a particular behavior in common: flag() method that indicates the object has been flagged by a user for purposes of violating the Terms of Service.
trait FlagContent {
public function flag(Int $userId, String $reason): bool {
$this->flagged = true;
$this->byUserId = $userId;
$this->flagReason = $reason;
return $this->updateDatabase();
}
}
Now consider that perhaps your CMS has other content that's subject to being flagged, like a Image class, or a Video class, or even a Comment class. These classes are all typically unrelated. It probably wouldn't make much sense just to have a specific class for flagging content, especially if the properties of the relevant objects have to be passed around to this class to update the database, for example. It also doesn't make sense for them to derive from a base class (they're all completely unrelated to each other). It also doesn't make sense to rewrite this same code in every class, since it would easier to change it in one place instead of many.
So what seems to be most sensible here is to use a Trait.
So again, in relation to your EventEmitter example, they're giving you some traits you can reuse in your implementing class to basically make it easier to reuse the code without having to extend from a base class (horizontal inheritance).
Per Sabre's Event Emitter's docs on "Integration into other objects":
To add Emitter capabilities to any class, you can simply extend it.
If you cannot extend, because the class is already part of an existing
class hierarchy you can use the supplied trait.
So in this case, the idea is if you're using your own objects that already are part of a class hierarchy, you may simply implement the interface + use the trait, instead of extending the Emitter class (which you won't be able to).
The Integration into other objects documentation says:
If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait".
I understand it's a workaround when you already have an OOP design you don't want to alter and you want to add event capabilities. For example:
Model -> AppModel -> Customer
PHP doesn't have multiple inheritance so Customer can extend AppModel or Emitter but not both. If you implement the interface in Customer the code is not reusable elsewhere; if you implement in e.g. AppModel it's available everywhere, which might not be desirable.
With traits, you can write custom event code and cherry-pick where you reuse it.
This is an interesting question and I will try to give my take on it. As you asked,
What is the purpose of using traits to define functions for an interface ?
Traits basically gives you the ability to create some reusable code or functionality which can then be used any where in your code base. Now as it stands, PHP doesn't support multiple inheritance therefore traits and interfaces are there to solve that issue. The question here is why traits though ?? Well imagine a scenario like below,
class User
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
public function name(){}
public function friends(){}
// and a few other methods
}
Now lets say that we have a post class which has the same logic as user and that can be achieved by having hasRatings() and hasBeenFavorited() methods. Now, one way would be to simply inherit from User Class.
class Post extends User
{
// Now we have access to the mentioned methods but we have inherited
// methods and properties which is not really needed here
}
Therefore, to solve this issue we can use traits.
trait UserActions
{
public function hasRatings()
{
// some how we want users to have ratings
}
public function hasBeenFavorited()
{
// other users can follow
}
}
Having that bit of logic we can now just use it any where in the code where ever it is required.
class User
{
use UserActions;
}
class Post
{
use UserActions;
}
Now lets say we have a report class where we want to generate certain report on the basis of user actions.
class Report
{
protected $user;
public function __construct(User $user)
{
$this->user = $user
}
public function generate()
{
return $this->user->hasRatings();
}
}
Now, what happens if i want to generate report for Post. The only way to achieve that would be to new up another report class i.e. maybe PostReport.. Can you see where I am getting at. Surely there could be another way, where i dont have to repeat myself. Thats where, interfaces or contracts come to place. Keeping that in mind, lets redefine our reports class and make it to accept a contract rather than concrete class which will always ensure that we have access to UserActions.
interface UserActionable
{
public function hasRatings();
public function hasBeenFavorited();
}
class Report
{
protected $actionable;
public function __construct(UserActionable $actionable)
{
$this->actionable = $actionable;
}
public function generate()
{
return $this->actionable->hasRatings();
}
}
//lets make our post and user implement the contract so we can pass them
// to report
class User implements UserActionable
{
uses UserActions;
}
class Post implements UserActionable
{
uses UserActions;
}
// Great now we can switch between user and post during run time to generate
// reports without changing the code base
$userReport = (new Report(new User))->generate();
$postReport = (new Report(new Post))->generate();
So in nutshell, interfaces and traits helps us to achieve design based on SOLID principles, much decoupled code and better composition. Hope that helps
I am looking to tidy up some code I have inherited. Essentially we have two classes (A + B) that extend off two separate classes that do various things differently, however A and B also share some functions. At present the functions are copy and pasted between the two and obviously I know this is wrong. I am looking to see if there it a solution to this so that I only have to define the functions once so that both A and B can use these. Any help would be great!
From php 5.4 you could use Traits.
Here is example from manual
<?php
trait ezcReflectionReturnInfo {
function getReturnType() { /*1*/ }
function getReturnDescription() { /*2*/ }
}
class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
?>
In an ideal world, it's possible that what you really want there is multiple inheritance, but that is not supported by PHP (or many other languages) as it is much more complex than single inheritance.
One alternative to consider is arranging your code so that both classes eventually inherit from some common ancestor, so that you can put your code here. This may not always be desirable or practical, however, particularly if some of the classes extended are from different libraries with no shared dependency.
You might be able to alter the ancestry of some of your classes by using "composition" and "delegation" rather than direct inheritance. The basic idea is that rather than class B extending class A, you store an instance of class A as a property of class B; when certain methods of class B are called, they call corresponding methods of the A instance, while other methods of B are completely separate, and can be inherited from somewhere else. The magic method __call can be useful for implementing this without having to know every possible delegated method in advance.
As of PHP 5.4, there is a form of "horizontal code reuse" called Traits. Traits are sometimes described as "compiler-assisted copy-and-paste", because they don't represent any OOP relationship between the classes where they are used, only a way of editing the functions in one place.
If the functions are public, you might want to declare the classes as implementing an Interface, which lets other code check that a set of methods are available, usually by using the instanceof operator. This can be used in combination with a Trait, which contains the details of how those methods are implemented.
So ive finally gotten round to playing with traits and they are very handy, the problem that i have been having is that i want to have some traits to add functionality to my data objects.
In of itself this is simple except that in doing so im using methods that are defined in my base data object
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object. I had thought about putting a check in the _addToUpdate method but ideally i would like an error to be shown when creating the instance.
I have come up with a solution that works but makes me feel a bit dirty and is far from ideal
abstract class Base_Object {
protected function _addToUpdate($field, $value) {
...
}
...
}
trait Extended_Object {
abstract protected function _addToUpdate($field, $value);
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
By adding an abstract method to the Extended_Object i then can at least be sure that an error will be show if the method i need in Base_Object isnt present but i am not guaranteed that the method in question will actually do what i want it to do.
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Im hoping that someone has found a way to do this or at least a better solution than mine.
Note: i know that i could do this with a constructor but that would only be viable when using a single trait if i decided at a later date to create anther few object extension traits its going to get very messy very quickly
Edit: i do realize that traits arnt really designed for what im trying to do but they do at least in part allow me to get around the problem of single inheritance and i know im not the only dev planning to use them in this way
Well (IMHO) the problem exists with the way you are using traits which is technically anti-pattern.
First, What are traits and why should I use them:
To quote from one of the comments in php.net
The best way to understand what traits are and how to use them is to
look at them for what they essentially are: language assisted copy
and paste.
If you can copy and paste the code from one class to another (and
we've all done this, even though we try not to because its code
duplication) then you have a candidate for a trait.
Now even that traits lets you use members of the class which is using them, that does not mean you should do that. back to SRP, this is a real violation.
PHP lets you do echo $_POST['XSS data'] but that does not mean you should do it. So, regardless to the way you want to strict your trait usage, what you are actually doing is that you are introducing the issue and you are trying to solve it
so to answer your question, simply redesign your code in order for you not to use class methods and members based on an assumption that each class which will use the trait should have these methods and members.
I think your solution with an abstract function is precisely what that facility is intended for. I agree with your gut feeling:
i am not guaranteed that the method in question will actually do what i want it to do
However, this is the same assumption you make whenever you use an interface: the only thing that is asserted is that a method exists with the correct signature (which in PHP amounts mostly to its name and number of parameters). There is no way to know that the function actually behaves in a particularly useful way when given those parameters.
In the case of a trait, an abstract method is effectively the same kind of contract as an interface: "in order to use this trait, you must provide these pre-requisites".
I would also note that common description of traits is "automated copy and paste", so it should generally be thought of as separate from object hierarchies. More technically, it represents "horizontal code reuse", not "multiple inheritance". For example, you can define a trait that allows a class to implement an interface, but to the outside code, it is the interface that is important, not the trait.
I am faced with a similar problem, however with multiple subclasses inheriting from the base class.
It would make sense at this point to put trait abstract declarations into some sort of include file and as a trait itself, e.g.:
abstract class Base_Object {
use BaseObjectTrait;
...
}
trait BaseObjectTrait {
protected function _addToUpdate($field, $value) {
...
}
}
trait BaseObjectTraitPrototypes {
abstract protected function _addToUpdate($field, $value);
}
trait Extended_Object {
use BaseObjectTraitPrototypes;
public function doSomeStuff() {
...
$this->_addToUpdate($someVar, $someOtherVar);
}
...
}
class User extends Base_Object {
use Extended_Object;
...
}
Can anyone think of a more elegant solution than this? I'm using the term 'prototype' very loosely here from a C programming sense. 'Header' files are likewise from a C programming context but still not ideal. Can anyone think of a more concise concept for the problem domain, something php-fig acceptable perhaps?
My problem is then if someone else in my team decides to use the Extended_Object trait on an object that doesnt extend Base_Object.
:
Ideally i would like to be able to run something like the code below when an object is instantiated using the Extended_Object trait
if (!($this instanceof Base_Object)) {
throw new Inheritance_Exception("Base_Object");
}
Maybe I'm missing something, but if this trait should only ever be applied to instances of Base_Object, then it sounds as if this "trait" should be a subclass of the Base_Object and not a trait at all?
The User class then extends this Extended_Object (a subclass), rather than useing the Extended_Object (a trait).
From: http://php.net/manual/en/language.oop5.traits.php
A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I have an application which defines certain actions on common object types.
For example, you can have forum post and images. For each forum post and image you can do the following actions: recommend, comment, rate.
I have currently defined a static class
class CoreObjectUtil
{
protected static $_objObjKey = null;
protected static $_objTypeKey = null;
public static function getComments (...) {...}
public static function getCommentsArray (...) {...}
public static function getRatings (...) {...}
public static function getRatingsArray (...) {...}
}
which is then subclassed like this
class ForumPostUtil extends CoreObjectUtil
{
protected static $_objObjKey = 'forumpost';
protected static $_objTypeKey = 'FP';
}
to provide the relevant functionality for forum posts. The 2 parameters suffice to let the generic code in CoreObjectUtil know what to do for each object type for which these functions are applicable.
To use these functions, I am calling the selectPostProcess() class in my instance classes like this:
public function selectPostProcess ($data)
{
$data = ForumPostUtil::mergeRatings ($data);
$data = ForumPostUtil::mergeComments ($data);
...
}
This works well and keeps the main code centralized in the CoreObjectUtil class with its subclasses providing the data setup to let the code in CoreObjectUtil know what to do.
An alternative approach would be to move the code from CoreObjectUtil into a base instance class which is then inherited in my instance classes. So rather than calling static methods from CoreObjectUtil I would be doing method calls like $this->getComments().
Either approach would work just fine from a functionality type point of view. I'm wondering however what ObjectOriented design guidelines and experienced ObjectOriented developers think of these two approaches. Which way of doing this is preferable and why?
I would appreciate any thoughts/insights on this matter. I can code either way without problem, but I'm having a tough time deciding which route to take.
That code you have now is, I think, the most procedural approach ever posing as OOP i.e what you have now is at the opposite side of OOP. Using the class keyword doesn't make it OOP.
First of all, you should forget about static, it's not that it's bad ot use but it's so easily abused that you really have to try first if the functionality can belong to an object modelling a domain concept (in your case forum related). Only if it doesn't make sense this way, you'll have it as a static method somewhere in a utility class.
Truth be told you have to redesign yur app around the OOP mindset, that is to define classes with behaviour which model a specific concept or process and which have only one responsaiblity. More over you should not mix things like business objects (object which model the forum concepts) with persistence concerns i.e don't put in the same object business functionality and database access. Use a separate class for accessing storage.
Use the Repository pattern to separate business layer from the persistence layer. Try not to mix together create/update functionality with querying IF it complicates things. Use a separate read model specifically for querying in that case.
The code you show us is about querying. You can have a simple DAO/Repository (call it what you want in this case) like this
class ThreadViewData
{
public $Id ;
public $Title;
public $Comments; //etc
}
class ThreadsQueryRepository
{
//we inject the db access object , this helps with testing
function _construct($db) { }
public function GetThread($id){ } //this returns a ThreadViewData
}
The postPRocess functionality is a service that can Merge Ratings and Comments. But maybe the merge functionality is more suitable to the Rating and Comment objects. I don't know the domain to actually give a valid suggestion.
Point is, you have to think in objects not in functions and right now all you have is functions.
I'm building a class to handle Paypal IPNs as part of a project, and since I already know i'm going to need to use it again in at least two more upcoming jobs - I want to make sure I structure it in a way that will allow me to re-use it without having to recode the class - I just want to have to handle changes in the business logic.
The first part of the question is re. interfaces. I haven't quite grasped their usefulness and when/where to deploy them. If I have my class file ("class.paypal-ipn.php"), do I implement the interface in that file?
Here's what i'm working with so far (the function list is incomplete but its just for illustration):
CLASS.PAYPAL-IPN-BASE.PHP
interface ipn_interface {
//Database Functions
// Actual queries should come from a project-specific business logic class
// so that this class is reusable.
public function getDatabaseConnection();
public function setDatabaseVars($host="localhost",$user="root",$password="",$db="mydb");
public function dbQuery($SQL);
//Logging Functions
public function writeLog($logMessage);
public function dumpLogToDatabase();
public function dumpLogToEmail();
public function dumpLogToFile();
//Business Logic Functions
private function getTransaction($transactionID);
//Misc Functions
public function terminate();
}
class paypal_ipn_base {
//nothing to do with business logic here.
public function getDatabaseConnection() {
}
public function setDatabaseVars($host="localhost",$user="root",$password="",$db="mydb") {
}
public function dbQuery($SQL) {
}
}
CLASS.PAYPAL-IPN.PHP
final class paypal_ipn extends paypal_ipn_base implements ipn_interface {
//business logic specific to each project here
private function getTransaction($transactionID) {
$SQL = "SELECT stuff FROM table";
$QRY = this->dbQuery($SQL);
//turn the specific project related stuff into something generic
return $generic_stuff; //to be handled by the base class again.
}
}
Usage
In this project:
Require the class files for both the base, and the business logic class.
Instatiate *paypal_ipn*
Write code
In other projects:
Copy over the base IPN class
Edit/rewrite the business logic class *paypal_ipn* within the constraints of the interface.
Instantiate *paypal_ipn*
Write code
So as you can see i'm literally just using it to define groups of related functions and add comments. It makes it easier to read, but of what (if any) other benefit is it to me - is it so that I can pull the extender and the base class together and force errors if something is missing?
stdClass Question
The second part of the question is building on the readability aspect. Within the class itself there is an ever increasing number of stored variables, some are set in the constructor, some by other functions - they relate to things such as holding the database connection vars (and the connection resource itself), whether the code should run in test mode, the settings for logging and the log itself, and so on...
I had started to just build them as per usual (again, below incomplete & for illustration):
$this->dbConnection = false;
$this->dbHost = "";
$this->dbUser = "";
$this->enableLogging = true;
$this->sendLogByEmail = true;
$this->sendLogTo = "user#domain.com";
But then I figured that the ever growing list could do with some structure, so I adapted it to:
$this->database->connection = false;
$this->database->host = "";
$this->database->user = "";
$this->logging->enable = true;
$this->logging->sendByEmail = true;
$this->logging->emailTo = "user#domain.com";
Which gives me a much easier to read list of variables when I dump the entire class out as I code & test.
Once complete, I then plan to write a project specific extension to the generic class where i'll keep the actual SQL for the queries - as from one project to another, Paypal's IPN procedure and logic won't change - but each project's database structure will, so an extention to the class will sanitize everything back into a single format, so the base class doesn't have to worry about it and will never need to change once written.
So all in all just a sanity check - before I go too far down this road, does it seem like the right approach?
if you are using a class autoloader, which I highly recommend, you would not want to keep the interface and the class in the same file so that the interface can autoload without needing to first load this one class that implements it.
For more info on autoloading:
http://php.net/manual/en/language.oop5.autoload.php
another thing you may want to consider is that a given class may impliment multiple interfaces, and multiple classes may implement the same interface.
interfaces are primarily used for various design patterns, to enforce rules, and to decouple a class from any dependent classes. when you decouple a class from its dependencies, it makes it much easier to modify code at a later time.
for instance, let's say you have a class A that takes in another class B as an argument, and this class is spread throughout your code. you want to enforce that only a class with a specific subset of methods can be accepted as this argument, but you do not want to limit the input to one concrete class and it's decendants. in the future, you may write an entirely different class that does not extend class B, but would be useful as an input for class A. this is why you would use an interface. it is a reusable contract between classes.
some would argue that since PHP is a dynamic language, interfaces are an unecessary complication, and that duck typing may be used instead. I find in large multi-user code bases however, that interfaces can save a lot of time, letting you know more about how one class uses another, without having to study the code in depth.
if you find yourself with a large list of variables that you have to pass around between objects or functions, they often do end up deserving a class of their own, but each case is different.
-- dependency injection example --
class A implements AInterface {
public function foo($some_var) {}
}
interface AInterface {
public function foo($some_var);
}
class B {
protected $localProperty;
// inject into the constructer. usually used if the object is saved in a property and used throughout the class
public function __construct(AInterface $a_object) {
$this->localProperty = $a_object;
}
// inject into a method. usually used if the object is only needed for this particular method
public function someMethod(AInterface $a_object) {
$a_object->foo('some_var');
}
}
you can now see that you can write another class that impliments a foo method (and the AInterface) and use that within class B as well.
as a real world example (used often), say you have a database class with particular methods that interact with the database (getRecord, deleteRecord). now lets say at a later time you find a reason to switch database rdbms. you now need to use entirely different SQL statements to accomplish the same goals, but since you used an interface for your type hinting, you can simply create a new class that impliments that interface, but impliments those same methods in entirely different ways as it interacts with a different rdbms. when creating this new class, you will know exactly what methods need to be written for this new class in order to fit into the same objects that need to use a database object. if you use a container class that you use to create objects and inject them into other objects, you would not need to change too much application code in order to switch databases classes, and therefore switch database rdbms. you could even use a factory class, which could limit your changes to one line of code to make this type of change (in theory).