Interface Guidelines Definition:
Proper Use of Interface Contracts for Implementing Concrete Types
Interface Guidelines Justification:
Interfaces are probably the most misunderstood Software Entity Type by most Developers.
Proper use of Interfaces will allow a Developer to design to Abstractions rather than Concretes.
This creates decoupled solutions that are less costly to maintain throughout the Life Cycle of the developed application.
Interface Guidelines Convention Standards:
Most Developers can probably recite back a version of the academic answer to “What is an Interface in C#?“.
“An Interface is a Contractual Agreement
… Between a Software Entity,
a Class or a Struct,
… To Implement the Concrete Behaviors
Defined in the Signature Abstractions
… For Properties, Methods, Indexers or Events
Declared within the C# Interface Type”
What is the real value of an Interface in a software development environment?
The first concept we need to understand is the difference between “Class Behavior Inheritance” and “Interface Behavior Inheritance“.
All derived child classes must have an “Is A” relationship to the base class.
This states that a derived Class is an extension of the functionality of the Base Class.
The Liskov Substitution Principle states that a Derived Class must be substitutable for it Base Class without adversely affecting the functionality of the consuming software module.
This is only possible if the derived Class has an “Is A” relationship for its inherited behaviors.
Class Inheritance should only be used for Polymorphism when modelling a point of view, as in an “Is A” relationship.
Sometimes called “Composition” inheritance
All Classes and Structs that implement an Interface agrees to comply with the Signatures provided within the Interface
They agree to add the Required Functionality for those Contract Signatures.
This creates a “Behaves Like” Inheritance Relationship.
The implementing Class or Struct agrees to Implement Code that results in the behavior fulfilling the contract.
An Implementing Type does not have to have an “Is A” relationship to the Interface, only common behaviour
Interfaces provide the following benefits to the developer’s design:
Forces a Developer, using a Design Pattern, to comply with a structure that can be repeated to ensure proper use of the Design Pattern.
Allows for defining Entity Types by abstractions that do not define run-time concretes.
Create a vehicle for creating collection of related Types at run-time. Reflection can be used to create candidates for instantiation based on runtime conditions without any knowledge of the concretes at compilation time.
Interfaces can implement other Interfaces for extending the contracts of existing Interfaces. This creates an Interface Inheritance structure that can be namespace managed for decoupling functionality requirements.
The accessors of a Class can be managed using an Interface for Property and Indexer. By defining the get; and set; Accessor in the Interface immutable data members can be guaranteed.
All Interfaces must be public and cannot contain static signatures.
They cannot contain constants, fields, and operators along with instance constructors, destructors or any Entity Types directly.
You use Properties signature to define return types from the Property Method with its accessors get; and set;.
The Modern Developer’s Interface Standards:
+C# Interface Standards
- The Naming Convention for an Interface is a Modified Pascal casing. Use a capital “I” as a prefix character to signify that it is an Interface type
- A business centric acronym can be used as an exception to the Pascal casing when it add value to the implantation of the underlying Interface
- Use Interfaces to group like Types at runtime for use in Design Patterns such as a Strategy Pattern for instantiating a runtime Type through Reflection
- Consider using Interfaces to add extended functionality by Namespaces though Extension Methods
- Type your Entities to Interfaces rather than the implemented concretes. This supports the Dependency Inversion Principle (DIP) and allows an Inversion of Control (IOC) container to manage Registered Concretes during the Lifetime of the Instantiated Type.
- Create Interfaces when more than one type is sharing Common Behavior to enable designing to Abstractions rather than Concretes
- Use Interfaces to extract the implementation abstractions of a “Fat Class” that violates the Single Responsibility Principle (SRP). You can then create a compliance Class that Implements only the Required Responsibilities.
- An Interface should comply with Single Responsibility Principle (SRP). This also would have the Interface comply with the Interface Segregation Principle (ISP). ISP states that a Class implementing an Interface should not have to implement Interface contracts it does not require.
- If a Class can afford to use its Single Inheritance then consider using an Abstract Class without any Implementations as the contract interface. It will enforce the contract and has a significant performance benefit due to minimized use of Reflection at Runtime.
Interfaces are a powerful tool to manage Software Entity Types.
There is no need to create an interface for every Class Type created, just when any of the above benefits can be realized in your solution.
Think about how your Types will be consumed within the assembly and by outside modules. Use Interfaces as Abstractions to those Implementations.
Use Interfaces to Prevent a Type from Being Used in a Fashion Not Intended
The following two tabs change content below.
I am a Principal Architect at Liquid Hub in the Philadelphia area specializing in Agile Practices as a Certified Scrum Master (CSM). I use Test Driven Development (TDD) and Acceptance Test Driven Development (ATDD) with Behavior Driven Development (BDD) as my bridge to Agile User Stories Acceptance Criteria in a Domain Driven Design (DDD) implementing true RESTful services