7. Interface vs Concrete
class Process
{
protected $ls;
public function __construct()
{
$this->ls = new Ls();
}
public function execute()
{
}
}
class Ls
{
public function invoke(): string
{
return 'ls';
}
}
このProcessクラスは、
lsに依存
他のコマンドを実装する場合、
OO Processクラスをたくさん
作成しなければならない
Lsクラスの実行メソッドはinvoke他のクラ
スの実行メソッドは違うかもしれない
8. Interface vs Concrete
class Command
{
public function process()
{
(new Process())->execute();
(new HogeProcess())->handle();
(new FugaProcess())->dispatch();
}
} クラスによって利用方法が異なる
各コマンドによる利用方法の違いを
知っていなければ利用できない
9. Interface vs Concrete
interface ProcessCommandInterface
{
/**
* @return string
*/
public function command(): string;
}
コマンドを提供
このインターフェースを実装するクラスは、
このメソッドを実装しなければならない
10. Interface vs Concrete
class Ls implements ProcessCommandInterface
{
public function command(): string
{
return 'ls';
}
}
11. Interface vs Concrete
class Process
{
protected $command;
public function __construct(
ProcessCommandInterface $command
) {
$this->command = $command;
}
public function execute()
{
$this->command->command();
}
}
このインターフェースを
実装したクラスであればなんでも良い
このメソッドは必ず存在する
12. Interface vs Concrete
class Command
{
protected $commandClass = [
Ls::class,
Rm::class,
];
public function process()
{
foreach($this->commandClass as $class) {
(new Process(new $class()))->execute();
}
}
}
一括で操作可能
外部から渡されるクラスによって
振る舞いが変わる
設定値として外から指定することも可
13. Laravel Service Container
• 外から実行クラスを指定する機能を元に設計
• インターフェースと具象クラスの指定は
Service Providerに記載
• フレームワークの機能はこの手法で拡張
45. データベースの戻り値を堅実に
use App¥Item;
final class IndexController extends Controller
{
public function __invoke()
{
foreach(Item::all() as $item) {
$item->item_id;
}
}
}
データベースのカラムとして
返ってきますが、
アクセス可能なプロパティは、
テーブル構造を知っている必要があります
52. リポジトリを抽象レイヤとして扱い堅実に
use App¥Item;
final class IndexController extends Controller
{
public function __invoke(
HogeRepository $repository
) {
$repository->all();
}
}
データベースへのアクセスを抽象化したもの
ただし返却は前述の通りカラム
53. リポジトリを抽象レイヤとして扱い堅実に
class HogeRepository
{
protected $item;
public function __construct(Item $item)
{
$this->item = $item;
}
public function all()
{
$result = [];
foreach($this->item->all() as $row) {
$result[] = new ItemMapper($row->item_id);
}
return $result;
}
}
Collection生成のように扱う
yieldしても良いでしょう
54. ビジネスロジックはクラスで表現する
class PaymentService
{
private $repository;
public function __construct(Repository $repository)
{
$this->repository = $repository;
}
public function pay(int $money)
{
$this->repository->add($money);
}
public function quantity(int $itemID)
{
// aaa
}
}
購入系ビジネスロジック?
依存が増えて複雑になりそう!
ここに処理がまとまってるから書こう!
あっという間に巨大クラス