Inheritance or Addiction?

Asked

Viewed 117 times

5

Well, my question is this. I’m refactoring a system where I have an integration with a REST API, there’s a class called Marketplace (That queries the API) that I currently extend from the class Curl (Which is a simplified PHP Curl interface).

The point is, class Marketplace should even be extended from the class Curl or maybe Curl should be a class dependency Marketplace?

Class Marketplace extended current (illustrative and simplified...)

<?php
class Marketplace extends Curl
{
    public function getOffers()
    {
        $this->get('/marketplace/offers');

        return $this->getResponseBody();
    }
}

Or Marketplace addictive

<?php
class Marketplace
{
    private $_curl;

    public function __construct(Curl $curl)
    {
        $this->_curl = $curl;
    }

    public function getOffers()
    {
        $this->_curl->get('/marketplace/offers');

        return $this->_curl->getResponseBody();
    }
}

What would be, say, a better structure? And if possible why..

  • 1

    Ask yourself: MarketPlace adds functionality to the class Curl or just needs it to function?

  • In fact it will not add new features to Curl.

  • So the best choice in this case is addiction, right?

  • 1

    Exactly. From the examples you’ve shown, it’s just a dependency. But it doesn’t mean that if your system grows, MarketPlace does not extend a class that may come between this and the Curl.

  • Don’t forget to mark some answer as resolved. Your question today may be someone else’s tomorrow. ;)

2 answers

3

Seeing on the side of cohesion and coupling, which is one of the key points of the Dependency injection, I’d rather make Curl a dependency on Marketplace, thus you will have a better cohesion, a low involvement which will generate a better level of encapsulation.

I think so because Curl has sufficient characteristics to become an encapsulated object (component), so Marketplace will use it as a dependency. A great advantage is that if in the future the communication of Marketplace no longer via Curl, you can create an interface with the methods that must be implemented and apply it in Curl and in the new class to be created.

Another important point is that as Marketplace grow, she might break the Principle of Liskov’s replacement, by the way, I recommend you read about the SOLID PRINCIPLES, are very legal grounds for agile development and readable code.

  • 1

    Thank you Marcio, and thanks for the references, it will be of great help!

  • @Caiocésar, Imagine! I’m glad to help! Continue so you’re on the right track!

2

This is a common question to those who start working with Object Orientation. And, to make matters worse, many people try to explain, but it ends up complicating the explanation so much that the amendment ends up worse than the sonnet.

When in doubt about when to extend a class, use an interface (extra credit) or inject another coming from an object, you should ask yourself if your object is a certain thing, if he can be a certain such thing (besides himself) or he just need of a certain thing to work.

  • If you answer that an object is another thing, you apply an inheritance.

  • If you answer that your object can be something other than itself, implement an interface. Even empty, they serve as types, which is great for polymorphism.

  • If you answer that your object just need from one another, instill it as dependency.

In your particular case, Marketplace is not an object Curl, but he can be, then you should have an interface.

I would suggest, however, something more subjective, because the data can come from anywhere, whether local, from a database, or remote. And if remote, you can use Curl or Stream Sockets:

interface OffersDataAccess {

    public function getOffers();
}

class Marketplace implements OffersDataAccess {

    public function getOffers() {}
}

And whoever uses that class gets one Offersdataaccess which may be a Marketplace as can also be a Catalog (Catalog of Offers), a Commercialbreak (commercial break) or even a Outdoorannouncement (billboard):

class Catalog implements OffersDataAccess {

    public function getOffers() {}
}

class CommercialBreak implements OffersDataAccess {

    public function getOffers() {}
}

class OffersController {

    public function listOffers( OffersDataAccess $offers ) {

        return $offers -> getOffers();
    }
}

class OutdoorAnnouncement  {

    public function listOffers( OffersDataAccess $offers ) {

        return $offers -> getOffers();
    }
}

$controller = new OffersController;

$marketPlaceOffers         = $controller -> listOffers( new Marketplace );
$catalogOffers             = $controller -> listOffers( new Catalog );
$commercialBreakOffers     = $controller -> listOffers( new CommercialBreak );
$outdoorAnnouncementOffers = $controller -> listOffers( new OutdoorAnnouncement );
  • Thanks Bruno, I think I could understand better on this issue applying the questions. So I think if I had several Marketplaces (Ex: Extra, Walmart) they could extend from the same (Class Marketpace) so would be new objects, I’m sure?

  • 1

    Yes and no, everything would depend on the magnitude of the application. If you have several Marketplaces that share characteristics (properties) and/or actions (methods) then yes, it would be fit to create an abstract class with everything they would have in common, implement the interface in it and everyone would extend this super-class (and consequently the interface). If there is no significant gain in abstraction, you should not do it as you would just be inflicting Syntatic Sugar in its Application.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.