Посетитель бизнес-объекта в домене в гексагональной / луковой архитектуре? - PullRequest
0 голосов
/ 03 февраля 2019

Я использую гексагональную архитектуру, и мне интересно, как шаблон посетителя будет уважать его?

Посещаемый объект является объектом домена, но посетитель стремится динамически диспетчеризовать указанные реализации объекта домена для соответствующих преобразователей между доменом.объект и объект передачи данных.

Моей первой мыслью было бы раскрыть абстракцию посетителя в домене и оставить его фактические реализации в инфраструктуре, аналогичной хранилищу.

Разве это не раскрывает инфраструктуру?Шаблон посетителя - это детали реализации, верно?Это не приносит никакой коммерческой ценности, поэтому не относится к домену, не так ли?Однако мне нужен метод accept в моем бизнес-объекте для достижения этого шаблона.

Что вы думаете об этом?

РЕДАКТИРОВАТЬ Пример кода (синтаксис C #, но ничего особенного):

namespace Domain
{
    public interface IFlow
    {
        void Accept(IFlowVisitor visitor);
    }

    public class Cashflow : IFlow
    {
        void Accept(IFlowVisitor visitor)
        {
            visitor.Visit(this);
        }

        // some properties
    }

    public class Assetflow : IFlow
    {
        void Accept(IFlowVisitor visitor)
        {
            visitor.Visit(this);
        }

        // some properties
    }

    public interface IFlowVisitor
    {
        void Visit(Assetflow flow);
        void Visit(Cashflow flow);
    }
}

namespace Infra
{
    public class FlowVisitor : IFlowVisitor
    {
        public FlowVisitor(ICashflowMapper cashflowMapper, IAssetflowMapper assetflowMapper, IDao dao)
        {
            CashflowMapper = cashflowMapper;
            AssetflowMapper = assetflowMapper;
            Dao = dao;
        }

        private readonly ICashflowMapper CashflowMapper {get; set;}
        private readonly IAssetflowMapper AssetflowMapper {get; set;}
        private readonly IDao Dao {get; set;}

        public void Visit(Assetflow flow)
        {
            Assetflow assetflowDto = AssetflowMapper.Map(flow);
            dao.Persist(assetflowDto);
        }

        public void Visit(Cashflow flow)
        {
            CashflowDto cashflowDto = CashflowMapper.Map(flow);
            dao.Persist(cashflowDto);
        }
    }

    public interface ICashflowMapper
    {
        CashflowDto Map(Cashflow domainObject);
    }

    public interface IAssetflowMapper
    {
        AssetflowDto Map(Assetflow domainObject);
    }

    public interface IDao
    {
        void Persist(CashflowDto dto);
        void Persist(AssetflowDto dto);
    }

    public class cashflowDto 
    {
        // property bag
    }
    public class assetflowDto
    {
        // property bag
    }

    public class Test
    {
        public void TestMethod()
        {
            ICashflowMapper cashflowMapper = new CashflowMapper();
            IAssetflowMapper assetflowMapper = new AssetflowMapper();
            IDao dao = new Dao();
            IFlowVisitor visitor = new FlowVisitor(cashflowMapper, assetflowMapper, dao)
            List<IFlow> flows = new List<IFlow> { new Assetflow(), new Cashflow(), new Assetflow() };

            foreach(var flow in flows)
            {
                flow.Accept(visitor);
            }
        }
    }
}

1 Ответ

0 голосов
/ 03 февраля 2019

Это правда, что реализация шаблона этого конкретного посетителя предполагает небольшое загрязнение домена, но часто лучше быть прагматичным, чем быть пуристом.Если это было бы наиболее практичным решением с выбранным вами языком, иначе вы бы столкнулись с гораздо более сложными техническими реализациями, тогда плюсы перевесили бы минусы и так и было.

К счастью, C # поддерживает динамическую диспетчеризацию с использованиемключевое слово dynamic, которое освобождает вас от использования метода Accept для ваших доменных объектов.

Например

public class FlowVisitor {

    public void Visit(IFlow flow) {
        Visit((dynamic) flow);
    }

    // Specific visit methods (private)...
}
...