DDD从外部API,存储库和域服务构造AggregateRoot实体

问题描述 投票:0回答:2

试图将DDD原则应用于小项目...我有PlayerProfile聚合根,它由Club实体和Rating值对象的集合组成。我必须定期从外部门户同步所有PlayerProfile的实体,解析原始HTML。

现在我想出了包装代码的解决方案,用简单的PlayerProfile更新PlayerProfileRepository,如下所示:

public interface IPlayerProfileRepository
{
    Task<IReadOnlyCollection<PlayerProfile>> SyncPlayersProfilesFromPortal(string sourceUrl);
    // other methods, which works with data storage
}

首先,我真的不喜欢混合方法的想法,它与数据存储一起使用方法,它与外部资源(HTML页面)一起定期创建PlayerProfile。对我而言,这听起来更像是PlayerProfileFactory的职责?

IPlayerProfileRepository的实际实现将实际页面的解析委托给3个IPageParser,它实际上与我的存储库位于同一层。像这样的东西:

    public PlayerProfileRepository(
        IPageParser<ParseClubDto> clubPageParser,
        IPageParser<ParsePlayerProfileDto> playerProfilePageParser,
        IPageParser<ParseRatingDto> ratingPageParser)

    {
        _playerProfilePageParser = playerProfilePageParser;
        _clubPageParser = clubPageParser;
    }

我不太确定所有这些Dtos实际上是Dtos,只要它们仅用于IPageParser来解析页面时保存中间数据。我想密切关注数据服务层中的IPageParser实现,但不要在单独的Dtos项目中共享它们,并且可能以不同的方式命名。

ParseClubDtoParsePlayerProfileDtoParseRatingDto解析后,我将它传递给PlayerProfileFactory.Create工厂方法,如下所示:

var playerProfiles = new List<PlayerProfile>();

var clubs = await _clubPageParser.ParseAsync(sourceUrl);

foreach (var club in clubs)
{
    var clubPlayers = await _playerProfilePageParser.ParseAsync(club.PlayersPageUrl);

    foreach (var clubPlayer in clubPlayers)
    {
        var ratings = await _ratingPageParser.ParseAsync(clubPlayer.RatingsPageUrl);

        playerProfiles.Add(PlayerProfileFactory.Create(club, clubPlayer, ratings));
     }
}

return playerProfiles;

完成此操作后,我必须与DB中的现有agreggate根目录进行实际同步,我通过在聚合根上调用ResyncFrom(PlayerProfile profile)来实现简单,或者它应该更像是单独的PlayerProfile域服务?

总的来说,我觉得我做错了什么,所以欢迎任何评论?

c# domain-driven-design ddd-repositories
2个回答
0
投票

我认为您的示例是使用反腐败图层模式在两个BC之间进行集成的情况。

我将有一个端口(域中的接口)与方法契约,返回播放器配置文件聚合列表。

在基础架构层中,我将有一个适配器,通过从远程门户读取html数据(例如使用REST API)并从该数据构建聚合来实现端口。

在应用程序层,我将有一个应用程序服务,您可以在其中注入处理本地数据库的端口和播放器配置文件聚合存储库。应用程序服务调用端口来构造聚合,然后调用存储库来存储它们。

我会定期运行这个应用程序服务。

这将是没有事件的异步集成,但如果远程门户触发事件,您可以使用事件实现它。


0
投票

IPlayerProfileRepository接口通常在域中定义,并通常通过Id向外界描述应如何检索聚合根。所以SyncPlayersProfilesFromPortal方法肯定不应该是这个接口的一部分。同步数据是基础设施问题,可以在后台异步完成,如前面的答案中所述。

© www.soinside.com 2019 - 2024. All rights reserved.