[英]Refactoring to comply with the DRY principle
I am trying to find a way to refactor this code so I don't to repeat same code in many places. 我试图找到一种重构此代码的方法,以免在很多地方重复相同的代码。 I am looking for DRY principle. 我正在寻找DRY原则。
This is an example of createDaemon()
method. 这是createDaemon()
方法的示例。
function createDaemon($server, $command, $user)
{
try {
DB::beginTransaction();
$model = $server->daemons()->create([
'command' => $command,
'user' => $user,
]);
$shell = $this->getCommand('add-daemon', [
'daemonId' => $daemon->id,
'command' => $command,
'user' => $user,
]);
$this->pushToQueue($model, $shell);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
return $model;
}
This is another example of createRule()
in another class, as you can see the code is almost the same. 这是另一个类中的createRule()
另一个示例,因为您可以看到代码几乎相同。 How to refactor this into DRY principle - would you create a new method or class to do the same logic? 如何将其重构为DRY原理-您会创建一个新方法或类来执行相同的逻辑吗?
public function createRule($server, $name, $port, $ipAddress = null)
{
try {
DB::beginTransaction();
$model = $server->rule()->create([
'name' => $name,
'port' => $port,
]);
$shell = $this->getCommand('rule', [
'port' => $port,
'ipAddress' => $ipAddress
]);
$this->pushToQueue($model, $shell);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
return $model;
}
I think I would create one common method like this: 我想我会创建一个像这样的常用方法:
public function createGeneralRule(Closure $closure)
{
try {
DB::beginTransaction();
[$model, $shell] = $closure();
$this->pushToQueue($model, $shell);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
return $model;
}
and now you can do use it like this: 现在您可以像这样使用它:
function createDaemon($server, $command, $user)
{
return $this->createGeneralRule(function() use ($server, $command, $user) {
$model = $server->daemons()->create([
'command' => $command,
'user' => $user,
]);
$shell = $this->getCommand('add-daemon', [
'daemonId' => $daemon->id,
'command' => $command,
'user' => $user,
]);
return [$model, $shell];
}
}
and 和
public function createRule($server, $name, $port, $ipAddress = null)
{
return $this->createGeneralRule(function() use ($server, $name, $port, $ipAddress) {
$model = $server->rule()->create([
'name' => $name,
'port' => $port,
]);
$shell = $this->getCommand('rule', [
'port' => $port,
'ipAddress' => $ipAddress
]);
return [$model, $shell];
}
}
Of course you could also use classes, but it really depends how many times you are going to reuse this code and what flexibility do you really need. 当然,您也可以使用类,但这实际上取决于要重用此代码的次数以及您真正需要的灵活性。
Using classes it could be something like this: 使用类可能是这样的:
abstract class Rule
{
public function process()
{
try {
DB::beginTransaction();
$model = $this->model();
$shell = $this->shell();
$this->pushToQueue($model, $shell);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
return $model;
}
protected function getCommand($name, $data)
{
// here you put implementation you had before of getCommand
}
abstract protected function model();
abstract protected function shell();
}
class Deamon extends Rule
{
protected $server;
protected $command;
protected $user;
public function __construct($server, $command, $user)
{
$this->server = $server;
$this->command = $command;
$this->user = $user;
}
protected function model()
{
return $this->server->daemons()->create([
'command' => $this->command,
'user' => $this->user,
]);
}
protected function shell()
{
return $this->getCommand('add-daemon', [
'daemonId' => $daemon->id, // this is unknown, should be passed in constructor?
'command' => $this->command,
'user' => $this->user,
]);
}
}
and in your controller you would use it like this: 在您的控制器中,您将像这样使用它:
(new Deamon($server, $command, $user))->process(); (新的Deamon($ server,$ command,$ user))-> process();
Just in case - keep in mind you have $deamon
variable which is not defined (it's not defined also in your controller) 以防万一-请记住,您有未定义的$deamon
变量(在控制器中也未定义)
Extends 延伸
You can make them extend the same base class: 您可以使它们扩展相同的基类:
class foo{
public function myMethod(){}
}
class bar extends foo{ }
class biz extends foo{ }
Now both subclasses have the method myMethod
现在两个子类都具有方法myMethod
Trait 特征
You can use a trait for the shared functionality 您可以将特征用于共享功能
trait foo{
public function myMethod(){}
}
class bar{
use foo;
}
class biz{
use foo;
}
As for the actual functionality I would break it down into 3 methods: I was going to write something on it but I see @Marcin Nabiałek, has a good answer for that part. 至于实际的功能,我将其分解为3种方法:我打算在上面写一些东西,但是我看到@MarcinNabiałek在这方面有很好的答案。 I just wanted to cover how to structure the classes in order to re-use a common method. 我只想介绍如何构造类以重新使用通用方法。
Cheers. 干杯。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.