Change routing to comply with Law of Demeter

I have a Task, Owner and Plan. Charge values are kept in a plan, owner is on a particular plan and task knows its owner.

A task needs to setup its charges based on the knowledge the owner has. Owner however needs to consult a plan to get those done. According to the Law of Demeter I am not allowed to do:

class Task {

    /**
     * @var Owner
     */
    private $owner;

    public function prepareCharges() {
        $plan = $this->owner->getPlan();
        $plan->chargeFor(...);
    }

So I am wondering if this sort of routing trick is a viable solution.

class Task {

    /**
     * @var Owner
     */
    private $owner;

    public function prepareCharges() {
        $this->owner->helpMeDoTheCharges($this);
    }

    public function doPlanCharges(Plan $plan) {
        $distanceCharge = new Money();
        $plan->chargeFor('distance', $distanceCharge);

        $fixedCharge = new Money();
        $plan->chargeFor('fixed', $fixedCharge);
    }

}

Task basically tells its owner to push the plan to it so it can send it messages.

class Plan {

    public function chargeFor($type, Money $money) {

    }

}

class Owner {

    private $plan;

    public function helpTaskDoTheCharges(Task $task) {
        $task->doPlanCharges($this->plan);
    }

}

7

I would suggest that you do something like the following:

class Task {
   public function prepareCharges() {
      $charges = new Charges();
      $distanceCharge = new Money();
      $charges->add('distance', $distanceCharge);

      $fixedCharge = new Money();
      $charges->add('fixed', $fixedCharge); 

      $this->owner->charge($charges);
   }
}

class Owner {
   public function charge(Charges $charges) {
       $this->plan->charge($charges);
   }
}

Basically, instead of trying to awkwardly induce a situation where you have references to all those objects, put all of the charges inside a value object and pass it the owner.

The intention of the Law of Demeter is to minimize the knowledge that one part of your system has about another. Task shouldn’t know about Plan. Your approach of having Owner call back into Task with a Plan may the follow the letter of the Law of Demeter, but it results in Task having in-depth knowledge of Owner, precisely what Demeter is trying to avoid. You’d be better off returning the plan because that code was easier to follow.

Usually you’d just use a layer of indirection…

class Task {

    private $owner;

    public function prepareCharges() {
        $this->owner->chargeFor(...);
    }
...

class Owner {
    public chargeFor() {
        $plan = $this->getPlan();
        $plan.chargeFor(...)
        ...

I think you should make the owner responsible for managing their charges, and simply pass the task to the owner. That way the task never has to touch the plan at all.

I don’t think your alternative is really that much better because a task still has to know about a plan and know that it’s responsible for determining the cost.

Here’s an example, I’m assuming the task is responsible for determining the cost variable (execution time), the plan is responsible for determining the rate per unit of cost variable, and the customer is responsible for accounting for the cost accrued over time:

class Task {

    /**
     * @var Owner
     */
    private $owner;

    public function execute() {
        // Do whatever a task does
        $this->owner->charge($this);    
    }

   public function getExecutionTime() {
       return 10; // Just an example
   }
}

class Owner {

    private $plan;
    private $bill = 0;

    public function charge(Task $task) {
        $taskCost = $this->plan->calculateCost($task->getExecutionTime());
        $bill += $taskCost;
    }

}

class Plan {

    private $rate = 0.5;

    public function calculateCost($time) {
        return $rate * $time;
    }

}

If owners is responsible for invoking the task execution then you might be able to get away with not even passing the owner to the task at all, you could simply invoke the task and get the execution time from within the owner. That way the task wouldn’t depend on an owner to run, although if other aspects of your task depend on having an owner then that wouldn’t be practical.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật