DTO 可以引用域模型的 VO 吗?
Can a DTO reference VO of the domain model?
问题
数据传输 object (DTO) 可以引用域模型的值 object (VO) 吗?
上下文
在我的域中,我有一个从 collection 导入聚合的导入器。 collection 由进口商依赖的收集器构建的 DTO 制成。由于导入器和收集器都是我域的服务(接口),DTO 可以引用域值 objects,还是我应该坚持使用原语并仅在处理 objects 时将它们转换为值 objects =27=](聚合构建)?
收集器实现,其中构建了由域模型中的值 object 构成的 DTO
<?php
/**
* i-MSCP Patcher plugin
*
* @author Laurent Declercq <l.declercq@nuxwin.com>
* @copyright (C) 2019 Laurent Declercq <l.declercq@nuxwin.com>
* @license i-MSCP License <https://www.i-mscp.net/license-agreement.html>
*/
/**
* @noinspection
* PhpUnhandledExceptionInspection
* PhpDocMissingThrowsInspection
*/
declare(strict_types=1);
namespace iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentBuild;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentName;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentVersion;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\ComponentCollector;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTO;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTOCollection;
use iMSCP_Config_Handler_File as MergedConfig;
use iMSCP_Plugin_Manager as PluginManager;
use RuntimeException;
use Throwable;
/**
* Class DefaultComponentCollector
* @package iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer
*/
class DefaultComponentCollector implements ComponentCollector
{
/**
* @var MergedConfig
*/
private $mergedConfig;
/**
* @var PluginManager
*/
private $pluginManager;
/**
* DefaultComponentCollector constructor.
*
* @param MergedConfig $mergedConfig
* @param PluginManager $pluginManager
*/
public function __construct(
MergedConfig $mergedConfig, PluginManager $pluginManager
)
{
$this->mergedConfig = $mergedConfig;
$this->pluginManager = $pluginManager;
}
/**
* @inheritDoc
*/
public function collect(ComponentDTOCollection $collection): void
{
try {
// Core
$collection->add(new ComponentDTO(
ComponentName::fromString('core'),
ComponentVersion::fromString($this->mergedConfig['Version']),
ComponentBuild::fromString($this->mergedConfig['Build'])
));
// Plugins
$this->collectComponentsFromCorePluginManager($collection);
} catch (Throwable $e) {
throw new RuntimeException(sprintf(
"Couldn't collect list of components: %s", $e->getMessage()
), $e->getCode(), $e);
}
}
/**
* Collects components from the i-MSCP core plugin manager.
*
* @param ComponentDTOCollection $collection
* @return void
*/
private function collectComponentsFromCorePluginManager(
ComponentDTOCollection $collection
): void
{
$pluginList = $this->pluginManager->pluginGetList('all', false);
foreach ($pluginList as $pluginName) {
$pluginInfo = $this->pluginManager
->pluginGetInfo($pluginName)
->toArray();
$componentDTO = new ComponentDTO(
ComponentName::fromString($pluginInfo['name']),
ComponentVersion::fromString($pluginInfo['version']),
ComponentBuild::fromString((string)$pluginInfo['build'])
);
$collection->add($componentDTO);
}
}
}
Can a data transfer object (DTO) reference a value object (VO) of the domain model?
是的,但是您要非常小心这样做。
一条data transfer object的核心是一条消息。为了使消息达到其目的,发送方和接收方都必须对其语义具有兼容的理解。对 DTO 架构进行不兼容的更改需要对接收方进行相应的更改。
域模型中的值对象不是消息。它是结构化信息,纯粹是当前模型的实现细节。如果我们想部署一个新版本的模型,它使用完全不同的值排列或它们的底层数据结构,那么我们可以。
因此,让 DTO(应该是稳定的)依赖于值对象(不承诺是稳定的)正在为未来的问题创造机会。
如果您的价值观词汇稳定,则风险较低。
问题
数据传输 object (DTO) 可以引用域模型的值 object (VO) 吗?
上下文
在我的域中,我有一个从 collection 导入聚合的导入器。 collection 由进口商依赖的收集器构建的 DTO 制成。由于导入器和收集器都是我域的服务(接口),DTO 可以引用域值 objects,还是我应该坚持使用原语并仅在处理 objects 时将它们转换为值 objects =27=](聚合构建)?
收集器实现,其中构建了由域模型中的值 object 构成的 DTO
<?php
/**
* i-MSCP Patcher plugin
*
* @author Laurent Declercq <l.declercq@nuxwin.com>
* @copyright (C) 2019 Laurent Declercq <l.declercq@nuxwin.com>
* @license i-MSCP License <https://www.i-mscp.net/license-agreement.html>
*/
/**
* @noinspection
* PhpUnhandledExceptionInspection
* PhpDocMissingThrowsInspection
*/
declare(strict_types=1);
namespace iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentBuild;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentName;
use iMSCP\Plugin\Patcher\Domain\Model\Component\ComponentVersion;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\ComponentCollector;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTO;
use iMSCP\Plugin\Patcher\Domain\Service\Component\Importer\DTO\ComponentDTOCollection;
use iMSCP_Config_Handler_File as MergedConfig;
use iMSCP_Plugin_Manager as PluginManager;
use RuntimeException;
use Throwable;
/**
* Class DefaultComponentCollector
* @package iMSCP\Plugin\Patcher\Infrastructure\Domain\Service\Component\Importer
*/
class DefaultComponentCollector implements ComponentCollector
{
/**
* @var MergedConfig
*/
private $mergedConfig;
/**
* @var PluginManager
*/
private $pluginManager;
/**
* DefaultComponentCollector constructor.
*
* @param MergedConfig $mergedConfig
* @param PluginManager $pluginManager
*/
public function __construct(
MergedConfig $mergedConfig, PluginManager $pluginManager
)
{
$this->mergedConfig = $mergedConfig;
$this->pluginManager = $pluginManager;
}
/**
* @inheritDoc
*/
public function collect(ComponentDTOCollection $collection): void
{
try {
// Core
$collection->add(new ComponentDTO(
ComponentName::fromString('core'),
ComponentVersion::fromString($this->mergedConfig['Version']),
ComponentBuild::fromString($this->mergedConfig['Build'])
));
// Plugins
$this->collectComponentsFromCorePluginManager($collection);
} catch (Throwable $e) {
throw new RuntimeException(sprintf(
"Couldn't collect list of components: %s", $e->getMessage()
), $e->getCode(), $e);
}
}
/**
* Collects components from the i-MSCP core plugin manager.
*
* @param ComponentDTOCollection $collection
* @return void
*/
private function collectComponentsFromCorePluginManager(
ComponentDTOCollection $collection
): void
{
$pluginList = $this->pluginManager->pluginGetList('all', false);
foreach ($pluginList as $pluginName) {
$pluginInfo = $this->pluginManager
->pluginGetInfo($pluginName)
->toArray();
$componentDTO = new ComponentDTO(
ComponentName::fromString($pluginInfo['name']),
ComponentVersion::fromString($pluginInfo['version']),
ComponentBuild::fromString((string)$pluginInfo['build'])
);
$collection->add($componentDTO);
}
}
}
Can a data transfer object (DTO) reference a value object (VO) of the domain model?
是的,但是您要非常小心这样做。
一条data transfer object的核心是一条消息。为了使消息达到其目的,发送方和接收方都必须对其语义具有兼容的理解。对 DTO 架构进行不兼容的更改需要对接收方进行相应的更改。
域模型中的值对象不是消息。它是结构化信息,纯粹是当前模型的实现细节。如果我们想部署一个新版本的模型,它使用完全不同的值排列或它们的底层数据结构,那么我们可以。
因此,让 DTO(应该是稳定的)依赖于值对象(不承诺是稳定的)正在为未来的问题创造机会。
如果您的价值观词汇稳定,则风险较低。