Sql2oCourseDao
The Sql2oCourseDao
is going to be our implementation of the CourseDao
interface. Add this class to your project.
import org.sql2o.Sql2o;
import java.util.List;
public class Sql2oCourseDao implements CourseDao {
private final Sql2o sql2o;
/**
* Construct Sql2oCourseDao.
*
* @param sql2o A Sql2o object is injected as a dependency;
* it is assumed sql2o is connected to a database that contains a table called
* "courses" with two columns: "offeringName" and "title".
*/
public Sql2oCourseDao(Sql2o sql2o) {
this.sql2o = sql2o;
}
@Override
public Course create(String offeringName, String title) throws DaoException {
return null; // stub
}
@Override
public Course read(String offeringName) throws DaoException {
return null; // stub
}
@Override
public List<Course> readAll() throws DaoException {
return null; // stub
}
@Override
public List<Course> readAll(String titleQuery) throws DaoException {
return null; // stub
}
@Override
public Course update(String offeringName, String title) throws DaoException {
return null; // stub
}
@Override
public Course delete(String offeringName) throws DaoException {
return null; // stub
}
}
At the moment, this class has placeholders (stub) for implementation of the operations of CourseDao
. Additionally, there is a Sql2o
filed and a constructor that initializes it. The constructor takes in a Sql2o
parameter to do this. In effect, this design means the responsibility of constructing a Sql2o
is not on Sql2oCourseDao
itself. This is consistent with our desire to write highly cohesive classes but it creates a tight coupling. The Sql2oCourseDao
makes certain assumptions about the Sql2o
object a client provides it with. Namely that it is connected to a database, and the database contains a courses
table with two columns: offeringName
and title
.
It is common that a DAO does not establish its own database connection and relies on a client to pass it to its constructor. This pattern is known as dependency injection.
The primary advantage of dependency injection is the separation between the DAO and the database used to provide persistence which can be expected to evolve independently.
Aside: Note the CourseDao
collaborates with the Course
class to fulfill the responsibilities related to providing persistence mechanism for course data. We could have had the Course
class take on these responsibilities, after all, operations like "create course", "update course", $\dots$ are about a course. Instead, we have extracted the persistence mechanism out of the Course
into its own entity. This is a good thing! It is in-line with "increasing cohesion;" the Course
class is only responsible to model a course; it does not need to know about some type of database or other persistence operations. If we change the persistence process, the Course
class remains intact (and therefore other entities in the code that collaborate with Course
have no reason to change).
There is, however, a dependency relationship between Course
and CourseDao
. This dependency is unavoidable; it is the price we pay to increase cohesion. The resulted coupling is not that bad! The CourseDao
(or more concretely, any class that implements it) only relies on the public methods of the Course
class. The public methods (the interface of) a class is expected to be stable (ideally, it never changes).