0

I have a class named as A and another Class named as B. Class A contains Class B as a property.

I have a business logic. Based on the value of a property in Class B, I have to calculate the value of another property in Class A. To do this calculation, I have to call a SOAP service, get a value and then, based on the value of a property in Class B, i have to do a mathematical calculation on the returned value from the SOAP service and then set the value for property in Class A.

public Class A{
  public string Property1{get;set;}
  public int Property2{get;set;}
  public B Property3{get;set;}
}

public class B{
 public string Property1{get;set;}
 public string Property2{get;set;}
}

The logic in pseudocode

  1. If classB.property1 = "Something1" then call soap service,get some integer value, perfome some arithmatical calculation using a constant, and assign the result to classA.Property2
  2. Else If classB.property1 = "Something2" then call soap service,get some integer value, and assign the result to classA.Property2
  3. Else then set classA.Property2 to a default value.

I dont like the If else, it doesnt follow the OCP. I was thinking of doing this with a decorator. The second option is to use a builder pattern and encapsulate the if else logic, but still it would break the OCP. Or a completely new Domain service that would perform this?But still the OCP is being broken if If else even if i chose to go the Domain service way.

The above logic is being performed in a business logic class.

So where does the responsibility for above logic of calculation go? Also how to avoid that if else?

Hari Subramaniam
  • 1,814
  • 5
  • 26
  • 46
  • @RobbyCornelissen . Thank you. I have edited it now – Hari Subramaniam Jun 30 '15 at 04:03
  • What are you looking for when trying to enforce OCP in this particular instance ? Are you implying that the decision logic should be in class `A` but the condition values ("something1", "something2") should be declared elsewhere because they are likely to change ? On what axis should this little system be *open for extension* ? – guillaume31 Jun 30 '15 at 09:15

3 Answers3

1

In DDD, ClassA is the aggregate root in this scenario and should be the one to handle this logic. ClassB could have a reference to ClassA; I personally prefer to let me relationships be a strict, one-direction, relationship. Meaning ClassB does not get to know that ClassA, exists. There are some edge cases where I break this rule; not many though.

Instead, I would use Domain events to facilitate this. There are a few good examples of this online to look at. Basically, the logic would be abstracted from both ClassA and ClassB. Rather a Domain Event would handle it. The event object would be given a message, containing a reference to both ClassA and ClassB, process it, assign what ever values it needs to (or better yet, pass them in to the classes via controlled methods), and be done. This makes the act of calculating a little more testable and allows you to reuse this component in more than one place.

Community
  • 1
  • 1
Johnathon Sullinger
  • 7,097
  • 5
  • 37
  • 102
1

I would create a DDD-type 'domain service' that takes a dependency on the SOAP service via an interface and do it that way. Nice and testable, and I can't see why it wouldn't be OCP-compliant.

Making the domain model dependent on external services should be avoided.

David Osborne
  • 6,436
  • 1
  • 21
  • 35
0

We really need more details of both "what these values are" and "will they be used in any other ways now or in the future" to be able to cleanly say where they should go.

That said, first, we can clean up your pseudocode to be:

Get a value from Class B.
If that value is equal to "foo":
   call SOAP service
   do math
   assign value to property2
Else if it's equal to "bar":
   call SOAP service
   assign value to property2
Else
   assign default value to property2

If there's no other way that anyone calls this value from class B, and there are no other calls from your code to the SOAP service, this functionality should probably be in class B, to hide the logic from external caller.

Dean J
  • 39,360
  • 16
  • 67
  • 93
  • 1
    Personally I would think this logic belongs outside of the business logic wouldn't it? The domain layer shouldn't be reaching out to a soap service imo. – Johnathon Sullinger Jun 30 '15 at 04:27