OOP - without GET / SET

Following the "Tell, do not Ask" -principle , you should not use getters in OOP.

But how to solve problems, where (at least I think so), actually some kind of "internal information" from the object is needed? So, how to change the following example so that the create_bill () function does not need to request a price for each element?

class chopping_cart {

    private $itemlist = array();

    function item_add( $name, $price ) {
        $his->itemlist[]=new item( $name, $price );
    }
    private create_bill() {

        foreach $this->itemlist AS $element;
        $sum += $element->get_price();

    }
}


class item {
    private $name;
    private $price;
    function __construcor($name,$price) {...}
    function get_price() {
        return $price;
    }
}

Using:

$sc = new shopping_cart()
$sc->item_add( "Bike", 1.00 );
$sc->item_add( "Ship", 2.00 );
$sc->create_bill();
+5
source share
3 answers

If you are not using the requested data / state to change the object you are referring to, I don't think that something is wrong with getters.

The principle speaks of such a scenario:

if ($item->get_price() < 5) {
    $item->set_price(5);
}

It should be turned into something like $item->set_minimum_price(5).

+7
source

, . , :

  • [...] [] , , , .
    chopping_cart . , , .
  • Design by Contract, ( ) , , , . , , , , .
    , , .

, , ", ".

+4

. Product addToBill, , , IBill. IBill addToTotal, , ; . :

interface IBill {
    /* needs to be public because PHP doesn't understand the concept of 
       friendship
     */
    function addToTotal($price);
}

class Bill implements IBill {
    private $total = 0;

    function addToTotal($price) {
        $this->total += $price;
    }
    ...
}

class ShoppingCart {
    private $items = array();

    function addItem($id, $product, $quantity) {
        if (isset($this->items[$id])) {
            $this->items[$id]->addQuantity($quantity);
        } else {
            $this->items[$id] = new LineItem($product, $quantity);
        }
    }

    private createBill() {
        $bill = new Bill;
        foreach ($this->items AS $lineItem) {
            $lineItem->addToBill($bill);
        }
        return ...;
    }
}

class LineItem {
    private $product, $quantity;
    function __constructor($product, $quantity) {...}
    function addToBill(IBill $bill) {
        $this->product->addToBill($bill, $quantity);
    }
    function addQuantity($quantity) {
        $this->quantity += $quantity;
    }
    ...
}

class Product {
    private $name, $description, $price;
    function __constructor(...) {...}
    function addToBill(IBill $bill, $quantity) {
        $bill->addToTotal($this->price * $quantity);
    }
    ...
}

, . , addToTotal, ( ), "Tell, Do not Ask" , addToTotal: * Bill; ShoppingCart . addItem ; addItem . , LineItem Product . , , , , , , ( ). * addItem Product LineItem; addItem . , , , $price , , addItem , . * . ShoppingCart . addItem . createBill . , , .

There are other potential projects, but each of them suffers from some kind of problem, usually associated with the separation of problems, the introduction of invariants and complexity. In aggregate, access to the total price of a position directly inside a method that calculates the total amount is not only the simplest, but the cleanest and least likely to cause errors.

+2
source

All Articles