HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Is it a good practice to use only one database instance?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
practicedatabaseinstanceonegooduseonly

Problem

I want to ask whether is good practice to have single instance of database connection or declare new every times when we needed? I have this two designs shown in below:

This is database class:

host = $host;
        }

        if(isset($dbname) && !empty($dbname)) {
            $this->dbname = $dbname;
        }

        if(isset($username) && !empty($username)) {
            $this->username = $username;
        }

        if(isset($passwd) && !empty($passwd)) {
            $this->passwd = $passwd;
        }

        parent::__construct("mysql:dbname=$this->dbname;host=$this->host", $this->username, $this->passwd, NULL);
        parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        parent::setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    }

}
?>


Method 1: Dependency Injection

db = $db;
    }

    //Some update and insert below here
}

class Employee {
    private $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }

    //Some update and insert below here
}
?>


So, I will do this when I want to use the classes:

update($id,$data);

    $emp = new Employee($db);
    $emp->delete($id);
?>


or the other ways?

Method 2:

db = new Database();
    }

    //Some update and insert below here
}

class Employee {
    private $db;

    public function __construct() {
        $this->db = new Database();
    }

    //Some update and insert below here
}
?>


and when I want to use it I will:

update($id,$data);

    $emp = new Employee();
    $emp->delete($id);
?>


Which method is preferable or better? Offer an explanation if possible.

Solution

In this situation, I would say to prefer dependency injection. The reasons being:

-
You may not only ever run your code against a single database. For example, if your project grows large, you may have separate databases for different regions about the world (North America, Europe, etc). You could also easily have a test database, or a stable-test and an experimental-test, etc., etc. All of this can be controlled by configuration. Of course, you could put this configuration-based logic inside your Database class, but..

-
You may want different types of databases. Right now you might be using MySQL; later you may use Oracle, or PostgreSQL, or an in-memory database, or a mock database that has no backing store. Using dependency injection lets you very easily switch between these, provided you adhere to the same interface for all of them. You may even start in one region where MySQL is readily available, then expand to another where you can only get Oracle hosts. Changing types is useful for easily changing technologies later, but also because..

-
Using dependency injection makes it easier to test. You can test against an in-memory database for your unit tests, and against an actual remote database during integration testing.

Of course, dependency injection isn't a cure-all and has its own problems, such as:

-
Dependency injection is infectious. Somebody somewhere has to know how to construct your object. If your object has its dependencies injected, then it has to know how to construct the dependencies. If it doesn't know that, then the next level up has to know, or the next level from there, or.. etc, etc. The result of this is that..

-
Your classes become more tightly coupled. Some of your classes become aware of the dependencies of their other classes, by virtue of having to inject their dependencies. A good dependency injection framework can help with this. I don't use PHP much so I'm not aware of any.

This is Code Review, of course, and I'd be remiss if I didn't comment on your code itself:

update($id,$data);

    $emp = new Employee();
    $emp->delete($id);
?>


To me (admittedly a non-PHP guy) this is an extremely strange pattern. A User and an Employee would seem to be model classes, but here you have them making database calls - you're mixing concerns for these objects. This is a great situation to use the data access object, or DAO, pattern:

pdo = $pdo;
        }

        public function saveUser(User $user) {
            // insert pdo insert/update logic here
        }
    }

    class InMemoryUserDao implements UserDao {
        // in-memory implementation here..
    }
?>

Code Snippets

<?php  
    $user = new User();
    $user->update($id,$data);

    $emp = new Employee();
    $emp->delete($id);
?>
<?php
    class User {
        private $data;

        public function __construct() {
            $data = "some_data";
        }
    }

    interface UserDao {
        public function saveUser(User $user);
    }

    // A DAO implementation which knows how to communicate using
    // PDO objects. Can be injected with a PDO object configured
    // to connect to any host, DBMS, etc.
    class PDOUserDao implements UserDao {
        private $pdo;

        public function __construct(PDO $pdo) {
            $this->pdo = $pdo;
        }

        public function saveUser(User $user) {
            // insert pdo insert/update logic here
        }
    }

    class InMemoryUserDao implements UserDao {
        // in-memory implementation here..
    }
?>

Context

StackExchange Code Review Q#60208, answer score: 4

Revisions (0)

No revisions yet.