{"id":423,"date":"2026-07-02T13:10:37","date_gmt":"2026-07-02T13:10:37","guid":{"rendered":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/?p=423"},"modified":"2026-07-02T13:17:36","modified_gmt":"2026-07-02T13:17:36","slug":"dependency-inversion-principle","status":"publish","type":"post","link":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/2026\/07\/02\/dependency-inversion-principle\/","title":{"rendered":"Dependency Inversion Principle"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">Depend on Abstractions, Not on Concrete Implementations<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Dependency Inversion Principle (DIP)<\/strong>, the fifth and final principle of SOLID, states that:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u201cHigh-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.\u201d \u2014 Robert C. Martin<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s break this into two separate statements because each carries its own important meaning.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">First Statement<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">High-level modules (those containing business logic) should not depend directly on low-level modules (those handling technical details such as database access or email delivery).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, both layers should depend on abstractions, such as interfaces or abstract classes.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Second Statement<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Abstractions themselves should not know about implementation details.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, implementation details should conform to the contract defined by the abstraction.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Simply Put<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Do not import concrete implementations where an interface is sufficient.<\/strong><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Real-Life Example: How to Understand It?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine ordering food for home delivery.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You do not call a delivery driver directly. Instead, you call a restaurant and place an order.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The restaurant knows it needs someone capable of delivering the food to your address.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It does not matter which courier performs the delivery. What matters is that every courier can pick up the package and deliver it successfully.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now imagine you insist that only one specific courier can deliver your food.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If that courier gets sick, quits the job, or is unavailable, you do not receive your meal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You have become dependent on a specific person instead of the role that person fulfills.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Programming works the same way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That &#8220;role&#8221; is an interface\u2014an abstraction.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The restaurant (business logic) does not know anything about the individual courier (the concrete class).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It only knows that it needs someone who fulfills the role of a courier: picking up and delivering packages.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">A Thought Exercise<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine an <code>OrderProcessor<\/code> class responsible for processing orders in an online store.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To complete an order, it must save data somewhere.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If <code>OrderProcessor<\/code> directly creates an instance of <code>MySQLOrderRepository<\/code>, then you are effectively calling the courier directly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What happens when you decide to switch to PostgreSQL, MongoDB, or file-based storage for tests?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You must modify a class that should focus on business logic, not infrastructure details.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is exactly the problem DIP solves.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example \u2014 DIP Violation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose we are building a notification system for an e-commerce platform.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>NotificationService<\/code> class sends notifications to customers after they place an order.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Someone unfamiliar with DIP might write something like this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;I need to send emails, so I&#8217;ll use <code>EmailSender<\/code>.&#8221;<\/p>\n<\/blockquote>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\/\/ Low-level class \u2014 concrete implementation<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class EmailSender {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void send(String recipient, String message) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ technical detail: sending email via SMTP<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(&#8220;Sending email to: &#8221; + recipient);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\/\/ High-level class \u2014 business logic<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class NotificationService {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 \/\/ Dependency on a CONCRETE IMPLEMENTATION<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 private EmailSender emailSender = new EmailSender();<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void notifyUser(String userEmail, String orderInfo) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 emailSender.send(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userEmail,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;Your order: &#8221; + orderInfo<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">At first glance, the code appears reasonable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, let&#8217;s see what happens when requirements change\u2014which they always do in real projects.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Scenario 1: Add SMS Notifications<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The business wants to support SMS notifications in addition to email.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To achieve this, we must modify <code>NotificationService<\/code>, even though the business logic itself has not changed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As a side effect, we are also moving toward violating SRP.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Scenario 2: Unit Testing<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">In unit tests, we do not want to send real emails.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unfortunately, there is no easy way to replace <code>EmailSender<\/code> with a mock because the class creates it internally with <code>new<\/code>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Scenario 3: Multiple Email Providers<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Suppose we want to support:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SendGrid,<\/li>\n\n\n\n<li>Mailgun,<\/li>\n\n\n\n<li>an internal SMTP server.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Every provider change requires modifying <code>NotificationService<\/code>, even though it should not care who actually sends emails.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Root Cause<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\"><code>NotificationService<\/code> depends on a concrete implementation (<code>EmailSender<\/code>) instead of depending on an abstraction.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Example \u2014 DIP-Compliant Design<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">How do we fix this?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We introduce an abstraction: an interface that defines the contract:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;Anything capable of sending notifications can be used here.&#8221;<\/p>\n<\/blockquote>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\/\/ Abstraction \u2014 the contract<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">interface NotificationSender {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 void send(String recipient, String message);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">Now low-level implementations depend on the abstraction:<\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class EmailSender implements NotificationSender {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 @Override<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void send(String recipient, String message) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;Email to: &#8221; + recipient +<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8221; | &#8221; + message<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<p><!--ScriptorStartFragment--><\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class SmsSender implements NotificationSender {<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 @Override<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void send(String recipient, String message) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.out.println(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;SMS to: &#8221; + recipient +<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8221; | &#8221; + message<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">The high-level module also depends on the abstraction:<\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class NotificationService {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 private final NotificationSender sender;<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 \/\/ Dependency Injection<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public NotificationService(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NotificationSender sender) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 this.sender = sender;<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void notifyUser(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String userContact,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String orderInfo) {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sender.send(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userContact,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;Your order: &#8221; + orderInfo<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<h5 class=\"wp-block-heading\">Usage<\/h5>\n\n\n<!--ScriptorStartFragment-->\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">public class Main {<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public static void main(String[] args) {<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NotificationSender emailSender =<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new EmailSender();<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NotificationService serviceA =<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new NotificationService(emailSender);<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 serviceA.notifyUser(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;john@example.com&#8221;,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;#12345&#8221;<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NotificationSender smsSender =<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new SmsSender();<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NotificationService serviceB =<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new NotificationService(smsSender);<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 serviceB.notifyUser(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;+48 600 000 000&#8221;,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;#12346&#8221;<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 );<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<h4 class=\"wp-block-heading\">What Changed?<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">1. We Introduced an Interface<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\"><code>NotificationSender<\/code> defines the contract.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Any notification sender must implement it.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">2. We Removed Object Creation from Business Logic<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\"><code>NotificationService<\/code> no longer creates dependencies using <code>new<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dependencies are provided externally.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This technique is called <strong>Dependency Injection (DI)<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>DIP is the principle. DI is a common technique used to implement it.<\/strong><\/p>\n\n\n\n<h5 class=\"wp-block-heading\">3. New Communication Channels Are Easy to Add<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Want:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>push notifications,<\/li>\n\n\n\n<li>Slack messages,<\/li>\n\n\n\n<li>Microsoft Teams notifications,<\/li>\n\n\n\n<li>WhatsApp alerts?<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Simply create another implementation of <code>NotificationSender<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No changes are required in <code>NotificationService<\/code>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">4. Testing Becomes Easy<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Tests can inject a fake sender instead of a real implementation.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Why Is DIP Important?<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">Flexibility and Replaceable Implementations<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">When business logic is isolated from technical details, changing:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>databases,<\/li>\n\n\n\n<li>notification channels,<\/li>\n\n\n\n<li>external APIs,<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">does not require changing the business logic itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is like replacing a light bulb while keeping the same socket.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Better Testability<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of the biggest practical benefits.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When a class depends on an interface, tests can inject a mock object rather than using the real implementation.<\/p>\n\n\n<!--ScriptorStartFragment-->\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">class MockSender implements NotificationSender {<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public List&lt;String&gt; sent =<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new ArrayList&lt;&gt;();<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 @Override<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public void send(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String recipient,<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 String message) {<\/div>\n<p style=\"padding-left: 80px;\">\u00a0<\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sent.add(recipient);<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">No emails are sent.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No external systems are contacted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The business logic is tested in isolation.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Fewer Team Conflicts<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">When dependencies are based on interfaces, different developers can work independently on:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>NotificationService<\/code>,<\/li>\n\n\n\n<li><code>EmailSender<\/code>,<\/li>\n\n\n\n<li><code>SmsSender<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The interface acts as a contract between teams.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Long-Term Benefits<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Large projects that ignore DIP often evolve into what engineers call:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;spaghetti dependencies&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">A tangled network of concrete class dependencies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Every modification creates a chain reaction.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Refactoring becomes dangerous.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Testing becomes difficult.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">New developers may need weeks to understand the dependency graph.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">DIP is an investment whose value grows alongside the size of the project.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">When Should You Apply DIP?<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">When a Class Connects to External Resources<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Examples include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>databases,<\/li>\n\n\n\n<li>external APIs,<\/li>\n\n\n\n<li>file systems,<\/li>\n\n\n\n<li>payment gateways,<\/li>\n\n\n\n<li>messaging services.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The implementation may change, but business logic should remain unaffected.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">When You Want Unit-Testable Code<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">If a class creates dependencies using:<\/p>\n\n\n<!--ScriptorStartFragment-->\n<p style=\"padding-left: 80px;\">new SomeService()<\/p>\n<!--ScriptorEndFragment-->\n\n\n<p class=\"wp-block-paragraph\">you cannot easily replace those dependencies during testing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If dependencies are provided through constructors or setters, mocks become trivial to use.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">In Frameworks That Already Use DIP<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Spring Framework is essentially DIP at industrial scale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its IoC (Inversion of Control) container creates objects and injects dependencies automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Annotations such as:<\/p>\n\n\n<p><!--ScriptorStartFragment--><\/p>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">@Autowired<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">@Component<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">@Service<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\">are mechanisms that support DIP.<\/p>\n\n\n<pre style=\"padding-left: 80px;\"><!--ScriptorStartFragment--><\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">@Service<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">public class OrderService {<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 private final PaymentGateway paymentGateway;<\/div>\n<pre style=\"padding-left: 80px;\">\u00a0<\/pre>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 @Autowired<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 public OrderService(<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 PaymentGateway paymentGateway) {<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 this.paymentGateway = paymentGateway;<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">\u00a0\u00a0\u00a0 }<\/div>\n<div class=\"scriptor-paragraph\" style=\"padding-left: 80px;\">}<!--ScriptorEndFragment--><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>OrderService<\/code> depends on the <code>PaymentGateway<\/code> interface, not on a concrete implementation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Spring decides which implementation to inject.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The class does not need to know.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Similarly, Hibernate and JPA use abstractions such as repositories and the <code>EntityManager<\/code> to separate business logic from database-specific details.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Memory Trick<\/h4>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Depend on the contract, not on the contractor.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">If you see <code>new ConcreteService()<\/code> inside a business class, the implementation decision is probably being made in the wrong place.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Point upward to abstractions, not downward to details.<\/p>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\">Summary<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">DIP completes the SOLID principles.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>SRP<\/strong> says classes should have a single responsibility.<\/li>\n\n\n\n<li><strong>OCP<\/strong> says software should be open for extension but closed for modification.<\/li>\n\n\n\n<li><strong>LSP<\/strong> ensures subclasses can safely replace base classes.<\/li>\n\n\n\n<li><strong>ISP<\/strong> promotes small, focused interfaces.<\/li>\n\n\n\n<li><strong>DIP<\/strong> ties everything together by ensuring that high-level logic depends on stable abstractions rather than volatile implementation details.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Define a contract.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Depend on the contract.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let implementation details serve the contract\u2014not control it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Depend on Abstractions, Not on Concrete Implementations The Dependency Inversion Principle (DIP), the fifth and final principle of SOLID, states that: \u201cHigh-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.\u201d \u2014 Robert C. Martin Let&#8217;s break this into two separate [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"saved_in_kubio":false,"footnotes":""},"categories":[12],"tags":[],"class_list":["post-423","post","type-post","status-publish","format-standard","hentry","category-solid"],"_links":{"self":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/423","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/comments?post=423"}],"version-history":[{"count":3,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/423\/revisions"}],"predecessor-version":[{"id":428,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/posts\/423\/revisions\/428"}],"wp:attachment":[{"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/media?parent=423"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/categories?post=423"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/patryk-sobilo.profesjonalnyprogramista.pl\/index.php\/wp-json\/wp\/v2\/tags?post=423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}