0

SOLID had both the Single Responsibility Principle and the Interface Segregation Principle, to me though, these seem totally interchangeable. To me, an interface is simple a class with no defined implementations.

I believe (though please correct em if I'm wrong) that in .NET an interface is the same as an abstract class with no implementations. I.e., if I replaced all my interfaces with abstract classes then nothing would change (with regards to SOLID).

So... I'd it fair to say that, SOLID can become SOLD?

OK, let me elaborate. I know there are some subtle 'behind the scenes' differences, like multiple inheritance. In the world of SOLID, are there any arguments that apply to either S.R.P. or I.S.P., but not the other?

Note that, in .NET and Java at least, a class must be at least as large an an interface

BanksySan
  • 27,362
  • 33
  • 117
  • 216
  • 2
    Well, on .NET they definitely re no the same - you can only have one base class but implement multiple interfaces. On bytecode level they are very different. – TomTom Oct 06 '14 at 11:52
  • possible duplicate of [Interface vs Base class](http://stackoverflow.com/questions/56867/interface-vs-base-class). Are they the same? **NO**. –  Oct 06 '14 at 11:53
  • Good point! I'd forgotten about the multiple inheritance bit. – BanksySan Oct 06 '14 at 11:53
  • Not a dup, I'm interested in how it related to SOLID. I'd say it might be off topic, but we have a [solid-principles] tag so I am assuming the subject matter is valid. – BanksySan Oct 06 '14 at 11:54

2 Answers2

2

There is a difference between responsibilities and interfaces. A responsibility can consist of several functions that are closely related, while an interface may be interrested in only a few of the functions.

For example a class Connection can be responsible for handling a client-server connection, but one of its interfaces could be ICommunicate that is only concerned with sending data through the connection once it is established.

A class generally represents an entity of some kind, while an interface generally represents an ability. An entity can have several abilities, and different kinds of entities can have the same abilities.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • However, classes have a one to many relationship to interfaces, so they are more granular. In your example, it would be more likely to be class: `Communication` which implements some interfaces including `IConnection`. – BanksySan Oct 06 '14 at 12:25
  • @BanksySan: That depends on what you put in the class and the interfaces. I was thinking of a `Connection` object that can open and close a connection, as well as reading and writing data through it. The `ICommunicate` interface would only have the read and write methods and wouldn't care about what it is communicating with, and how its done. – Guffa Oct 06 '14 at 12:47
  • OK, gotcha. I my point that interfaces, by virtue of having to be an interface needing to be fulfilled by a single class makes the ISP a little redundant? Classes will always be at least as segregated as the interfaces they implement. – BanksySan Oct 06 '14 at 13:01
  • @BanksySan: On the contrary, classes will usually handle all aspects of an object, while an interface can represent a limited set of abilities that the class has. To be as reusable as possible an interface should contain the minimium that is needed for it to be useful, while a class has the full responsibility for whatever it is responsible for. – Guffa Oct 06 '14 at 15:34
1

The intention of SOLID is to get you to create a system that is implementation independent.

SOLID means building many pieces that inject their dependencies so that every individual facet of your system is independently testable. You have an IDbConnectionService that provides an implementation contract to your project. When writing test cases for a service that uses IDbConnectionService as a dependency, you can mock out the functionality of IDbConnectionService to return what you need it to in a faked run time environment.

By using a base class, you are now providing an low-level implementation. Our intention with SOLID is to specifically not provide implementations until absolutely necessary.

For instance, take this example of an IConnectionFactory:

IConnectionFactory.cs

public interface IConnectionFactory {
     DbConnection GetProviderConnection(); //CLR type that oracleconn and sqlconn derive from
}

SqlConnectionFactory.cs

public class SqlConnectionFactory : IConnectionFactory {
    //explicit implementation of GetProviderConnection    
}

OracleConnectionFactory.cs

public class OracleConnectionFactory : IConnectionFactory {
    //explicit implementation of GetProviderConnection
}

SqlConnection and OracleConnection have one reason to change, but the interface segregation principal only requires one contract for them to fulfill in order to stand in for the concept of a ConnectionFactory.

C Bauer
  • 5,003
  • 4
  • 33
  • 62
  • So are you saying that ISP == SRP? – BanksySan Oct 06 '14 at 12:15
  • Well Single Responsibility is having only one reason to change. Interface-segregation is breaking up your application into digestible parts. They are similar, but not the same. You might think of SRP as the guide for breaking down your application, while ISP tells you how to do so. – C Bauer Oct 06 '14 at 12:24
  • At present, I still can't get any reasonable difference between them. – BanksySan Oct 06 '14 at 12:27
  • A class SqlDatabaseConnection : IConnectionFactory {}. SqlDatabaseConnection class does not change when you need to connect to oracle. Instead you do OracleDatabaseConnection : IConnectionFactory {} – C Bauer Oct 06 '14 at 12:34
  • So both the classes and the interfaces appear to require the same rules for good code. Both have a single responsibility and both are correctly segregated. Maybe I shouldn't be considering an interface to be the an `interface` (i.e. made with the interface keyword, but more the public face of an a class). – BanksySan Oct 06 '14 at 12:47
  • That's kinda the idea of an interface, it's like an implementation contract that says "if you're going to be doing IX, then implement IX.Y() and IX.Z(), because the things that use IX are going to expect it to do Y() and Z()". In this example, an IConnectionFactory would look like a IConnectionFactory { DbConnection GetProviderConnection(); } (Because DBConnection is a CLR type that both OracleConnection and SqlConnection derive from) [ed - I hate comments this looks so confusing] – C Bauer Oct 06 '14 at 13:01
  • @BanksySan I tried writing a condensed version of this explanation in my original answer – C Bauer Oct 06 '14 at 13:06