SOLID Principle In Laravel with Repository Pattern
SOLID Principle In Laravel with Repository Pattern
我对在维护 SOLID 原则的同时使用 Controller with Repository Pattern 感到有些困惑。考虑一下,我有两种类型的 Quotations
- 商业报价
- 私人报价
而且以后很有可能出现新的报价类型。每个报价单都有不同的领域、业务逻辑,但它们有许多共同的功能。所以我创建了一个 QuotationInterface
报价界面
interface QuotationInterface
{
public function save(array $data);
}
实现接口的引用class
class CommercialQuotation implements QuotationInterface
{
public function(array $data)
{
// save commercial quotation
}
}
class PrivateQuotation implements QuotationInterface
{
public function(array $data)
{
// save Private quotation
}
}
报价资料库
class QuotationRepository
{
public function save(array $data, QuotationInterface $quotation)
{
$quotation->save($data);
}
}
QotationController
public function store(Resource $resource)
{
$inputs = $resource->all();
/**
* Clearly here Open/Close Principle is broken
*/
if ($inputs['type'] == 'private'){
$quotation = new PrivateQuotation;;
}
else if($inputs['type'] == 'commercial'){
$quotation = new CommercialQuotation;
}
$this->repo->save($inputs, $quotation);
}
在我的 QuotationController 中,它显然违反了 Open/Close 原则..
是否为每种类型的报价创建一个控制器(有一天可能会超过 10 个,谁知道?)以避免违反 OCP 或我的设计是个好主意只是错了吗?欢迎任何建议、设计更改提示和资源。
注意:我的 Quotation Controller 除了仅保存外还有许多其他功能。
我认为这主要取决于您的应用范围。在如今的 PHP 世界中,人们对 if/else 的言论非常愤怒 :)。但是,如果这适用于您的应用程序并且在您的上下文范围内看起来合理,我认为这很好。
业务变化和业务变化并不总是容易规划。您只能在这些更改出现时尝试使它们更容易。
话虽这么说,类 很便宜,我认为现在(以及将来)单独使用 类 是非常合理的。如果对每种类型的报价单的要求都扩大了,那么您的立足点就会很好,而且我认为您目前还没有抽象到代码难以理解的程度。
如果你按照你所展示的方式前进,我建议你为你的报价单使用一个控制器,并使用 Factory 设计模式来创建你的 $quotation
个对象
例如,像这样的简单工厂:
//FACTORY CLASS
abstract class QuotationFactory
{
/** return QuotationInterface */
public static function createQuotation($type)
{
switch($type)
{
CASE "private":
return new PrivateQuotation();
break;
CASE "commercial":
return new CommercialQuotation();
break;
}
}
}
您可以使用控制器方法中的工厂:
//YOUR CONTROLLER'S METHOD
public function store(Resource $resource)
{
$inputs = $resource->all();
//delegate objects creation to factory class
$quotation = QuotationFactory::createQuotation( $inputs['type'] );
$this->repo->save($inputs, $quotation);
}
这样你就不会违反控制器中的open/closed原则,因为当你添加引号时,你只需要修改工厂的方法(将 case 添加到 switch 语句) , 它会在需要的地方 return 一个 QuotationFactory
对象。
这也将保留您的代码 DRY 和 SOLID 因为您不必重复 if/else 语句来在将创建对象的责任委托给特定工厂时,在控制器的方法中创建对象 class
正如下面评论中正确指出的那样,简单工厂将帮助您避免控制器中的 Open/Closed 原则,但请注意,从更一般的角度来看,简单工厂本身本质上违反了 OCP,因为它使用了开关盒。
无论如何,从我对您的应用程序的了解来看,简单工厂可能是一个很好的解决方案,因为您主要关心的是在许多地方从变量类型构建实例。因此,使用简单工厂,您可以 'hide' 在工厂中创建对象的过程,并在您的控制器中获取您需要的实例。所以你只是在开关盒的工厂内部违反了 OCP,但我认为这可能是一个可以承受的权衡
我知道来晚了,但我希望我的评论能帮助更多人搜索您的问题。
您应该遵循以下原则:
“如果你有这样的条件,你应该在低级抽象中而不是在高级抽象中进行”
所以设计应该是:
class QuotationFactory
{
public static function make($type)
{
switch($type)
{
CASE "private":
return new PrivateQuotation();
CASE "commercial":
return new CommercialQuotation();
default:
throw new InvalidTypeException("Invalid type code.");
}
}
}
上述重构称为“用多态替换conditional/type代码”。
如果以后没有新的类型,你应该遵循“用显式方法替换参数”重构,这将提高可读性。
要了解更多信息,您应该阅读 Martin Fowler 的一本名为“重构:改进现有代码的设计”的书。
我对在维护 SOLID 原则的同时使用 Controller with Repository Pattern 感到有些困惑。考虑一下,我有两种类型的 Quotations
- 商业报价
- 私人报价
而且以后很有可能出现新的报价类型。每个报价单都有不同的领域、业务逻辑,但它们有许多共同的功能。所以我创建了一个 QuotationInterface
报价界面
interface QuotationInterface
{
public function save(array $data);
}
实现接口的引用class
class CommercialQuotation implements QuotationInterface
{
public function(array $data)
{
// save commercial quotation
}
}
class PrivateQuotation implements QuotationInterface
{
public function(array $data)
{
// save Private quotation
}
}
报价资料库
class QuotationRepository
{
public function save(array $data, QuotationInterface $quotation)
{
$quotation->save($data);
}
}
QotationController
public function store(Resource $resource)
{
$inputs = $resource->all();
/**
* Clearly here Open/Close Principle is broken
*/
if ($inputs['type'] == 'private'){
$quotation = new PrivateQuotation;;
}
else if($inputs['type'] == 'commercial'){
$quotation = new CommercialQuotation;
}
$this->repo->save($inputs, $quotation);
}
在我的 QuotationController 中,它显然违反了 Open/Close 原则..
是否为每种类型的报价创建一个控制器(有一天可能会超过 10 个,谁知道?)以避免违反 OCP 或我的设计是个好主意只是错了吗?欢迎任何建议、设计更改提示和资源。
注意:我的 Quotation Controller 除了仅保存外还有许多其他功能。
我认为这主要取决于您的应用范围。在如今的 PHP 世界中,人们对 if/else 的言论非常愤怒 :)。但是,如果这适用于您的应用程序并且在您的上下文范围内看起来合理,我认为这很好。
业务变化和业务变化并不总是容易规划。您只能在这些更改出现时尝试使它们更容易。
话虽这么说,类 很便宜,我认为现在(以及将来)单独使用 类 是非常合理的。如果对每种类型的报价单的要求都扩大了,那么您的立足点就会很好,而且我认为您目前还没有抽象到代码难以理解的程度。
如果你按照你所展示的方式前进,我建议你为你的报价单使用一个控制器,并使用 Factory 设计模式来创建你的 $quotation
个对象
例如,像这样的简单工厂:
//FACTORY CLASS
abstract class QuotationFactory
{
/** return QuotationInterface */
public static function createQuotation($type)
{
switch($type)
{
CASE "private":
return new PrivateQuotation();
break;
CASE "commercial":
return new CommercialQuotation();
break;
}
}
}
您可以使用控制器方法中的工厂:
//YOUR CONTROLLER'S METHOD
public function store(Resource $resource)
{
$inputs = $resource->all();
//delegate objects creation to factory class
$quotation = QuotationFactory::createQuotation( $inputs['type'] );
$this->repo->save($inputs, $quotation);
}
这样你就不会违反控制器中的open/closed原则,因为当你添加引号时,你只需要修改工厂的方法(将 case 添加到 switch 语句) , 它会在需要的地方 return 一个 QuotationFactory
对象。
这也将保留您的代码 DRY 和 SOLID 因为您不必重复 if/else 语句来在将创建对象的责任委托给特定工厂时,在控制器的方法中创建对象 class
正如下面评论中正确指出的那样,简单工厂将帮助您避免控制器中的 Open/Closed 原则,但请注意,从更一般的角度来看,简单工厂本身本质上违反了 OCP,因为它使用了开关盒。
无论如何,从我对您的应用程序的了解来看,简单工厂可能是一个很好的解决方案,因为您主要关心的是在许多地方从变量类型构建实例。因此,使用简单工厂,您可以 'hide' 在工厂中创建对象的过程,并在您的控制器中获取您需要的实例。所以你只是在开关盒的工厂内部违反了 OCP,但我认为这可能是一个可以承受的权衡
我知道来晚了,但我希望我的评论能帮助更多人搜索您的问题。
您应该遵循以下原则:
“如果你有这样的条件,你应该在低级抽象中而不是在高级抽象中进行”
所以设计应该是:
class QuotationFactory
{
public static function make($type)
{
switch($type)
{
CASE "private":
return new PrivateQuotation();
CASE "commercial":
return new CommercialQuotation();
default:
throw new InvalidTypeException("Invalid type code.");
}
}
}
上述重构称为“用多态替换conditional/type代码”。
如果以后没有新的类型,你应该遵循“用显式方法替换参数”重构,这将提高可读性。
要了解更多信息,您应该阅读 Martin Fowler 的一本名为“重构:改进现有代码的设计”的书。