Home > Enterprise >  Add an extra property to an element without inheritance
Add an extra property to an element without inheritance

Time:07-19

I am thinking about the best practice in OOP for the following problem:

We have a program that is working with an external API.

The API has an object of type Element which is basically a geometric element. Our application is a validation application that runs on a geometric model The application takes a collection of those elements and performs some geometric tests on them.

We wrap this API element with our own class called "ValidationElement" and save some additional information to this wrapper element that can not be obtained directly from the API Element but is required by our application.

So far so good, but now the application should expand and support other types of models (basically we can say that the app is running in a different environment). Specifically for this environment (and it does not apply to the previous cases), we want to save an additional parameter that obtaining it results in low performance.

What is the best practice option to implement it? On one hand, I would like to avoid adding extra parameters that are not relevant to a specific(the first) part of the program. And on the second hand, I am not sure that I want to use inheritance and split this object just for this small additional property.

public class ValidationElement
{
        public Element Element { get; set; }
        public XYZ Location {get; set;}//The extra property
}

The first and easy option is that the same class will have the additional property and calculation method:

public class ValidationElement
{
        public Element Element { get; set; }
        public XYZ Location {get; set;}//The extra property
        public string AdditionalProperty { get; set; }
        public void HardProcessingCalcOfAdditionalProperty()
        {
            //hard processing
            AdditionalProperty = result
        }
}

The second option that I mentioned is the inheritance

public class SecondTypeValidationElement : ValidationElement
{
        public string AdditionalProperty { get; set; }
        public void HardProcessingCalcOfAdditionalProperty()
        {
            //hard processing
            AdditionalProperty = result
        }
}

What do you think is the best practice for this? Is there any other way or design pattern that should help me achieve the goal?

CodePudding user response:

OOP and SOLID best practice is to use abstractions (interfaces or abstract classes), wich is closer to your second approach.

Dependency Inversion Principle: The Dependency Inversion principle states that our classes should depend upon interfaces or abstract classes instead of concrete classes and functions.

Your first approach to edit the ValidationElement class is generally a bad idea, given that there are several environments for the project to be run onto. In addition, maintaining and developing the project on this approach is not scalable and will be a headache in the long run.

Open-Closed Principle: The Open-Closed Principle requires that classes should be open for extension and closed to modification.

I suggest below designing:

public interface IValidationElement
{
    Element Element { get; set; }
    XYZ Location {get; set;}//The extra property

    // declare other base properties and methods
}

public class ValidationElement: IValidationElement
{
    public Element Element { get; set; }
    public XYZ Location {get; set;}//The extra property

    // define other base properties and methods
}

public interface ISecondTypeValidationElement: IValidationElement
{
    string AdditionalProperty { get; set; }
    void HardProcessingCalcOfAdditionalProperty();
}

public class SecondTypeValidationElement: ISecondTypeValidationElement
{
    public string AdditionalProperty { get; set; }
    public void HardProcessingCalcOfAdditionalProperty()
    {
        //hard processing
        AdditionalProperty = result
    }
}

public interface IThirdEnvironmentValidationElement: IValidationElement
{
    string ThirdProperty { get; set; }
    void RequiredProcessing();
}

public class ThirdEnvironmentValidationElement: IThirdEnvironmentValidationElement
{
    public string ThirdProperty { get; set; }
    public void RequiredProcessing()
    {
        //related operations
    }
}

CodePudding user response:

I would like to avoid adding extra parameters that are not relevant to a specific(the first) part of the program.

It looks like it is a sign that an inheritance shoulbe be avoided here. As there is a strong possibility that this behaviour is not applicable for other classes.

And this is the second reason to avoid of creation some abstraction:

Element which is basically a geometric element

Because:

So let's prefer composition over inheritance.

So, in my view, it would be really good if we move all heavy, tightly coupled logic of calculating of additional property to separate class:

public class ValidationElement
{
    public string Element { get; set; }

    public SomeExtra AdditionalProperty { get; set; }
}

public class SomeExtra
{
    public string Location { get; set; }//The extra property

    public string AdditionalProperty { get; set; }

    public void HardProcessingCalcOfAdditionalProperty()
    {
        //hard processing
        AdditionalProperty = string.Empty;
    }
}

Why have we created separate class SomeExtra and put logic here:

  • if we want to edit logic HardProcessingCalcOfAdditionalProperty, then we will edit just one class SomeExtra. By doing this we are satisfying Single Responsibility Principle of SOLID principles.
  • we can easily create some base abstract class for SomeExtra and then at runtime we can decide what concrete implementation should be injected. By doing this we are satisfying Open Closed Principle of SOLID principles.
  • Related