Let's say that we have the following interface -

interface IDatabase { 
    string ConnectionString{get;set;}
    void ExecuteNoQuery(string sql);
    void ExecuteNoQuery(string[] sql);
    //Various other methods all requiring ConnectionString to be set
}

The precondition is that ConnectionString must be set/intialized before any of the methods can be run.

This precondition can be somewhat achieved by passing a connectionString via a constructor if IDatabase were an abstract or concrete class -

abstract class Database { 
    public string ConnectionString{get;set;}
    public Database(string connectionString){ ConnectionString = connectionString;}

    public void ExecuteNoQuery(string sql);
    public void ExecuteNoQuery(string[] sql);
    //Various other methods all requiring ConnectionString to be set
}

Alternatively, we can create connectionString a parameter for each method, but it looks worse than just creating an abstract class -

interface IDatabase { 
    void ExecuteNoQuery(string connectionString, string sql);
    void ExecuteNoQuery(string connectionString, string[] sql);
    //Various other methods all with the connectionString parameter
}

Questions -

  1. Is there a way to specify this precondition within the interface itself? It is a valid "contract" so I'm wondering if there is a language feature or pattern for this (the abstract class solution is more of a hack imo besides the need of creating two types - an interface and an abstract class - every time this is needed)
  2. This is more of a theoretical curiosity - Does this precondition actually fall into the definition of a precondition as in the context of LSP?
share|improve this question

Connecting and querying are two separate concerns. As such, they should have two separate interfaces.

interface IDatabaseConnection
{
    IDatabase Connect(string connectionString);
}

interface IDatabase
{
    public void ExecuteNoQuery(string sql);
    public void ExecuteNoQuery(string[] sql);
}

This both ensures that IDatabase will be connected when used and makes client not depend on interface it doesn't need.

share|improve this answer
    
Could be more explicit about "this is a pattern of enforcing the preconditions through types" – Caleth 4 hours ago
    
@Caleth: this is not a "general pattern of enforcing preconditions". This is a solution for this specific requirement of ensuring the connect happens before anything else. Other preconditions will need different solutions (like the one I mentioned in my answer). I would like to add for this requirement, I would clearly prefer Euphoric's suggestion over mine, because it is much simpler and does not need any additional third party component. – Doc Brown 4 hours ago
    
The specific requrement that something happens before something else is widely applicable. I also think your answer better fits this question, but this answer can be improved – Caleth 4 hours ago
    
I strongly disagree here. A query 1) requires a connection to exist and 2) can be executed against any of multiple existing transactions. You're hiding dependencies here, which makes understanding the code more difficult. – jpmc26 1 min ago
  1. Yes. From .Net 4.0 upward, Microsoft provides Code Contracts. These can be used to define preconditions in the form Contract.Requires( ConnectionString != null ); for an interface. However, you will still need a helper class IDatabaseContract to make this work, and the precondition needs to be defined for every individual method of your interface where it shall hold. See here for an extensive example for interfaces.

  2. Yes, the LSP deals with both syntactical and semantical parts of a contract.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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