Reputation: 1891
I am maintaining an ASP.NET MVC project. In the project the original developer has an absolute ton of interfaces. For example: IOrderService
, IPaymentService
, IEmailService
, IResourceService
. The thing I am confused about is each of these is only implemented by a single class. In other words:
OrderService : IOrderService
PaymentService : IPaymentService
My understanding of interfaces has always been that they are used to create an architecture in which components can be interchanged easily. Something like:
Square : IShape
Circle : IShape
Furthermore, I don't understand how these are being created and used. Here is the OrderService:
public class OrderService : IOrderService
{
private readonly ICommunicationService _communicationService;
private readonly ILogger _logger;
private readonly IRepository<Product> _productRepository;
public OrderService(ICommunicationService communicationService, ILogger logger,
IRepository<Product> productRepository)
{
_communicationService = communicationService;
_logger = logger;
_productRepository = productRepository;
}
}
These objects don't seem be ever be created directly as in OrderService orderService = new OrderService()
it is always using the interface. I don't understand why the interfaces are being used instead of the class implementing the interface, or how that even works. Is there something major that I am missing about interfaces that my google skills aren't uncovering?
Upvotes: 6
Views: 325
Reputation: 108880
These are service interfaces, which encapsulate some kind of externality. You often have just a single implementation of them in your main project, but your tests use simpler implementations that don't depend on that external stuff.
For example if your payment service contacts paypal to verify payments, you don't want to do that in a test of unrelated code. Instead you might replace them with a simple implementation that always returns "payment worked" and check that the order process goes through, and another implementation that returns "payment failed" and check that the order process fails too.
To avoid depending on the implementation, you don't create instances yourself, you accept them in the constructor. Then the IoC container that creates your class will fill them in. Look up Inversion of Control.
Your project has probably some code that sets up the IoC container in its startup code. And that code contains information about which class to create when you want an implementation of a certain interface.
Upvotes: 0
Reputation: 4413
It's good practice to program against interfaces rather than objects. This question gives good reasons why, but some reasons include allowing the implementation to change (ex. for testing).
Just because there's currently only 1 class that implements the interface doesn't mean that it can't change in the future.
Furthermore, I don't understand how these are being created and used.
This is called dependency injection and basically means that the class doesn't need to know how or where to instantiate it's dependencies from, someone else will handle it.
Upvotes: 1
Reputation: 27515
This particular design pattern is typically to facilitate unit testing, as you can now replace OrderService with a TestOrderService, both of which are only referenced as IOrderService. This means you can write TestOrderService to provide specific behavior to a class under test, then sense whether the class under test is doing the correct things.
In practice, the above is often accomplished by using a Mocking framework, so that you don't actually hand-code a TestOrderService, but rather use a more concise syntax to describe how it should behave for a typical test, then have the mocking framework dynamically generate an implementation for you.
As for why you never see 'new OrderService' in the code, it's likely that your project is using some form of Inversion of Control container, which facilitates automatic Dependency Injection. In other words, you don't have to construct OrderService directly, because somewhere you've configured that any use of IOrderService should automatically be fulfilled by constructing a singleton OrderService and passing it in to the constructor. There are a lot of subtleties here and I'm not exactly sure how your dependency injection is being accomplished (it doesn't have to be automatic; you can also just construct the instances manually and pass them in through the constructors.)
Upvotes: 4
Reputation: 62159
These objects don't seem be ever be created directly as in OrderService orderService = new OrderService()
So waht?
Point is that SOMEONE calls the OrderService constructor and THE CALLER is respónsible for creating them. He hands them over.
I don't understand why the interfaces are being used instead of the class implementing the interface
Because you want not to know the class - it may change, be external, be configurable using an IOC container and the programmer decided to not require even a common base class. THe less assumptions you make about how someone implements used utility classes, the better.
Is there something major that I am missing about interfaces that my google skills aren't uncovering?
No, bu a good book about OO programming would help more than random google snippets. This baiscally falls into the architecture area and .NET basics (for the first part).
Upvotes: 1
Reputation: 6308
That's not the only use of interfaces, in MVC they are being used to decouple contract from implementation. To understand about MVC you need to read up a bit on the related topics such as separation of concerns and inversion of control (IoC).The actual act of creating an object to be passed to OrderService
constructor is handled by IoC container based on some predefined mapping.
Upvotes: 1