Friday, March 25, 2011

vaccine framework example - preview 3 (create order)

Salam

Adad beberapa minor changes dlm codebase vaccine framework, yang utama sekali ialah macam maner aku nak handle part read side iaitu reporting.Aku akan sentuh part nie nanti. Tetapi untuk sekarang nie aku nak tunjukkan bagaimana aku pecahkan relation Customer dari Order dan pecahkan relation OrderLine dari Product.

Kalau tengok balik domain diagram yang sebelum nie, domain diagram ini adalah cara design yang kebiasaan dari kita akan buat apabila menggunakan cara n-tier, dimana dlm domain tersebut kita ubah, dalam domain tersebut juga kita baca latest state object tersebut untuk kita tunjukkan kepada client balik dan kebiasaan juga, process ini akan melibatkan kita map dengan class Data Transfer Object untuk reshape maklumat kepada UI screen di client.



Selepas tu aku cakap jika menggunakan DCI+CQSR+Event Sourcing, kita boleh pecahkan relation tadi dan letakkan reference tersebut berada dalam Role, dan relation ini bersifat sementara.Kenapa Role penting? Ini adalah kerana kita boleh share role diantara aggregateroot object yang lain dengan syarat aggregateroot object tersebut juga perlulah memenuhi contract Role yang didefine. Dan di dalam Role jugalah berlaku interaction antara object, sebagai contoh jika condition ini berlaku, execute object yang itu, etc.

Berbalik pada demo code yang aku nak tunjuk, sebelum nie aku dah tunjukkan bagaimana nak create Customer, tetapi ada beberapa code penting aku terlupa nak cerita, menyebabkan terdapat beberapa kekeliruan.InsyAllah aku cuba terangkan dengan lebih lengkap dalam n3 kali ini.

Untuk create Order bagi specific Customer, kita perlu lah juga ada Product, so process untuk create Product adalah lebih kurang macam mana nak create Customer.

Jadi sekarang nie aku dah adalah list Customer dan aku juga dah ada list Product. UI dia ada seperti ini:



Langkah seterunya ialah aku define object Order, dan class code dia adalah seperti ini. Code dalam class Order sebenarnya dibina secara incremental tapi payah nak tunjuk satu-satu, so aku show complete class Order.



Line 5 , menunjukkan Order mengandungi OrderLine dan object OrderLine nie ialah child object bagi Order. Line 52, ialah complete OrderLine, dan lihatlah berapa simple class tersebut.

Line 11 dan 12 pula, kita perlu registerkan event handler yang akan execute apabila kita replay balik semula event2 tersebut.Ok buat masa nie, kita tingglkan sekejap class Order nie.

Next, aku perlu define pula apa Command yang perlu dibuat untuk melakukan Order bagi Customer. So disini aku define Command - MakeNewOrderCommand



Code yang ini pun cukup straight forward, cuma aku define dictionar collection ialah bagi aku combinekan selection product dan juga berapa quantity.

Seterusnya ialah dengan define Role, apa Role yang akan memainkan peranan dalam melakukan Order dan siapa AggregateRoot yang akan menjadi RolePlayer?

Aku memilih Order object sebagai AggregateRoot dan juga menjadi RolePlayer untuk Role MakeNewOrderRole.



Ok jom kena tengok apa yang menarik didalam Role ini. Line 5, aku perlu mapkan apa command yang akan digunakan dalam Role ini.
Beri perhatian pada Line 7.Pada Line 7 ini, aku akan load AggregateRoot Customer hanya dengan Id, apa yang berlaku dibelakang scene ialah, vaccine framework akan baca setiap event dalam eventsnapshot source untuk aggregateroot customer dan akan replay event-event tersebut.



Okay lihat semula pada code Customer, sebelum ini kita dah registerkan Customer tersebut untuk terima 2 jenis event iaitu event NewCustomerCreatedEvent dan CashBalanceDecreasedEvent. Line 25, OnNewCustomerCreated ini lah vaccine framework akan trigger semula apabila direplay jika ada event NewCustomerCreatedEvent, dari situ kita dapat lihat bagaimana sesuatu AggregateRoot object dibina state2 object tersebut.

Ambil masa dan kaji macam maner interaction between object berlaku didalam Role dan bagaimana juga Role ini nanti boleh dishare dengan AggregateRoot object yang lain sebagai RolePalyer. Kalau sekarang nie RolePlayer ialah Order, ada kemungkinan process Order ini tetapi aku nak menggunkan keatas AggregateRoot object yang lain seperti Sale etc? Cuma sekarang nie mengambil konsep "YAGNI", kita hanya concentrate pada objective yang hendak dicapai, jika ada keperluan untuk dishare pada masa tu kita akan buat minor refactor.

Line 14 kita akan replay event untuk Product pula, process sama macam yang diterangkan, manakala Line 22,23,24 ketiga3 AggregateRoot akan memainkan peranan untuk execute method2 bagi menjayakan hasrat Role itu tadi.

Okay Line 23, customer.DecreaseCashBalance(totalAmount), singkap balik code dalam Customer dimana method DecreaseCashBalance dan lihat apa yang berlaku.


public void DecreaseCashBalance(decimal totalAmount)
{
if (cashBalance >= totalAmount)
{
cashBalance -= totalAmount;
var e = new CashBalanceDecreasedEvent { CashBalance = cashBalance };
Apply(e)
.UpdateReport(r => r.cashBalance = cashBalance);
}
else
{
throw new Exception("Insufficent amount to deduct");
}
}



Okay yang ini pula ialah code di client


private ActionResult MakeAnOrderComplete(CustomerOrderViewModel model)
{
try
{
var cmd = new MakeNewOrderCommand { CustomerId = new Guid(Request.Params["CustomerId"]) };
foreach (var item in model.OrderItems)
{
cmd.Quantities.Add(item.ProductId, item.Quantity);
}

using (var s = UnitOfWork)
{
var ctx = new ContextHandler(repo);
ctx.Bind(cmd)
.Execute();
s.Commit();
}

return MakeAnOrder();
}
catch(Exception err)
{
throw err;
}
}



Ada beberapa, part yang aku belum sentuh, insyAllah dalam n3 yang lain, n3 nie pun dah agak panjang.

https://github.com/ryzam/VaccineWeb-Preview - Code

0 comments: