5

This is question about class relationships not class functionality.

Currently my DBConnection and DBQuery classes are two separate objects

class DBConnection {
    public $dbh;

    __construct() {
       $this->dbh = ... //Establish Connection to db
    }
}

class DBQuery {
    private $dbh;

    __construct(PDO $dbh) {
       $this->dbh= $dbh;
    }

    public runSQLQuery($query) {
       $result = $this->dbh->execute($query);
       $return $result;
    }

}

$dbh = new DBConnection();
$DBQuery = new DBQuery($dbh);
$DBQuery->executeSQLQuery("SELECT * FROM mytable");

So i injecting DBConnection to DBQuery.

1st Question - can i have them merged as one object instead as $dbh is unlikely to be used in any other class than DBQuery. Is this bad practice to group them, why?

class DBQuery {
    private $dbh;

    __construct() {
       $this->dbh = ... //Establish Connection to db
    }


    public runSQLQuery($query) {
       $result = $this->dbh->execute($query);
       $return $result;
    }

}


$DBQuery = new DBQuery();
$DBQuery->executeSQLQuery("SELECT * FROM mytable");

2nd Question - If merging is No-No then, how about extending, it keeps DBConnection class separate so it can be used by another class if needed, class DBQuery simply extends class DBConnection. They seem to be logically related so is this bad practice also, why?

class DBConnection {
    public $dbh;

    __construct() {
       $this->dbh = ... //Establish Connection to db
    }
}

class DBQuery extends DBConnection {

    __construct() {
       parent::__construct()
    }

    public runSQLQuery($query) {
       $result = $this->dbh->execute($query);
       $return $result;
    }

}

$DBQuery = new DBQuery();
$DBQuery->executeSQLQuery("SELECT * FROM mytable");

Bottom line is i am trying to find a solution in which i dont have to instantiate extra objects (it uses too many lines of code) as well as write unneeded lines of code inside classes just to pass one to another for no obvious reason.

P.S. I am familiar with SOLID OOD and Separation of Concerns however i still see no forecast for keeping this two classes separate.

  • Conceptually, a query and a connection are two different things. A query uses a connection, but doesn't have anything in common with it to imply inheritance. – devnull Nov 22 '16 at 20:37
  • Well in a real world neither connection or query are objects, they more like actions that are pretty related to me. Plus they only used together all the time never separate so why i keep them in two instances. why i cannot simply save myself few lines of code and merge them. Why i got to think OO all the time vs common sense? – Bananas Nov 22 '16 at 20:40
  • So, by your logic, if Apple and Animal are actions what's animal.Eat(apple)? – devnull Nov 22 '16 at 20:45
  • in real world Apple is an particular object, Animal is group of particular objects (animals). Database connection is action of establishing electric signal between computers, not object. network packets traveling over internet would be objects however connection to database is an action, query to database is also an action someone making. Dog peeing is object or action? In my logic database class is object while connection and query are its methods. – Bananas Nov 22 '16 at 21:33
  • Sending a query to the database is an action. The query itself is an object. Connecting to the database is an action. The connection is an object with actions like close(). – Ivo van der Veeken Dec 2 '16 at 16:04
1

The (correct) decision to separate these two classes has more to do with the Single Responsibility Principal:

Wikipedia:

The single responsibility principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility. Robert C. Martin expresses the principle as follows:

"A class should have only one reason to change."

Emphasis, mine.

If the way you establish a database connection changes, how should that have any affect on executing a command?

If the way a command is executed against an already established connection, how should that have any affect on the way a connection is opened?

Separating the two allows you to refactor how connections are managed without impacting code already in use for executing queries, and vice-versa.


As an addendum, your DbQuery class really should require a DBConnection object in its constructor. This allows for looser coupling between the two classes, as your query object doesn't have to know how to get and open a connection. Something else does that for it.

  • link In his book Robert C. Martin saying on page 112 If, on the other hand, the application is not changing in ways that cause the the two responsibilities to change at differen times, then there is no need to separate them. Indeed, separating them would smell of Needless Complexity. There is a corrolary here. An axis of change is only an axis of change if the changes actually occurr. It is not wise to apply the SRP, or any other principle for that matter, if there is no symptom. – Bananas Nov 22 '16 at 23:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.