views:

54

answers:

2

For example, you have an IRepository interface. You also have a SqlRepository class, which implements the interface, backed by a SQL database. Let's say the constructor for that class takes a connection string. If your repository makes stored procedure calls and if those calls are internal to the repository, isn't that a hidden dependency? Your repository is dependant not only on the database connection specified by the connection string, it's also dependant on the database having the proper stored procedures installed. If your backing database doesn't have those stored procedures, your program will crash. How would you know what stored procedures have to be installed in order for your program to run if you didn't have access to the SqlRepository's code? Is this the type of hidden dependency that makes DI advocates cringe?

+1  A: 

Um... your repository also depends on your database having certain tables, and those tables having certain columns. Those are all dependancies, but they aren't particularly hidden.

In fact, those are even bigger dependencies than the stored procedure. The repository could be rewritten to avoid needing them, but the data really has to be there....

James Curran
Thanks for the response. I agree, I'm just trying to see where all this depency injection stuff leads you. Where do you draw the line?
Brandon
DI allows you to swap out different object, but those objects must still met some basic requirement of doing the job. Imagine instead of IRespository, you tried swapping two objects which merely just both implemented IComparable. Would you expect that to work?
James Curran
I might...isn't that why you code to an interface? So that two different object can implement the same functionality? I don't care how they do it, just that they do it.
Brandon
+1  A: 

Yes. The problem is that there's no way to impose contracts on SQL databases (contracts in the object-oriented sense).

That is, we don't have any way to say that a database conforms to an IPersonRepository interface, so we can't be certain that it implements a procedure "dbo.GetPerson" which returns two resultsets with columns a, b, c, and d. (Or that we have permission to execute that procedure.) Therefore we can't require an IPersonRepository in our connection string.

Mature object-relational mappers like (N)Hibernate solve this problem by creating domain-specific languages to describe those expectations (their elaborate configuration specifications), but those techniques are only a partial solution, because they can't be enforced on the database side.

This is another facet of the object-relational impedance mismatch, albeit one about which I haven't seen anything written.

Jeff Sternal
Jeff - Good point. I agree, there is just no good way to express a contract between C# and a resource external to C#. Providing hints in our code that an external dependency is used, such as a connection string or file path parameter in the constructor of a repository class, and throwing when something goes wrong is the best we can do.
Brandon