Inheritance or Dependency?

5

Well, my question is this. I am refactoring a system where I have an integration with a REST API, there is a class called Marketplace (which makes the API queries) which I currently extend from class Curl (which is a simplified interface for PHP curl).

The question is, should Marketplace be extended from class Curl or maybe Curl should be a dependency of class Marketplace ?

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

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

        return $this->getResponseBody();
    }
}

Or% with dependency%

<?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 it be, let's say a better structure? And if possible why ..

    
asked by anonymous 22.11.2014 / 15:53

2 answers

3

Looking at the cohesion and coupling side, which is one of the key points of the Dependency Injection , I I'd prefer to make Curl a dependency of Marketplace , so you'll have better cohesion, a low matching which will generate a better level of encapsulation.

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

Another important point is that as Marketplace grows, it may break the Principle of replacing Liskov , by talking about it, I recommend you read about the SOLID principles , are very cool foundations for agile development and readable code.

    
22.11.2014 / 17:37
2

This is a common question for anyone who starts working with Object Orientation. And, to make matters worse, a lot of people try to explain, but it complicates so much the explanation that the amendment ends worse than the sonnet.

When in doubt about when to extend a class, use an interface (extra credit), or inject another from an object, you should ask yourself if your object is a particular thing, if it > can be a certain thing (besides itself) or it only needs of a certain thing to work.

  • If you respond that a object is something else, you apply an inheritance.

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

  • If you respond that your only needs another object, inject it as a dependency.

In your particular case, Marketplace is not a Curl object, but it can be , so you should have an interface.

I would suggest, however, something more subjective, since 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 is using this class gets a OffersDataAccess which can be a Marketplace as well as a Catalog a CommercialBreak (commercial range) or even an OutdoorAnnouncement (outdoor):

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 );
    
22.11.2014 / 16:24