в TokenRepository
Вы можете увидеть 3 аналогичных метода. Он создает новую запись в таблице токенов, но у каждого метода есть свои поля.
Как я могу рефакторинг это? Должен ли я объединить 3 метода в 1 метод или использовать шаблон стратегии?
Класс TokenRepository:
class TokenRepository
{
public function createTokenDigitalOcean(User $user, $name, $accessToken, $refreshToken = null)
{
return $user->tokens()->create([
'name' => $name,
'provider' => 'digital_ocean',
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
]);
}
public function createTokenLinode(User $user, $name, $key)
{
return $user->tokens()->create([
'name' => $name,
'provider' => 'linode',
'linode_key' => $key,
]);
}
public function createTokenAws(User $user, $name, $key, $secret)
{
return $user->tokens()->create([
'name' => $name,
'provider' => 'aws',
'aws_key' => $key,
'aws_secret' => $secret,
]);
}
}
У меня есть 3 класса, как DigitalOceanProvider
, LinodeProvider
а также AwsProvider
, Например использования LinodeProvider
и класс AwsProvider.
class LinodeProvider
{
public function callback()
{
$this->tokenRepo->createTokenLinode($user, $name, $key);
}
}class AwsProvider
{
public function callback()
{
$this->tokenRepo->createTokenAws($user, $name, $key, $secret);
}
}
Это может быть немного излишним, но для того, чтобы облегчить жизнь в будущем, вы можете создать отдельные реализации каждой из них, которые расширяют абстрактный класс. Таким образом, вы можете унифицировать и определить интерфейс и легко добавлять новые типы токенов.
<?php namespace Foo\Tokens;
abstract class Token
{
protected $name = '';
protected $key = '';
protected $provider = '';
public function __construct($name, $key)
{
$this->name = $name;
$this->key = $key;
}
public function data()
{
return [
'name' => $this->name,
'provider' => $this->provider,
'token' => $this->key
];
}
}
Затем мы создаем наш класс токенов Digital Ocean. Этот класс может использовать реализацию по умолчанию или переопределить ее.
<?php namespace Foo\Tokens;
use Foo\Tokens\Token;
class DigitalOceanToken extends Token
{
protected $provider = 'digital_ocean';
public function __construct($name, $key, $refreshToken = null)
{
parent::__construct($name, $key);
$this->refreshToken = $refreshToken;
}
public function data()
{
return [
'name' => $this->name,
'provider' => $this->provider,
'key' => $this->key,
'refreshToken' => $this->refreshToken
];
}
}
TokenRepository теперь просто заботится о присоединении данного токена к пользователю.
<?php namespace Foo;
use User;
use Foo\Tokens\Token;
class TokenRepository
{
public function createToken(User $user, Token $token)
{
return $user->tokens()->create(
$token->data()
);
}
}
И ваши поставщики услуг так же просто, как …
<?php
use Foo\Tokens\AwsToken;
class AwsProvider
{
public function callback()
{
$this->tokenRepo->createToken(
$user, new AwsToken($name, $key, $secret)
);
}
}
Это не рабочий код, поскольку я не пытался его запустить, но это просто еще одна идея о том, как вы можете организовать и распределить ответственность. Надеюсь, что это поможет, и приветствуем отзывы других.
По моему мнению, вы должны реализовать это так:
class TokenRepository
{
public function createTokenForVendor(User $user, $inputs)
{
return $user->tokens()->create($inputs);
}
}
и внутри вашего обратного вызова:
class VendorProvider
{
public function callback()
{
switch($tokenType) {
case 'DigitalOcean':
$inputs = [
'name' => $name,
'provider' => 'digital_ocean',
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
];
break;
case 'Linode':
$inputs = [
'name' => $name,
'provider' => 'linode',
'linode_key' => $key,
];
break;
case 'Aws':
$inputs = [
'name' => $name,
'provider' => 'aws',
'aws_key' => $key,
'aws_secret' => $secret,
];
break;
}
$this->tokenRepo->createTokenForVendor($user, $inputs);
}
}
Надеюсь, вам следует обновить структуру кода.
Надеюсь это поможет!