I know a little bit about Object Oriented design, but I\'m not sure how to go about using those principles in my code. Here\'s what I\'m working on:
pub
To write less code but improve readability the the level of declaritive code you can swith to a dictionary with delegates for each database. That can easily be extended and is very readable. With that more functional approach in mind you get something like
void Query(Agency agency, Citation queryCitation)
{
Dictionary<string, Action<Agency, Citation>> QueryMap = new Dictionary<string, Action<Agency, Citation>>
{
{ "SQL", QueryOracle},
{ "PIC", QueryPic}
};
queryCitation.AgencyCode = agency.AgencyCode;
QueryMap[agency.ClientDb.Type](agency, queryCitation);
}
There are two OOP solutions polymorphism and Visitor pattern.
Is Agency a class you control? If so do something like this:
public abstract class GenericDb
{
public abstract void Query(parms);
}
In your Agency Class, you could have
public GenericDb ClientDb {get; set;}
Then have a SqlDb class like:
public class SqlDb : GenericDb
{
public void Query(parms);
}
public class PicDb : GenericDb
{
public void Query(parms);
}
Then this code:
public void Query(Agency agency, Citation queryCitation) {
queryCitation.AgencyCode = agency.AgencyCode;
switch (agency.ClientDb.Type) {
case "SQL":
QueryOracle(agency, queryCitation);
break;
case "PIC":
QueryPick(agency, queryCitation);
break;
}
}
becomes
public void Query(Agency agency, Citation queryCitation) {
queryCitation.AgencyCode = agency.AgencyCode;
agency.ClientDb.Query(queryCitation);
}
Because of inheritance, it will know that ClientDb has a base class of GenericDb. It will know by the type of the ClientDb parameter whether it should run the SqlDb or the PicDb or Oracle etc.
ADO.NET has a set of generic classes: DbCommand, DbConnection, etc... that also implement another set of generic interfaces: IDbCommand, IDbConnection, etc...
So you could use them, but it may become quite complicated in the end. The advantage of your solution is it's very readable. Plus maybe the pick database does not have any ADO.NET provider...
PS: I would replace the Type property type though, and use an enum instead.
You will likely want to implement the strategy pattern here. Basically, each of your possible "types" in your switch statement would become a class of its own that implements the same interface.
Applying the Strategy Pattern
You can then use a factory method that takes a "type" value as its parameter. That method would return the correct class (its return type is the interface mentioned above).
I would refactor to take advantage of an interface. I would probably make it something like:
public interface IQuery
{
void Execute(Agency agency, Citation query);
}
public class OracleQuery : IQuery
{
// Implementation
}
public class PickQuery : IQuery
{
// Implementation
}
You could then change the Agency class to store an instance of an IQuery
object rather than (or in addition to) the ClientDb
object:
public class Agency
{
public IQuery Query { get; set; }
}
And then in your initialization code (where you would normally set the ClientDb
property), you could set the instance to the appropriate IQuery
implementation:
agency.Query = new PickQuery();