I am wrestling with this OOP design issue. Take these base classes, for example:
class Database
{
public string ConnectionString { get; set; }
public Table MyTable { get; set; }
}
class Table
{
public string Name { get; set; }
}
This example is oversimplified to just concentrate on the question at hand.
If I wanted to add logic that would get the Table
row count, you would think that naturally belongs in Table
class:
class Table
{
public string Name { get; set; }
public int GetRowCount() { ... }
}
The problem is, in order to get the row count, a database connection would need to happen. Not a big deal, but the Table
class has no way to retrieve the Database.ConnectionString
property in order to actually connect to get the row count of the particular table.
I see a few options here, and none of them really seem like great approaches.
Keep logic out of child objects
In this case, the GetRowCount()
logic would have to live in the parent object. Something like this:
class Database
{
public string ConnectionString { get; set; }
public Table MyTable { get; set; }
public int GetRowCount(Table table) { ... }
}
class Table
{
public string Name { get; set; }
}
The Table
class is now "dumb" to the logic of the row count, which isn't altogether a bad thing, but now there is no way to have a member in the Table
class to store or retrieve data that is directly related to the Table
class.
Have a reference to the Parent Object in the Child object
This I like even less than the above approach. In this case, it would resemble something like this:
class Database
{
public string ConnectionString { get; set; }
public Table MyTable { get; set; }
}
class Table
{
public string Name { get; set; }
public Database Parent { get; set; }
public int GetRowCount() { ... }
}
Sure, Table.GetRowCount()
can make a reference to Table.Parent.ConnectionString
, but this just seems like unnecessary recursion and... sloppy.
Explicity pass the required data around
I don't like this either, but if the Table.GetRowCount()
implementation required that the connection string is passed to it, this logic could live in the Table
class, but now there is a lack of DRY as well as a leak of Database
data into the Table
implementation:
class Database
{
public string ConnectionString { get; set; }
public Table MyTable { get; set; }
}
class Table
{
public string Name { get; set; }
public int GetRowCount(string connectionString) { ... }
}
Not to mention that this could lead to challenging logic bugs, I would imagine.
How is this typically done, and what's the best approach here? I want the row count logic to live where it naturally belongs, with the Table
class. But that logic and data depends on a member (the connection string) that naturally lives in the Database
class.