1

We need to retrieve data in the form of entities

We have DAOs that hit a DB

But sometimes we need to parse (local) XMLs to retrieve essentially the same entities

Should we have a separate type for that (say, EntityParser)? Or should we simply create another DAO implementation? For example, if we have interface PatientDao that returns Patients we may create an XmlPatientDao implementation that fetches them from a local XML (parses nodes etc.) — in addition to an already written implementation that queries a DB

In other words, is it still DAO? It stands for "data access object", not "database access object". Or is it implied that DAOs only communicate with a DB and never perform any parsing of local files? I'm a bit confused on the terminology

Suppose, the answer is "yes", and I should use one DAO abstraction for both cases, PatientDao in my case. But what if a type has to fetch entities from both a DB and XML files (not simultaneously)? I can't think of any good solution to this yet. Imagine its constructor: PatientService(PatientDao dbDao, PatientDao xmlDao). Not safe at all (a programmer can mess up the order of args). Should there be (probably, marker) subinterfaces, DbPatientDao and XmlPatientDao? But then I sort of expose what is supposed to be an implementation detail

It's an unsolvable conundrum, it seems

0

1 Answer 1

2

You are correct that "DAO" means Data Access Object:

In software, a data access object (DAO) is a pattern that provides an abstract interface to some type of database or other persistence mechanism.

(emphasis, mine)

This implies an interface and one or more concrete implementations. Your idea of a implementation for a database and another implementation for XML is precisely how this pattern is meant to be used.

Regarding your comment:

What if a type has to fetch entities from both a DB and XML files (not simultaneously)? I can't think of any good solution to this yet. Imagine its constructor: PatientService(PatientDao dbDao, PatientDao xmlDao). Should there be (probably, marker) subinterfaces, DbPatientDao and XmlPatientDao?

It's all about the DAO interface consumed by the rest of the application. The implementation can fetch from any data source necessary — including multiple data sources. So what if it requires two other DAO's to do its job? Separate them if it makes sense. Combine them if it makes your life easier. It's all about the abstraction provided by the DAO interface. Everything else is there to support that interface.

You might be over-thinking this, but there are some complexities here.

Consider for a moment that your patient DAO needs to access a relational database and an XML file. You can make these private separate methods in the DAO, or spin that functionality off into other classes. Another useful concept might be the Gateway pattern:

An object that encapsulates access to an external system or resource

The external system can be a relational database. The external resource can be an XML file. Perhaps your patient DAO requires two gateways: a PatientDatabaseGateway and a PatientXmlFileGateway.

db = new PatientSqlLiteDatabaseGateway(connectionString);
xml = new PatientXmlFileGateway(xmlFilePath);
dao = new PatientDataAccess(db, xml);

If necessary, you can declare interfaces for each of those gateways:

public interface PatientDatabaseGateway {
    // methods
}

public interface PatientXmlGateway {
    // methods
}

The DAO becomes:

public class PatientDataAccess implements PatientDAO {
    private final PatientDatabaseGateway db;
    private final PatientXmlGateway xml;

    public PatientDataAccess(PatientDatabaseGateway db, PatientXmlGateway xml) {
        this.db = db;
        this.xml = xml;
    }

    // methods that use either gateway
}

Internally, the PatientDataAccess object can decide which data source to use. There is a slight snag in this, though. As soon as calling code needs to know which storage mechanism it is dealing with, you simply need two data access objects. Dealing with data access through an abstraction is no longer useful. In this case, I would deal with the concrete sub types directly, and only declare interfaces if I need to write unit tests.

8
  • Thank you. What if a type has to fetch entities from both a DB and XML files (not simultaneously)? I can't think of any good solution to this yet. Imagine its constructor: PatientService(PatientDao dbDao, PatientDao xmlDao). Should there be (probably, marker) subinterfaces, DbPatientDao and XmlPatientDao? Commented Oct 11 at 16:16
  • @SergeyZolotarev: I updated my answer, if that helps. Commented Oct 11 at 17:35
  • "Separate them if it makes sense. That's exactly what curious about, does it make sense? You either have an unsafe clutter in the constructor or expose an implementation detail. How would you resolve it? Commented Oct 11 at 17:45
  • @SergeyZolotarev - and another update. Commented Oct 11 at 17:48
  • BTW, constructors are concrete, so concrete details in a constructor is not "unsafe clutter." That is precisely the place for the "unsafe clutter" to go. Commented Oct 11 at 17:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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