<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sour_grape</title>
    <description>The latest articles on DEV Community by sour_grape (@sour_grape).</description>
    <link>https://dev.to/sour_grape</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3290820%2F9749907b-83f4-49f7-b37d-63aa6e1146b6.png</url>
      <title>DEV Community: sour_grape</title>
      <link>https://dev.to/sour_grape</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sour_grape"/>
    <language>en</language>
    <item>
      <title>My Take on OOP (Part 7): Dependency Injection is No Big Deal</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 16:50:28 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-7-dependency-injection-is-no-big-deal-22nm</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-7-dependency-injection-is-no-big-deal-22nm</guid>
      <description>&lt;h1&gt;
  
  
  Requirements, Contracts, Messages
&lt;/h1&gt;

&lt;p&gt;These are the three things I've emphasized while explaining Object-Oriented Programming.&lt;/p&gt;

&lt;p&gt;By now, you should understand that these three aren't independent concepts; they are organically connected. This entire series of articles has just been a demonstration of their natural flow.&lt;/p&gt;

&lt;p&gt;I've said that interfaces and polymorphism are just about "swapping parts."&lt;/p&gt;

&lt;p&gt;But is swapping parts really that easy? There's a hidden trap. Today, I'm going to talk about that trap and how Dependency Injection (DI) is just the good old object-oriented way of fixing it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's Design Based on What We've Learned
&lt;/h1&gt;

&lt;p&gt;We get the theory, so let's see how it's reflected in code. I'll do exactly what we've been doing in the previous parts.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Requirement and the Contract: "Hey, come by car."
&lt;/h1&gt;

&lt;p&gt;There are two parts to this contract: you have to come to the meeting spot, and you have to come by car.&lt;/p&gt;

&lt;p&gt;So, we design the contract as an interface, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Car {
    void move();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Friend {
    private final Car car;

    // We inject the contract that the friend must come by car.
    public Friend(Car car) {
        this.car = car;
    }

    public void goToAppointment() {
        this.car.move();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good. We've designed this naturally. Unlike the bad example from before, we haven't hardcoded a "Red 2023 Ford Mustang GT, license plate 8XN-4Y2" directly into our design. We just naturally included a Car interface in the class, just like how we talk. This is great.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Now, Let's Send the Message: "You Figure It Out"
&lt;/h1&gt;

&lt;p&gt;We have to send a message that says, "Just honor the contract and you figure out the rest."&lt;/p&gt;

&lt;h1&gt;
  
  
  But You Have to Use the Design, Right?
&lt;/h1&gt;

&lt;p&gt;Okay, we've designed our object-oriented system naturally. Why did we design it? To use it, obviously. Let's implement the real-world scenario of me telling my friend to come by car.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Me {
    public static void main(String[] args) {
        // "I" want to get my friend to come to the appointment.
        // But... "I" have to personally create the 'car' to give to my friend.
        Car aFriendsCar = new MyFordMustang();

        // And then I create the friend who has that car.
        Friend friend = new Friend(aFriendsCar);

        // Only now can I tell my friend to come to the meeting spot.
        friend.goToAppointment();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I said we have to send a message to our friend. Let me emphasize it again. OOP is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"As long as you honor the requirements and the contract, you figure out the rest."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the previous example, we honored the requirements and the contract, and we designed the method—the messenger—well by using an interface. It seems like we should be able to send the "You figure it out" message. &lt;strong&gt;But there's a trap in the process of sending this message.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the code above, for me to send a message to my friend, I have to inject the specific car information myself.&lt;/p&gt;

&lt;p&gt;This is the same as the situation where I know my friend's car is a "Red 2023 Ford Mustang GT, license plate 8XN-4Y2."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In other words, this code is exactly the same as me saying, "Hey, come in that Red 2023 Ford Mustang GT, license plate 8XN-4Y2, that you own."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You go through all the trouble of designing a good, "you-figure-it-out" OOP system, only to ruin it all at the very last step when you actually run it. It's the worst-case scenario.&lt;/p&gt;

&lt;h1&gt;
  
  
  So How Do We Fix It?
&lt;/h1&gt;

&lt;p&gt;What's the object-oriented way to solve a problem like this? Like I've been saying, you send a message: "You figure it out."&lt;/p&gt;

&lt;p&gt;In the code above, the situation is messed up because when it was time to create the friend who would perform the action, I injected the specific car information. &lt;strong&gt;In other words, it's a situation I messed up by doing the injection myself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, what if I don't do the injection? What if I just send a message to "go figure out the injection yourself"?&lt;/p&gt;

&lt;p&gt;Then we can just create a 'guy' whose only job is to do the injecting, and give him an order: &lt;strong&gt;"Hey, you handle the injection."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can express it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CarFactory {
    // This is the response to the request, "I need a car, prepare one."
    public Car createCar() {
        // Only this guy knows what the friend's car is.
        return new MyFordMustang();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I can send my message like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Me {
    public static void main(String[] args) {
        // I call the guy who knows what my friend's car is.
        CarFactory carFactory = new CarFactory();

        // I delegate all the specific details to that guy.
        // "I" no longer know if it's a 'MyFordMustang'. I just know it's a 'Car'.
        Car aFriendsCar = carFactory.createCar();

        // I don't know what kind of car it is, I just send the message to my friend: "Hey, come by car."
        Friend friend = new Friend(aFriendsCar);

        // Then my friend figures it out and comes by car.
        friend.goToAppointment();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I solved the trap of knowing my friend's car by using the original object-oriented solution. I created a 'guy' who handles injecting the car info, and I just sent him a message to do his job.&lt;/p&gt;

&lt;p&gt;I have perfectly implemented the "Hey, come by car" message, instead of the "Hey, come in your specific Ford Mustang" command.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;When people explain DI, they throw around a bunch of complicated words like "Inversion of Control~~" or "reducing coupling~~"...&lt;/p&gt;

&lt;p&gt;It's just the same old OOP trick for avoiding the trap. &lt;strong&gt;It's no big deal&lt;/strong&gt;. It's just sticking to the "you figure it out" attitude to the very end.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 6): Forget "Polymorphism." It's Just Swapping Parts.</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 16:38:27 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-6-forget-polymorphism-its-just-swapping-parts-35d4</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-6-forget-polymorphism-its-just-swapping-parts-35d4</guid>
      <description>&lt;h1&gt;
  
  
  I Like Feynman
&lt;/h1&gt;

&lt;p&gt;I'm a big fan of Richard Feynman. If you study physics, you usually end up reading his famous "Red Books," and from there, you get into his biographies. Feynman used to say, "If you can't explain something in simple terms, you don't understand it yourself."&lt;/p&gt;

&lt;p&gt;That's probably why he won a Nobel Prize for explaining theories with simple diagrams.&lt;/p&gt;

&lt;p&gt;Anyway, my point is, I don't get why people insist on explaining Object-Oriented Programming in such a ridiculously complicated way.&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits of an Interface
&lt;/h1&gt;

&lt;p&gt;I've been emphasizing that the biggest benefit of an interface is that it lets you define and enforce a contract in code. Another great benefit is polymorphism.&lt;/p&gt;

&lt;p&gt;I already explained this naturally when I talked about abstraction in the last part.&lt;/p&gt;

&lt;p&gt;If you just write up the contract, you don't have to care how it's implemented. To bring back the analogy from last time:&lt;/p&gt;

&lt;p&gt;The contract "Come by car" just means you have to show up in a car. My friend doesn't care if I take a taxi, a bus, or my own car. I just have to get there by car.&lt;/p&gt;

&lt;p&gt;So if you flip that around, it means as long as I'm in a car, I can change my mind whenever I want, right?&lt;/p&gt;

&lt;p&gt;I was planning to take the bus, but I'm running late, so I'll take a taxi instead. No problem. &lt;strong&gt;This freedom to change my mind based on my situation, to swap things out as I please—that's polymorphism.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Polymorphism Exists: OOP and Messages
&lt;/h1&gt;

&lt;p&gt;The core of OOP, as I've said, is a strict &lt;strong&gt;division of labor&lt;/strong&gt;. It's a system where everyone minds their own business and just sends messages to each other. It's a system where you just &lt;strong&gt;throw the contract over the wall and tell the other guy, "You figure it out."&lt;/strong&gt; Polymorphism is the natural result of this system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My way? Yeah, my way. As long as I honor the contract, I'll do it however I want. And if I don't like it later, I'll swap it out myself. You just get the result. That's the deal. That's the contract.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implementing, swapping, and changing things however you want—as long as you uphold the contract and deliver the result—that's a successful division of labor, that's successful messaging, that's proper OOP.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Benefit of Polymorphism
&lt;/h1&gt;

&lt;p&gt;I'll show you exactly what this looks like in code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The Contract
interface Car {
    void moveTo(String destination);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Person {
    // anyCar, i.e., as long as it's a car, anything goes.
    public void goToAppointment(Car anyCar) {
        anyCar.moveTo("the meeting spot");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        // "Me," who needs to get to an appointment
        Person me = new Person();

        // I can make and use whatever I want to ride.
        Car myCar = new MyFordMustang();
        Car taxi = new Taxi();
        Car bus = new Bus();

        System.out.println("--- Today's Plan ---");

        // I just have to honor the "Come by car" contract.
        // Which 'Car' I use is completely up to me.

        System.out.println("1. Maybe I'll take my own car today?");
        me.goToAppointment(myCar); // I'm taking my car.

        System.out.println("2. I should take a taxi tomorrow.");
        me.goToAppointment(taxi); // Gotta take a taxi.

        System.out.println("3. Let's take the bus the day after.");
        me.goToAppointment(bus); // Taking the bus.
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You hear a lot of talk about "flexibility" and "extensibility." Isn't this more intuitive? The contract just has to be met, so of course it's flexible and extensible.&lt;/p&gt;

&lt;p&gt;No, let's put it more simply: &lt;strong&gt;The biggest advantage is that nothing breaks when I swap things out as I please&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you want to change code later, it usually falls into two categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You change the requirements and the contract.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You change the implementation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Number 1 means you just change the interface.&lt;br&gt;
Number 2 means you just build a new implementation, throw out the old one, and swap in the new one.&lt;/p&gt;

&lt;p&gt;Polymorphism is what gives you the power to do #2.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Polymorphism is born from the division of labor and messaging in OOP.&lt;br&gt;
&lt;strong&gt;Polymorphism is the freedom to swap things out as you please, as long as you honor the contract.&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 5): "Abstraction" is a Scary Word. It's Just How We Talk.</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 16:27:41 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-5-abstraction-is-a-scary-word-its-just-how-we-talk-4i3b</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-5-abstraction-is-a-scary-word-its-just-how-we-talk-4i3b</guid>
      <description>&lt;h1&gt;
  
  
  Abstraction??
&lt;/h1&gt;

&lt;p&gt;The poster child for abstraction is mathematics. And let's be honest, mathematical abstraction is notoriously difficult. If you can actually enjoy it, you have a real talent for math.&lt;/p&gt;

&lt;p&gt;Because it has such a bad reputation, people assume programming abstraction must be hard, too.&lt;/p&gt;

&lt;p&gt;In a way, they're the same. But in another, they are completely different.&lt;/p&gt;

&lt;h1&gt;
  
  
  Programming Abstraction is Our Daily Life
&lt;/h1&gt;

&lt;p&gt;Abstraction in programming is our everyday life. It's our language.&lt;/p&gt;

&lt;p&gt;What "abstraction" means in programming is the same as how we normally talk. To be precise, it's the method for expressing the 'Contracts' I find so important.&lt;/p&gt;

&lt;p&gt;Let's say I'm making plans with a friend. I can tell them, &lt;strong&gt;"Come by car tomorrow."&lt;/strong&gt; A totally normal phrase, right? But that is programming abstraction.&lt;/p&gt;

&lt;p&gt;The Contract is: You must arrive at the meeting place tomorrow, and you must come by car.&lt;/p&gt;

&lt;p&gt;That's it. Those are the only two conditions. As long as I fulfill those two, the specific details of how are completely up to me. My friend doesn't care if I take a taxi, a bus, or my own car.&lt;/p&gt;

&lt;p&gt;So what does it mean to not use abstraction in programming?&lt;/p&gt;

&lt;p&gt;It's like your friend saying, &lt;strong&gt;"Tomorrow, come in your Red 2023 Ford Mustang GT, license plate 8XN-4Y2."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you talked like that in real life, people would think you're a psycho. And the biggest problem with this "contract" is that I must come in that specific Ford Mustang.&lt;/p&gt;

&lt;p&gt;But what if I sold it? What if it's in the shop for repairs? What if I bought a new car? What if I left my car in another city? It becomes difficult to fulfill the contract, and the truly important part—showing up to the meeting—is blocked by a trivial constraint.&lt;/p&gt;

&lt;p&gt;This happens because your friend knows the specific details of the car you own.&lt;/p&gt;

&lt;p&gt;"Just make sure it's a car, and you figure out the rest." That's how we normally talk.&lt;/p&gt;

&lt;p&gt;"Turn on your laptop so we can video call." "Grab a spoon so we can eat." "Check your texts." "The car broke down, so take it to a repair shop." All of this everyday language is abstraction. It's completely natural to us.&lt;/p&gt;

&lt;p&gt;But imagine if people said this instead:&lt;br&gt;
"Turn on your M2 MacBook Air for the video call." "Grab that specific spoon from the Chinese restaurant." "Check your texts on your iPhone 14." "Your Red 2023 Ford Mustang GT, license plate 8XN-4Y2, is broken, so take it to the specific Ford dealership on 123 Main Street to get it fixed."&lt;/p&gt;

&lt;p&gt;That's not abstraction; that's defining a contract with needless, suffocating detail. It's a contract you can't fulfill if circumstances change later. Besides, who even talks like that?&lt;/p&gt;

&lt;p&gt;But in programming, we make this mistake all the time.&lt;/p&gt;

&lt;p&gt;Let's translate that "psycho conversation" into code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The concrete implementation: a Ford Mustang GT
class FordMustangGT {
    public void driveTo(String destination) {
        System.out.println("Driving the Ford Mustang GT smoothly to " + destination + ".");
    }
}

// The requester: demands a specific 'FordMustangGT'
class Person {
    public void goToAppointment(FordMustangGT myCar) {
        // This code can only talk to a 'FordMustangGT'.
        myCar.driveTo("the meeting spot");
    }
}

// The execution code
public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        FordMustangGT mustang = new FordMustangGT();
        person.goToAppointment(mustang);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Writing code like this is often seen as perfectly natural. Isn't that weird? The very way of speaking that would get you labeled a psycho in real life is considered normal in programming.&lt;/p&gt;

&lt;p&gt;Now let's change it to a natural, everyday conversation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 1. The Contract (Interface): Defines the "must be able to move" contract
interface Car {
    void moveTo(String destination);
}

// 2. The various implementations that honor the contract
class MyFordMustang implements Car {
    @Override
    public void moveTo(String destination) {
        System.out.println("Driving my Ford Mustang to " + destination + ".");
    }
}

class Taxi implements Car {
    @Override
    public void moveTo(String destination) {
        System.out.println("Calling an Uber to get to " + destination + ".");
    }
}

class Bus implements Car {
    @Override
    public void moveTo(String destination) {
        System.out.println("Taking the 143 bus to " + destination + ".");
    }
}

// 3. The requester: Depends only on the 'Car' contract
class Person {
    public void goToAppointment(Car anyCar) {
        // This code can talk to ANY object that honors the 'Car' contract.
        anyCar.moveTo("the meeting spot");
    }
}

// 4. The execution code
public class Main {
    public static void main(String[] args) {
        Person person = new Person();

        // Today, I'll use my own car.
        person.goToAppointment(new MyFordMustang());

        // Tomorrow, I'll take a taxi.
        person.goToAppointment(new Taxi());

        // The day after, I'll take the bus.
        person.goToAppointment(new Bus());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll admit, writing the code this way can feel like a pain. It seems like more effort, so you're tempted to just write the specific, concrete code. But this "good" code is just a direct translation of our natural, everyday life. I think it's strange to treat the same concept so differently.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Abstraction is the natural language we use every day.&lt;/p&gt;

&lt;p&gt;Next time, I'll explain the specific benefits of using abstraction like this.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 4): TDD Isn't a Cult, It's a Contract</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 16:17:45 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-4-tdd-isnt-a-cult-its-a-contract-29nm</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-4-tdd-isnt-a-cult-its-a-contract-29nm</guid>
      <description>&lt;h1&gt;
  
  
  Why I Hate TDD
&lt;/h1&gt;

&lt;p&gt;You've probably heard the TDD mantra:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;RED: First, write a failing test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GREEN: Write the actual code to make the test pass.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BLUE: Refactor to remove duplication, generalize, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is why I hate TDD.&lt;/p&gt;

&lt;p&gt;But I also love TDD.&lt;/p&gt;

&lt;p&gt;Sounds like nonsense, right? Let me explain. I don't think the essence of TDD is this rigid formula.&lt;/p&gt;

&lt;p&gt;If you've read the first three parts of this series, you know how critical it is to honor your requirements and contracts. We use interfaces in our software to represent these contracts. But how do we know if the contract is actually being fulfilled? Is conforming to an interface enough to satisfy our requirements?&lt;/p&gt;

&lt;p&gt;It’s not enough.&lt;/p&gt;

&lt;p&gt;We test to see if our implementation honors the requirements and contracts. So, isn't the ultimate goal to uphold the contract? Then doesn't it make sense to first create a test that verifies the contract?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TDD is the verification of a contract&lt;/strong&gt;. TDD is a true test that checks if the implementation satisfies the agreement. If the tests don't pass, the implementation is a failure. Why? Because it broke the contract.&lt;/p&gt;

&lt;p&gt;Do you see why I hate the way TDD is described? TDD is a contract verification. It's a living guarantee, a document that evolves. But the dogma tells you to intentionally write failing code?&lt;/p&gt;

&lt;p&gt;The 'RED' step isn't about aiming for failure. It's a natural consequence. You've simply defined the 'contract to be fulfilled' (the test) first, and the implementation that satisfies it doesn't exist yet. The 'failure' isn't the goal; it's just the expected state before the contract is fulfilled. Describing this as "deliberately failing" distorts the purpose and puts the cart before the horse.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why I Love TDD
&lt;/h1&gt;

&lt;p&gt;If you've read the rest of this series, you'll understand how much I value requirements and contracts.&lt;/p&gt;

&lt;p&gt;Whether you write the test first or after, I love TDD from the perspective that it verifies the contract. This is how I use TDD.&lt;/p&gt;

&lt;p&gt;To make it easy to understand, here's a unit test file for a Value Object (VO) class I wrote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TestActorValueObject(unittest.TestCase):

    def test_create_valid_actor_all_fields(self):
        # Contract: Must be able to successfully create an ActorVO with all valid fields.
        vo = ActorVO(name="Tom Hanks", role_name="Forrest Gump", external_id="tmdb_actor_123")
        self.assertEqual(vo.name, "Tom Hanks")
        self.assertEqual(vo.role_name, "Forrest Gump")
        self.assertEqual(vo.external_id, "tmdb_actor_123")

    def test_create_valid_actor_name_only(self):
        # Contract: Must be able to successfully create an ActorVO with only the required field, name.
        vo = ActorVO(name="Song Kang-ho")
        self.assertEqual(vo.name, "Song Kang-ho")
        self.assertIsNone(vo.role_name)
        self.assertIsNone(vo.external_id)

    # ... (and so on for all other test cases) ...

    def test_create_with_empty_name_raises_value_error(self):
        # Contract: Attempting to create with an empty name must raise a ValueError.
        with self.assertRaisesRegex(ValueError, "Actor name cannot be empty."):
            ActorVO(name="")

    def test_actor_equality(self):
        # Contract: Two ActorVO objects must be equal if all their attributes are the same.
        vo1 = ActorVO(name="Same Actor", role_name="Same Role", external_id="ext1")
        vo2 = ActorVO(name="Same Actor", role_name="Same Role", external_id="ext1")
        self.assertEqual(vo1, vo2)

    def test_actor_string_representation(self):
        # Contract: The string representation of an ActorVO object must be displayed appropriately.
        vo_with_role = ActorVO(name="Ma Dong-seok", role_name="Maseokdo")
        self.assertEqual(str(vo_with_role), "Ma Dong-seok (Role: Maseokdo)")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I explicitly state the contracts and constraints that arise from the design as comments. No matter how I implement or change ActorVO, it must honor these contracts. This test suite is the living document that guarantees it.&lt;/p&gt;

&lt;p&gt;What if the requirements themselves change and the contract is updated? I just modify the test. And of course, I update the contract in the comment.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Thoughts on assert
&lt;/h1&gt;

&lt;p&gt;When I first started writing tests, the thing I understood the least was assert.&lt;/p&gt;

&lt;p&gt;You create a result and then check if it matches what you expect. What's the point of that? Seems like a waste of time, right?&lt;/p&gt;

&lt;p&gt;But as we've seen in this series, requirements and contracts are what matter.&lt;/p&gt;

&lt;p&gt;The word assert means "to state a fact or belief confidently and forcefully." Why do we need to 'assert' something in a test? &lt;strong&gt;Because we have to verify that the contract is being met.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;assert(my_implementation_result, what_the_contract_requires)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This assertion is, in essence: &lt;code&gt;my_implementation_result == contract_satisfaction_value.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The assert statement is the most intuitive expression of the purpose of testing: verifying the contract.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;TDD is a helper for OOP. It's the living document that verifies our requirements and contracts are being met.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 3): DDD is Just the Instruction Manual for OOP</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 16:06:44 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-3-ddd-is-just-the-instruction-manual-for-oop-9in</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-3-ddd-is-just-the-instruction-manual-for-oop-9in</guid>
      <description>&lt;h1&gt;
  
  
  How to Design OOP Well
&lt;/h1&gt;

&lt;p&gt;I'm no expert on Domain-Driven Design (DDD), but as far as I can tell, it's just a fancy term for doing OOP well.&lt;/p&gt;

&lt;p&gt;But what does "doing OOP well" even mean? I think it boils down to this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You have to divide things just right.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You have to group things just right.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The groups have to send messages to each other just right.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And that messaging needs to be performant, secure, and stable.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I know you might hate that phrase, "just right." It sounds vague. But I believe that single phrase is the very essence of design.&lt;/p&gt;

&lt;h1&gt;
  
  
  Everything is a Trade-off
&lt;/h1&gt;

&lt;p&gt;There are no silver bullets in software. No flawless solutions, no magic answers that fix everything. Every choice is a trade-off, which means you have to analyze the situation and find the most "just right" solution for the context.&lt;/p&gt;

&lt;p&gt;I didn't make this up; this is what architects always say.&lt;/p&gt;

&lt;p&gt;The hardest part of project design is this fundamental nature of software. Since there are no objective criteria for "just right," your choices will always be subjective.&lt;/p&gt;

&lt;p&gt;Take OOP, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You divide business logic just right, according to the requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You group business logic just right, according to the requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The boundaries communicate just right, according to the requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You implement robust communication just right, according to the requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DDD acts as the guidebook that helps you establish the criteria for 'just right'.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Subject of DDD
&lt;/h1&gt;

&lt;p&gt;Let's state it again: software is about making money. To make money, you have to satisfy your users. To satisfy your users, you have to fulfill their requirements.&lt;/p&gt;

&lt;p&gt;Therefore, DDD starts with getting as specific as possible about the requirements through communication with the customer. And to do that, you first need smooth communication.&lt;/p&gt;

&lt;p&gt;That's why DDD defines what's called a &lt;strong&gt;Ubiquitous Language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In simple terms: developers should primarily use the language that the business experts use.&lt;/p&gt;

&lt;p&gt;You know that one tech guy who insists on using overly technical terms and jargon for no reason? It's annoying as hell, right? It's the same feeling. You don't want to talk to people who deliberately use difficult language when it's not necessary.&lt;/p&gt;

&lt;p&gt;That's exactly how the customer feels. They're trying to explain what they want, and the developers are mixing in programming terms. The customer can't understand a thing and just gets frustrated.&lt;/p&gt;

&lt;p&gt;On the flip side, developers have to fully understand the context behind the customer's requirements. We call this the &lt;strong&gt;Domain&lt;/strong&gt;. If you don't understand the business, you can't understand the business's terminology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Ubiquitous Language&lt;/strong&gt; is the shared vocabulary that everyone—developers and customers alike—agrees to use to ensure smooth communication. It's the process of using these defined terms in your requirements docs, and even in your code, to eliminate any chance of misunderstanding.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dividing and Grouping 'Just Right'
&lt;/h1&gt;

&lt;p&gt;Once you've defined the Ubiquitous Language, you start dividing the entire business into domains of responsibility.&lt;/p&gt;

&lt;p&gt;A popular method for this is Event Storming, but I'm not gonna explain it here. Just look it up. It's a workshop where not just developers, but customers too, get together and map things out. Sometimes you divide based on data, sometimes based on ownership. For the details, check out a book on DDD.&lt;/p&gt;

&lt;p&gt;Once you've drawn the boundaries for the business logic, you have to group the related things inside. Of course, the trick here is also to group them "just right." Usually, you group things based on &lt;strong&gt;transactional consistency&lt;/strong&gt;. And you pick one object in the bundle to be the "representative" or "gateway" for the group. This is the &lt;strong&gt;Aggregate&lt;/strong&gt; and &lt;strong&gt;Aggregate Root&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When these groups communicate, they use this gateway as the standard. This naturally allows you to achieve the OOP goals of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Communicating between boundaries according to requirements.&lt;/li&gt;
&lt;li&gt;Implementing robust communication according to requirements.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Ubiquitous Language&lt;/strong&gt; solved the problem of communication, which was plagued by misunderstandings and assumptions, and clarified the essence of the requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Bounded Context&lt;/strong&gt; gave us clear criteria—'responsibility and language'—to divide a massive business "just right."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Aggregate&lt;/strong&gt; provided a standard for grouping related concepts "just right" within those boundaries, based on the principle of 'data consistency.'&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Aggregate Root&lt;/strong&gt; opened a path for these well-divided and grouped units of responsibility to communicate safely through a clear 'gateway,' without treading on each other's toes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how DDD helps you design OOP well.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 2): Requirements and Contracts</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 15:54:31 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-2-requirements-and-contracts-2hfi</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-2-requirements-and-contracts-2hfi</guid>
      <description>&lt;h1&gt;
  
  
  Requirements are Money
&lt;/h1&gt;

&lt;p&gt;Personally, I think the most important thing in software is making money.&lt;/p&gt;

&lt;p&gt;To make money, you have to satisfy your users or customers. And to do that, you have to satisfy their requirements. Therefore, the most critical job in software is to &lt;strong&gt;figure out and fulfill the requirements.&lt;/strong&gt; Period.&lt;/p&gt;

&lt;h1&gt;
  
  
  OOP and Requirements
&lt;/h1&gt;

&lt;p&gt;Requirements and Object-Oriented Programming are two sides of the same coin. In fact, almost everything in software—OOP, TDD, DDD, and by extension, Microservices—are all just tools to help us satisfy requirements better.&lt;/p&gt;

&lt;p&gt;If your requirements are a mess, all those fancy acronyms are useless. But on the flip side, if you get the requirements right and truly understand the "division of labor" I talked about in Part 1, it finally clicks: &lt;strong&gt;all these methodologies exist to serve the requirements.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements and Contracts
&lt;/h1&gt;

&lt;p&gt;I'm not going to talk about how to gather good requirements here. We'll also save TDD and DDD for later. For now, let's just focus on how to implement well-defined, real-world requirements in software.&lt;/p&gt;

&lt;p&gt;In this series, I'm going to define the methods, expressions, and promises needed to satisfy a requirement as a &lt;strong&gt;"Contract."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A well-designed requirement defines constraints and necessary actions. For example, a smartphone display has the following requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It must turn on.&lt;/li&gt;
&lt;li&gt;Its brightness must be adjustable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a requirement, a contract, a constraint. When we implement this in software, it's a &lt;strong&gt;non-negotiable contract&lt;/strong&gt; we have to fulfill.&lt;/p&gt;

&lt;p&gt;And the tool that lets us express and enforce this contract in code is the &lt;strong&gt;Interface&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Display {
    void turnOn(); // It turns on.
    void setBrightness(int level); // Its brightness can be adjusted.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the display's contract can be explicitly defined in code like this. Therefore, the interface is the tool that &lt;strong&gt;guarantees and enforces this contract in code.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Development Process
&lt;/h1&gt;

&lt;p&gt;If you strip away the operational stuff and just focus on implementing features, the process looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Listen to the requirements through meetings with the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flesh out the requirements through ongoing meetings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write up the contract.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute the project design.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Translate the contract for each part into an interface in code.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The implementation classes must then honor this interface contract to complete the work.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The project's design is critical, and using interfaces is an extension of that design process. That's why they are so important.&lt;/p&gt;

&lt;h1&gt;
  
  
  Back to Requirements and OOP
&lt;/h1&gt;

&lt;p&gt;So, what does all this have to do with Object-Oriented Programming?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the essence of OOP is the 'division of labor', then requirements are the very work that gets divided. They are the standard for that division.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We look at the requirements to decide what to split apart. We analyze the requirements to group related things together. &lt;strong&gt;This very process—of dividing and grouping the system appropriately based on requirements and assigning clear responsibilities to each part—is the object-oriented approach.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And the interface is the tool that enforces the promises (the contracts) between these divided, collaborating objects.&lt;/p&gt;

&lt;p&gt;(Next time, we'll discuss this further.)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Take on OOP (Part 1): It's Just a Damn Assembly Line</title>
      <dc:creator>sour_grape</dc:creator>
      <pubDate>Tue, 24 Jun 2025 15:15:21 +0000</pubDate>
      <link>https://dev.to/sour_grape/my-take-on-oop-part-1-its-just-a-damn-assembly-line-266p</link>
      <guid>https://dev.to/sour_grape/my-take-on-oop-part-1-its-just-a-damn-assembly-line-266p</guid>
      <description>&lt;p&gt;People usually learn Object-Oriented Programming by studying the history of procedural versus object-oriented paradigms.&lt;/p&gt;

&lt;p&gt;My fundamentals are lacking, so I'm just going to interpret OOP my own way.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Quick Rant
&lt;/h1&gt;

&lt;p&gt;Here's my philosophy: Software is made by people. Purely. That means every single thing in software exists because of an intention.&lt;/p&gt;

&lt;p&gt;Given my background, I know that even physics, which people mistake for a search for absolute truth, is full of human interpretation. Software is no different.&lt;/p&gt;

&lt;p&gt;Therefore, to understand software is to understand the choices and intentions of the people who made it.&lt;/p&gt;

&lt;p&gt;And don't treat the original creators like gods. Their ideas aren't made of steel. If you stop being intimidated and just try to figure out what they were thinking, you'll get it pretty quickly.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Purpose of OOP
&lt;/h1&gt;

&lt;p&gt;Why was OOP even created? To build and run programs well. But the model for getting work done efficiently was already perfected during the industrial age.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object-Oriented Programming is the division of labor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The era of artisans passed. With the discovery of coal and the invention of the steam engine, factory-style production through a division of labor proved to be incredibly efficient. This is self-evident.&lt;/p&gt;

&lt;p&gt;Since I'm currently at SSAFY (Samsung Software Academy for Youth), let's use Samsung Electronics as an example.&lt;/p&gt;

&lt;p&gt;Samsung operates through a ruthless division of labor. You have Samsung's DX (Device eXperience), DS (Device Solutions), Research, and so on. Within those, you have business units, and within those, more departments.&lt;/p&gt;

&lt;p&gt;The point is, &lt;strong&gt;the entire company is organized around a strict division of labor, with each part having its own clear responsibilities.&lt;/strong&gt; For example, when Samsung makes a smartphone, countless departments—product planning, design, development, software—collaborate to complete the final product.&lt;/p&gt;

&lt;p&gt;You could say that OOP is just a direct software implementation of this brutally efficient model.&lt;/p&gt;

&lt;p&gt;Therefore, to understand the principles of OOP, you first have to burn this into your brain: &lt;strong&gt;OOP is all about the division of labor.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Design Patterns, 'Laws' of OOP?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;I refuse to memorize that stuff.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing I've noticed about the software field is its weird obsession with jargon and definitions. You get these interview questions like, "Explain encapsulation, polymorphism, and abstraction." Memorizing that crap doesn't seem very helpful.&lt;/p&gt;

&lt;p&gt;If you just think from the perspective of the division of labor, these principles become dead-simple common sense.&lt;/p&gt;

&lt;p&gt;Let's go back to the Samsung example.&lt;/p&gt;

&lt;p&gt;If Samsung pursues peak efficiency through a strict division of labor, then messing up that division kills efficiency.&lt;/p&gt;

&lt;p&gt;The phone's design belongs to the design department. The display is made by the display department. The company's operations are run by the management department. The other departments don't need to—and &lt;strong&gt;shouldn't&lt;/strong&gt;—know their internal business. (&lt;strong&gt;That's Encapsulation.&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;When these departments collaborate, they just send messages. The guys on the assembly line just tell the parts department, "&lt;strong&gt;Gimme the materials.&lt;/strong&gt;" That's it. They get the materials back as a result. (&lt;strong&gt;That's Messaging.&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;When they send these messages, they don't need to know the implementation details of each department.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Gimme a display." (Good).&lt;br&gt;
"Gimme the display with serial number (xxs~~~), produced on this date, with these materials, from that factory..." (Bad).&lt;br&gt;
(That's Abstraction.)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think strictly in terms of dividing labor. That is Object-Oriented Programming.&lt;/p&gt;

&lt;h1&gt;
  
  
  Anti-Patterns
&lt;/h1&gt;

&lt;p&gt;An anti-pattern is when this division of labor breaks down. Simple as that.&lt;/p&gt;

&lt;p&gt;A classic example is the kind of problem at Samsung you see mentioned on Blind (an anonymous employee app). The business guys don't need to know the tech. The technology should be the sole responsibility of the engineers, and management should stick to its own responsibilities. When management crosses that line and meddles with technology, the division of labor has failed, and efficiency is ruined.&lt;/p&gt;

&lt;p&gt;OOP is the exact same. The dependency issues people talk about happen when one object crosses into another's territory and gets too tangled up in its business.&lt;/p&gt;

&lt;p&gt;The way to design OOP well is to group things appropriately and divide responsibilities appropriately. To perfect the division of labor.&lt;/p&gt;

&lt;p&gt;Next time, I'll discuss the methods for doing this.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
