
Saat menggunakan arsitektur dalam gaya irisan vertikal, cepat atau lambat timbul pertanyaan "apa yang harus dilakukan jika kode muncul yang perlu digunakan di beberapa penangan sekaligus?"
TLDR: Anda perlu membuat middleware penangan dan menambahkan antarmuka penanda khusus untuk memperjelas penangan mana yang merupakan abstraksi holistik dan mana yang bukan.
Jawaban atas pertanyaan ini tidak selalu jelas. Jimmy Boggard, misalnya, menyarankan " refactoring saja ". Saya sepenuhnya mendukung pendekatan ini, tetapi bentuk jawabannya menurut saya sama mengecewakannya dengan proposal untuk menggunakan monad gratis untuk injeksi ketergantungan dalam pemrograman fungsional . Nasihat ini tepat dan singkat, tetapi tidak terlalu membantu. Saya akan mencoba menjawab pertanyaan ini lebih detail.
Refactoring
Jadi, saya akan menggunakan dua teknik refactoring:
, :
public IEnumerable<SomeDto> Handle(SomeQuery q)
{
// 100 ,
//
// 50 ,
//
return result;
}
, , 100 50 . , . ยซยป, ctrl+shift+r -> extract method . โ .
, , - :
public IEnumerable<SomeDto> Handle(SomeQuery q)
{
var shared = GetShared(q);
var result = GetResult(shared);
return result;
}
?
public IEnumerable<SomeDto> Handle(SomeQuery q)
{
var shared1 = GetShared1(q);
var shared2 = GetShared2(q);
var shared3 = GetShared3(q);
var shared4 = GetShared4(q);
var result = GetResult(shared1,shared2, shared3, shared4);
return result;
}
public class ConcreteQueryHandler:
IQueryHandler<SomeQuery, IEnumerable<SomeDto>>
{
??? _sharedHandler;
public ConcreteQueryHandler(??? sharedHandler)
{
_sharedHandler = sharedHandler;
}
}
///- (Domain Services). IDomainHandler<TIn, TOut>
, IHandler<TIn, TOut>
.
. . , โ , .
.
public class ConcreteQueryHandler2:
IQueryHandler<SomeQuery, IEnumerable<SomeDto>>
{
IDomainHandler<???, ???> _sharedHandler;
public ConcreteQueryHandlerI(IDomainHandler<???, ???> sharedHandler)
{
_sharedHandler = sharedHandler;
}
}
public class ConcreteQueryHandler2:
IQueryHandler<SomeQuery, IEnumerable<SomeDto>>
{
IDomainHandler<???, ???> _sharedHandler;
public ConcreteQueryHandlerI(IDomainHandler<???, ???> sharedHandler)
{
_sharedHandler = sharedHandler;
}
}
?
, IHandler
. , , .
, , . , ยซ ยป. , .
-: , IDomainHandler<???, ???>
. :
-
ICommand/IQuery
? -
IQueryable<T>
?
ICommand/IQuery
?
public interface ICommand<TResult>
{
}
public interface IQuery<TResult>
{
}
IDomainHandler
Command/Query
, .
IQueryable<T>
?
, ORM:) โฆ LINQ LSP , โ ยซยป. , , . IQueryable
โ .
- Memasukkan ketergantungan lapisan domain sebagai argumen konstruktor
public class ConcreteQueryHandler:
IQueryHandler<SomeQuery, IEnumerable<SomeDto>>
{
IDomainHandler<
SomeValueObjectAsParam,
IQueryable<SomeDto>>_sharedHandler;
public ConcreteQueryHandler(
IDomainHandler<
SomeValueObjectAsParam,
IQueryable<SomeDto>>)
{
_sharedHandler = sharedHandler;
}
public IEnumerable<SomeDto> Handle(SomeQuery q)
{
var prm = new SomeValueObjectAsParam(q.Param1, q.Param2);
var shared = _sharedHandler.Handle(prm);
var result = shared
.Where(x => x.IsRightForThisUseCase)
.ProjectToType<SomeDto>()
.ToList();
return result;
}
}