Skip to main content
edited body
Source Link
9000
  • 24.3k
  • 4
  • 52
  • 79

I'm used to think that an interface only defines methods and constants. We can, of course, suppose that for "read-only fields" your interface are methods that return constant values.

The point of an interface if to define, well, an interface, but allow any reasonable implementation.

If a reasonable implementation would need full access to an encryption algorithm anyway, then exposing getEncryptionAlgoGetEncryptionAlgo() (or passing it as a parameter to an interface method) is ok.

If ThisEncryptionAlgo.Encrypt is strictly sufficient for the purposes of your interface, then exposing the rest is not a good idea, in my eys.

What you call the "spirit" seems to be your hunch of a possible implementation. This limits possible implementations. E.g. if you have a completely different encryption library then you are used to, it's easy t expose via the interface that only needs .Encrypt, and hard, or impossible, in your interface.

Ironically, it becomes harder to mock the encryption provider for testing of a class implementing that interface: you need to mock more, and have an easier time to mock it incorrectly.

In general, I'd suggest to expose only the strict minimum of methods in an interface. The simpler it is, the lower the chance of implementing it incorrectly.

If you want to expose more, consider an extended interface that extendsaugments your minimal interface but also provideswith specific implementation conveniences:

interface Stream<T> {  // Minimal.
  T Read();
  Boolean HasMore();
}

interface SeekableStream<T> : Stream<T> {
  long GetPosition();
  void Seek(long);
}

class File<T> : SeekableStream<T> { // Still acceptable anywhere a Stream goes.
... 
}

I'm used to think that an interface only defines methods and constants. We can, of course, suppose that for "read-only fields" your interface are methods that return constant values.

The point of an interface if to define, well, an interface, but allow any reasonable implementation.

If a reasonable implementation would need full access to an encryption algorithm anyway, then exposing getEncryptionAlgo() (or passing it as a parameter to an interface method) is ok.

If ThisEncryptionAlgo.Encrypt is strictly sufficient for the purposes of your interface, then exposing the rest is not a good idea, in my eys.

What you call the "spirit" seems to be your hunch of a possible implementation. This limits possible implementations. E.g. if you have a completely different encryption library then you are used to, it's easy t expose via the interface that only needs .Encrypt, and hard, or impossible, in your interface.

Ironically, it becomes harder to mock the encryption provider for testing of a class implementing that interface: you need to mock more, and have an easier time to mock it incorrectly.

In general, I'd suggest to expose only the strict minimum of methods in an interface. The simpler it is, the lower the chance of implementing it incorrectly.

If you want to expose more, consider an extended interface that extends your minimal interface but also provides specific implementation conveniences:

interface Stream<T> {  // Minimal.
  T Read();
  Boolean HasMore();
}

interface SeekableStream<T> : Stream<T> {
  long GetPosition();
  void Seek(long);
}

class File<T> : SeekableStream<T> { // Still acceptable anywhere a Stream goes.
... 
}

I'm used to think that an interface only defines methods and constants. We can, of course, suppose that for "read-only fields" your interface are methods that return constant values.

The point of an interface if to define, well, an interface, but allow any reasonable implementation.

If a reasonable implementation would need full access to an encryption algorithm anyway, then exposing GetEncryptionAlgo() (or passing it as a parameter to an interface method) is ok.

If ThisEncryptionAlgo.Encrypt is strictly sufficient for the purposes of your interface, then exposing the rest is not a good idea, in my eys.

What you call the "spirit" seems to be your hunch of a possible implementation. This limits possible implementations. E.g. if you have a completely different encryption library then you are used to, it's easy t expose via the interface that only needs .Encrypt, and hard, or impossible, in your interface.

Ironically, it becomes harder to mock the encryption provider for testing of a class implementing that interface: you need to mock more, and have an easier time to mock it incorrectly.

In general, I'd suggest to expose only the strict minimum of methods in an interface. The simpler it is, the lower the chance of implementing it incorrectly.

If you want to expose more, consider an extended interface that augments your minimal interface with specific implementation conveniences:

interface Stream<T> {  // Minimal.
  T Read();
  Boolean HasMore();
}

interface SeekableStream<T> : Stream<T> {
  long GetPosition();
  void Seek(long);
}

class File<T> : SeekableStream<T> { // Still acceptable anywhere a Stream goes.
... 
}
Source Link
9000
  • 24.3k
  • 4
  • 52
  • 79

I'm used to think that an interface only defines methods and constants. We can, of course, suppose that for "read-only fields" your interface are methods that return constant values.

The point of an interface if to define, well, an interface, but allow any reasonable implementation.

If a reasonable implementation would need full access to an encryption algorithm anyway, then exposing getEncryptionAlgo() (or passing it as a parameter to an interface method) is ok.

If ThisEncryptionAlgo.Encrypt is strictly sufficient for the purposes of your interface, then exposing the rest is not a good idea, in my eys.

What you call the "spirit" seems to be your hunch of a possible implementation. This limits possible implementations. E.g. if you have a completely different encryption library then you are used to, it's easy t expose via the interface that only needs .Encrypt, and hard, or impossible, in your interface.

Ironically, it becomes harder to mock the encryption provider for testing of a class implementing that interface: you need to mock more, and have an easier time to mock it incorrectly.

In general, I'd suggest to expose only the strict minimum of methods in an interface. The simpler it is, the lower the chance of implementing it incorrectly.

If you want to expose more, consider an extended interface that extends your minimal interface but also provides specific implementation conveniences:

interface Stream<T> {  // Minimal.
  T Read();
  Boolean HasMore();
}

interface SeekableStream<T> : Stream<T> {
  long GetPosition();
  void Seek(long);
}

class File<T> : SeekableStream<T> { // Still acceptable anywhere a Stream goes.
... 
}