0

Clearing things on the beggining:

  • I understand how to apply OCP to code below (virtual class, DI and so on, there are tons of resources on web about that)

  • I know (but do not understand) arguments why I need to apply OCP (3 that mainly occur on web are listed below)

  • I think I am missing the point because I do not have big enough commercial experience.

What I don't understand in OCP are the arguments/consequences (mentioned below) found in all articles regarding OCP

Violating OCP is bad because:

1. You need to write test for old class - it is bad, better to write test for new class.

I do not understand why it is bad?

In both cases I need to write new test. Either for new class or for old class.

2. You need to redeploy application If there are two clients: A (which do not need new functionality) and B (who wants new functionality)

2.1 When I am violating OCP by modifying base class.

client A - do not need to redeploy - because he don't need new functionality

client B - need to redeploy - to get new functionality

2.2 When I am not violating OCP by adding derived class.

client A - do not need to redeploy - because he don't need new functionality

client B - need to redeploy - to get new functionality

I do not understand why I need to redeploy whole application? In both cases it is the same situation- client A do not need to redeploy, client B need to get redeployed application.

3. You can introduce a mistake to the working system But I can also do that when I will put new functionality in it, can't I?

Can you help me understand the meaning of these points above? I was using following example from website

public enum InvoiceType
{
    Final,Proposed
};

public class Invoice
{
    public InvoiceType InvoiceType { get; set; }

    public double GetDiscount(double amount,InvoiceType invoiceType)
    {
        double finalAmount = 0;
        if (invoiceType == InvoiceType.Final)
        {
            finalAmount = amount - 100;
        }
        else if(invoiceType == InvoiceType.Proposed)
        {
            finalAmount = amount - 50;
        }
        return finalAmount;
    }

}
TommyLee
  • 1
  • 1

1 Answers1

1

Let me try to give you some insight, however I'm not going to cover all the problems you've mentioned.

First and most important. Tests. Typical enterprise app contains ~10000-~20000 unit tests, not considering data randomization (if any, which is rarely the case: OO-programmers haven't discover tools like Haskell's QuickCheck). And those tests are typically kind of entrance to the hell. Hundreds of mocks wired up in a given sequence, complicated dependency injections just to "make it work" and other kind of setups mixed up with test implementation heavily relied on the helpful methods of the... test classes or somewhat class SuchKindOfTestsUtilities. In most cases there is either no time to cleanup tests frequently, or people just don't care: somewhy it is assumed that tests can contain duplicate of code, violate well-known principles of clean code without any consequences...

Now imagine you have to introduce new functionality. There is time pressure. There are tens of classes and stuff you're not quite familiar with. And you got choice like Neo: either green (don't like blue color) or red, where "green" represents "DO NOT CHANGE WHAT IS WORKING UNLESS ABSOLUTELY NECESSARY!!!" paradigm; indeed, "freezing" existing things, especially poorly coded, is the best way to go unless your manager and business ready to wait (and to pay) for a long refactorings (which they usually consider a time-waster).

And that one is just a tip of the iceberg ;)

Zazaeil
  • 3,900
  • 2
  • 14
  • 31
  • Thanks a lot for your answer! :) I think i need some more explanation... I am thinking, how adding additional code in this switch will break other tests. Let's assume: We will have Test 1 which will check InoviceType.Final part, and we will have Test 2 which will check InoviceType.Proposed part. How adding Test 3 for let's say InvoiceType.SemiFinal part will broke other tests ? – TommyLee Mar 11 '18 at 11:23
  • 1
    @TommyLee your example is way to simple to reflect problem of a typical enterprise. Bear in mind that those ideas came from millions-of-code-application, distributed in many different forms over many different platforms. Thus the complexity you're missing is key factor. – Zazaeil Mar 11 '18 at 11:26
  • Complexity could be a factor here, but i believe that it could be explained without the need to dig into system with milions LOC. People are learning design patterns somehow :) I will come back here one day and answer my question i guess. – TommyLee Mar 12 '18 at 16:08