-3

I'm having a hard time to grasp a solution for the following problem.

I am decoupling the classes with their correspondent interface but I need to extend the class for a new change instead of changing the original implementation in order to be compliant with open close principle.

This the base class HttpRequest implementing IHttpRequest

public class HttpRequest : IHttpRequest
{
    public string RawUrl { get; protected set; }

    public HttpRequest(string rawUrl)
    {
        RawUrl = rawUrl;
    }

    public string GetJsonFromUrl(string url)
    {
        //
    }
}

public interface IHttpRequest
{
    string GetJsonFromUrl(string url);
}

and the extended class is UrlMetadataResolver:

public class UrlMetadataResolver : HttpRequest
{
    public UrlMetadataResolver(string rawUrl) : base(rawUrl)
    {
        //
    }
}

What should I do? should I created an interface for UrlMetadataResolver (IUrlMetadataResolver)?

If that's the case it becomes even more confusing.

Thanks

RollRoll
  • 8,133
  • 20
  • 76
  • 135
  • 2
    Its hard to know what your actual concerns are, though i assume you are doing this for DI... can the functionality of `UrlMetadataResolver` go int to HttpRequest ? or are they sufficiently separate concerns. if they are, inheriting, is not a bad thing, however can be a slippery slope. In general using composition is usually preferred over inheritance in more complex situations – TheGeneral Oct 20 '18 at 02:21
  • the are separated concerns solving different problems, UrlMetadataResolver will have few methods on its own, thats where the confusion gets worst, thanks – RollRoll Oct 20 '18 at 02:23
  • I also prefer not inheriting when I can use some association, but I do believe they could not be exclusive (either association(whether composition or agregation) or inheritance). – RollRoll Oct 20 '18 at 02:26
  • You gotta ask what code will be using these classes and in which context? Does the client code needing a UrlMetadataResolver care about the fact that it's implemented through an `HttpRequest`? Probably not. – plalx Oct 20 '18 at 05:23
  • 3
    you have not shown what extension is required. All you have shown is another class that inherits from another. This is confusing as we do not have the entire picture of what you are trying to achieve – Nkosi Oct 22 '18 at 12:41
  • @RollRoll, What responsibility does UrlMetadataResolver class have? – Maksym Fedorov Oct 22 '18 at 12:59
  • @RollRoll What behaviors does `UrlMetadataResolver` have? Would a client using a `UrlMetadataResolver` want to use the underlying `HttpRequest` features as well? No one can answer this question without more details about the problem you are trying to solve. – plalx Oct 24 '18 at 00:56
  • This is exactly why, i do not like company tests\assessments, which say something like show how you would apply SOLID principles to xyz, they always something silly like the above.. which doesn't have a right or wrong answer subjectively. – Seabizkit Oct 25 '18 at 07:12
  • Is `UrlMetadataResolver` really a type of `HttpRequest`? Would it make sense for another object to interact with it only knowing that it was an `HttpRequest`? Or it just something that, in one particular implementation happens to make use of an `HttpRequest` object to do its work? That seems more likely, in which case `UrlMetadataResolver` shouldn't implement `IHttpRequest` at all. – Dylan Nicholson Oct 26 '18 at 20:51
  • @RollRoll What's the point of a bounty if you are not to answer any of the above questions? – plalx Oct 27 '18 at 17:49

2 Answers2

2

It is true that since you don't provide any description on what you want to accomplish, there can't be any complete or specific answer.

But here is a hint or two:

If you're already using the HttpRequest class then probably the best thing is not to change it; in order to be compliant with open close principle, as you said. So yes create a new class.

If the new fuctionality of UrlMetadataResolver class is indeed extending the functionality of the HttpRequest class; meaning it uses the methods of HttpRequest and some additional too, then yes, you should inherit from HttpRequest, to be able to use its methods, and add your new methods in the new class.

And in this case yes, you should create a new interface that inherits from IHttpRequest and extends it. The meaning of an interface is to allow a change in the way the things are implemented, without changing the way the things are done. I.e. you can later use another approach and implement the UrlMetadataResolver functionalities in another way, by another class. Using an interface will allow you to change only that, without changing anything in your business layer, in the references of the IUrlMetadataResolver interface.

Composition is a good practise too, as suggested, but makes more sense in cases where we want to inherit from more than one classes. C# and .NET clearly favors composition over inheritance (and they do well) by not allowing inheritance of more than one class.

If, on the other hand, the new functionality, doesn't extend, but rather overrides the functionality of HttpRequest, then the way to go is to mark the HttpRequest methods as virtual, inherit and override in UrlMetadataResolver.

You can assume of course that you can go both ways; override and extend the HttpRequest class.

You can always of course create a new class UrlMetadataResolver with no relation to the HttpRequest.

Hope I could help, merry coding!

Kostas Dafnomilis
  • 629
  • 1
  • 5
  • 13
0

I recommend creating a base class that implements all methods the classes have in common:

public abstract class HttpBaseRequest : IHttpRequest
{
    protected HttpBaseRequest(string rawUrl)
    {
        RawUrl = rawUrl;
    }


    public string RawUrl{ get; protected set; }


    public string GetJsonFromUrl(string url)
    {
        return "";
    }
}



public class HttpDataRequest : HttpBaseRequest
{
    public HttpDataRequest(string rawUrl) : base(rawUrl) { }
}



public class UrlMetadataResolver : HttpBaseRequest
{
    public UrlMetadataResolver(string rawUrl) : base(rawUrl) { }
}

If required you can still create an interface IUrlMetadataResolver.

horotab
  • 675
  • 3
  • 20