從百草園到三味書屋 (一)依賴注入

一句話兒發表於2020-02-10
簡單分析如下程式碼,是否存在問題?
class UserController extends BaseController{     
    public function getIndex()     {         
        $users = User::all();         
        return View::make('users.index', compact('users'));     
    } 
}

分析:

  1. 這段程式碼很 簡短,但我們要想測試這段程式碼的話就一定會和實際的資料庫發生聯絡。

  2. 也就是說, Eloquent ORM(譯者注:Laravel的資料庫物件模型庫)和該控制器有著緊耦合。如果不使用Eloquent ORM,不連線到實際資料庫,我們就沒辦法執行或者測試這段程式碼。這段程式碼同時也違背了“關注分離”這個軟體設計原則。

  3. 簡單講:這個控制器知道的太多了。 控制器不需要去了解資料是從哪兒來的,只要知道如何訪問就行。控制器也不需要知道這資料是從MySQL或哪兒來的,只需要知道這資料目前是可用的。

每一個類都應該有單獨的職責,並且該職責應完全被這個類封裝。

//定義介面
interface UserRepositoryInterface
{
    public function all();
}

//實現介面
class DbUserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all()->toArray();
    }
}

// 面向介面程式設計,透過建構函式,注入例項(實現介面的任意類例項)
class UserController extends BaseController
{
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }

    public function getIndex()
    {
        $users=$this->users->all();
        return View::make('users.index', compact('users'));
    }
}

分析:

  1. 現在我們的控制器就完全和資料層面無關了。在這裡無知是福!

  2. 我們的資料可能來自MySQL,MongoDB或者Redis。我們的控制器不知道也不需要知道他們的區別。

  3. 僅僅做出了這麼小小的改變,我們就可以獨立於資料層來測試Web層了,將來切換儲存實現也會很容易。

記得要保持清晰的責任邊界。 控制器和路由是作為HTTP和你的應用程式之間的中介軟體來用的。當編寫大型應用程式時,不要將你的領域邏輯混雜在其中(控制器、路由)。

場景:提醒使用者交錢,需用到支付 和 通知 兩個方法。

//定義賬單支付介面
interface BillerInterface {
    public function bill(array $user, $amount);
}

//定義賬單通知介面
interface BillingNotifierInterface {
    public function notify(array $user, $amount);
}

//實現賬單支付介面,同時注入,賬單通知介面
class StripeBiller implements BillerInterface{
    public function __construct(BillingNotifierInterface $notifier)
    {
        $this->notifier = $notifier;
    }

    public function bill(array $user, $amount)
    {
        $this->notifier->notify($user, $amount);
    }
}

//使用sms作為賬單支付通知,那我們如何做依賴注入呢?很簡單:
$biller = new StripeBiller(new SmsNotifier);

分析:

  1. 這就是依賴注入。(與容器ioc可以是脫離獨立存在的,後面會講解ioc)

  2. biller不需再考慮提醒使用者的事兒,我們直接傳給他一個提示器(notifier)。 這種微小的改動能使你的應用煥然一新。

  3. 你的程式碼馬上就變得更容易維護, 因為明確指定了類的職責邊界。 並且更容易測試, 你只需使用模擬依賴即可。

依賴注入的核心,是基於介面程式設計,實際目的在於解耦,使得類之間更加獨立,健壯,易於維護。

原文連結: https://my.oschina.net/zgldh?tab=newest&am...

本作品採用《CC 協議》,轉載必須註明作者和本文連結
寫的不好,就當是整理下思緒吧。

相關文章