Data Access Objects (DOAs)

In my experience, I have found that the best way to treat DAOs is to consider them to be a specialized type of factory. We can use the DAO to access a database or other service, retrieve the data, and then return a new instance of a class that contains the retrieved data. Typically, a DAO is a singleton, since we only want one a single point of connection to any given external resource. In this case, we simply make the actual connection a singleton, and pass that into the DAO. namespace FunctionalLayer.Daos { public class Database { const string queryString = "storedProc"; ... // private fields for database connection private DBDataFactory _factory; public Database(SingletonConnection databaseConnection) { ... } public virtual ReturnType ExecuteQuery(...parameters...) { var returned = Construct(); // execute query and fill out values in returned return returned; } protected ReturnType Construct() { return new ReturnType(); } } } namespace TraceableLayer.Daos { public class Database : FunctionalLayer.Daos.Database { private Tracer _tracer; public DataBase(SingletonConnection databaseConnection, Tracer tracer) : base(databaseConnection) { _tracer = tracer; } public virtual ReturnType ExecuteQuery(...parameters...) { _tracer.OpenNode("Database.ExecuteQuery"); _tracer.AddNode("arg0", arg0); ... additional parameters var results = base.ExecuteQuery(parameters); _tracer.AddAttribute("result", results); _tracer.CloseNode(); return value; } protected ReturnType Construct() { return new TraceableLayer.Objects.ReturnType(); } } }

If the DAO simply reads data from a source, and creates an object then its design is fairly straightforward. However, if the DAO updates a database, or calls another service to update information, then you may not want that update to actually be applied. Instead, you can have the Traceable Layer DAO intercept the call, add the appropriate information to the Trace data, and then simply not execute the query (or not call the service).

Another consideration to keep in mind is how much of the data from the DAO should be put in the stream. For example, a database query may only return a few rows of data, and so it is ok to put everything in the trace data. However, if the query returns 100,000 rows, that might be a bit much. My personal bias is default to including all of the data until doing so causes problems. Many times I have encountered situations where I did not receive enough data, and thus had to request more (and thus slowed down resolving the issue). The number of times I received too much data has been very rare.

For more on this discussion, see Tool Design.

Next: Meta-Factories