Our modules are interdependent, so we are facing issues, such as reusability of code and unresolved bugs, due to changes in one module. These are deployment challenges. To tackle these issues, let's segregate our application in such a way that we will be able to divide modules into submodules. We can divide our Order module in such a way that it would implement the interface, and this can be initiated from the constructor. Here is a small code snippet that shows how we can apply this in our existing monolithic application.
Here is a code example that shows our Order class, where we use the constructor injection:
namespace FlixOne.BookStore.Common
{
public class Order : IOrder
{
private readonly IOrderRepository _orderRepository;
public Order(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
public OrderModel GetBy(Guid orderId)
{
return _orderRepository.Get(orderId);
}
}
}
The inversion of control, or IoC, is nothing but a way in which objects do not create other objects on whom they rely to do their work.
In the preceding code snippet, we abstracted our Order module in such a way that it could use the IOrder interface. Afterward, our Order class implements the IOrder interface, and with the use of inversion of control, we create an object, as this is resolved automatically with the help of inversion of control.
Furthermore, the code snippets of IOrderRepository and OrderRepository are as follows:
namespace FlixOne.BookStore.Common
{
public interface IOrderRepository
{
OrderModel Get(Guid orderId);
}
}
namespace FlixOne.BookStore.Common
{
public class OrderRepository : IOrderRepository
{
public OrderModel Get(Guid orderId)
{
//call data method here
return new OrderModel
{
OrderId = Guid.NewGuid(),
OrderDate = DateTime.Now,
OrderStatus = "In Transit"
};
}
}
}
Here we are trying to showcase how our Order module gets abstracted. In the preceding code snippet, we return default values for our order just to demonstrate the solution to the actual problem.
Finally, our presentation layer (the MVC controller) will use the available methods, as shown in the following code snippet:
namespace FlixOne.BookStore.Controllers
{
public class OrderController : Controller
{
private readonly IOrder _order;
public OrderController(IOrder order)
{
_order = order;
}
// GET: Order
public ActionResult Index()
{
return View();
}
// GET: Order/Details/5
public ActionResult Details(string id)
{
var orderId = Guid.Parse(id);
var orderModel = _order.GetBy(orderId);
return View(orderModel);
}
}
}
The following is a class diagram that depicts how our interfaces and classes are associated with each other and how they expose their methods, properties, and so on:
Here again, we used the constructor injection, where IOrder passed and got the Order class initialized; hence, all the methods are available within our controller.
By achieving this, we would overcome a few problems, such as:
- Reduced module dependency: With the introduction of IOrder in our application, we are reducing the interdependency of the Order module. This way, if we are required to add or remove anything to/from this module, then other modules would not be affected, as IOrder is only implemented by the Order module. Let's say we want to make an enhancement to our Order module; it would not affect our Stock module. This way, we reduce module interdependency.
- Introducing code reusability: If you are required to get the order details of any of the application modules, you can easily do so using the IOrder type.
- Improvements in code maintainability: We have divided our modules into submodules or classes and interfaces now. We can now structure our code in such a manner that all the types, that is, all the interfaces, are placed under one folder and follow the suit for the repositories. With this structure, it would be easier for us to arrange and maintain code.
- Unit Testing: Our current monolithic application does not have any kind of unit testing. With the introduction of interfaces, we can now easily perform unit testing and adopt the system of test-driven development with ease.