8 Comments

Pokušati ću opisati još jedan u nizu patterna za arhitekturu aplikacije, bilo web, desktop ili Silverlight, koji upotrebljavam već neko vrijeme. Pattern se pokazao jako korisnim, i to sa stajališta organizacije veće količine koda, enkapsulacije logike u zasebne, odvojive cjeline, time omogućivši i lakši unit testing. Svrha ovog patterna je i pojednostavljenje koda i uklanjanje bespotrebne apstrakcije upotrebom puno slojeva (hint: dali baš u svakoj aplikaciji treba biti layer sa Repository klasama, Service klasama sa (praznom) poslovnom logikom, i sl?).

U osnovi, radi se o starom i poznatom CQS patternu (Command Query Segragation), koji nalaže da se odvoji logika za upite (npr: dohvati sve proizvode iz kategorije), koja vraća podatke, od logike koja sadrži određeno procesiranje, i ne vraća podatke (npr: dodaj proizvod u košaricu za kupnju). Dodatnu popularnost ovaj pattern je dobio kroz upotrebu u CQRS arhitekturi, koji query/command priču diže na jedan viši, enterprise nivo, da bi se dotakli problemi (horizontalnog) skaliranja i race conditiona (više procesa se natječu za prvenstvo pristupa određenom resursu), dodajući odvojene izvore podataka za pisanje i čitanje, te asinkroni sistem zapisivanja i sinkronizacije. Dodatne informacije o CQRSu se mogu pronaći na blogu od Udi Dahana.

Primjer upotrebe ovog patterna možemo prikazati na jednostavnom primjeru web shopa, kroz upotrebu u dva scenarija:

1 Dohvat prozvoda zadane kategorije
2 Dodavanje odabranog proizvoda u košaricu za kupnju

Naravno, ovdje se radi o web aplikaciji, koja može i ne mora biti MVC.

[more]

Prvi scenarij možemo opisati generičkim interfaceom, koji potom upotrebljavamo za sve upite:

Interface IQuery<TParam, TResult> 
{ 
	TResult Execute(TParam args) 
}

ovime smo dobili enkapsulaciju logike upita u zasebnu klasu, koja nasljeđuje IQuery interface.

Drugi scenarij ne zahtjeva nikakvu povratnu vrijednost, osim eventualno bacanja Exceptiona, i opisuje se interfaceom:

Interface IHandle<T> where T:class 
{ 
	void Handle(T command); 
}

vrlo slična stvar kao i IQuery, samo bez povratne vrijednosti.

Cijelu upotrebu ovih interfaceova uvelike olakšava neki IoC/DI framework, jer on omogućava automatsko traženje konkretne implementacije određenog interfacea. Prije sam uvijek morao raditi vlastiti kod za pretraživanje klasa u assemblju, što je znalo imati skrivene bugove, a onda sam nabasao na korisnu funkciju unutar StructureMap frameworka, koji inače koristim za IoC/DI, i inicijalizacija izgleda ovako:

scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>)); 
scan.ConnectImplementationsToTypesClosing(typeof(IQuery<,>));   

upotreba unutar akcije/kontrolea u MVC aplikaciji izgleda ovako:

public HomeController(IQuery<CategoryInfo,ProductViewModel> productFromCategory, 
ICommandBus commandBus) 
{ 
	_productFromCategory = productFromCategory; 
	_commandBus = commandBus; 
} 

public ActionResult CategoryProducts(int categoryId) 
{ 
	var products = _productFromCategory.Execute(new CategoryInfo(categoryId)); 
	return View(products);
} 

public ActionResult Add(int ProductID)
{
	try { 
		_commandBus.Send(new AddProductToBasketCommand(ProductID));
	}
	catch(Exception e)
	{
		// handle exception ...
	}
	return RedirectToAction("Index");
} 

Ovdje se može vidjeti upotreba CommandBus klase, odnosno ICommandBus interface-a, koji se samo “factory” za pozivanje IHandle<T> objekta, a nekako bolje opisuje namjeru i svrhu. Nije na odmet spomenuti da dozvoljava jednostavniji rast aplikacije, dodavanje novih funkcionalnosti se svodi na kreiranje novih IHandle klasa, upotreba iste logike je jednostavnija. Kod timskog rada, programer BLL sloja može u dogovoru sa Front End (FE) programerom definirati parametre za izvršavanje određenog procesa, poslovne logike, upita, i omogućiti FE programeru da samo poziva objekte prema interfaceu, ne brinući se gdje je to i kako implementirano!

Sample aplikaciju, sa primjerom ovih interface-ova, konfiguracije StructureMap-a i MVCa, možete skinuti ovdje:

https://bitbucket.org/hhrvoje/cqssample

Comments

Comment by SEO Optimierung

Hello friend Appreciation for spreading this article along with us. Typically i wouldn\'t reply to Sites. However just like it. If only additional posts and written content online would be as much as handy as well as useful when compared with this. Excellent publish, many thanks Best wishes.

Comment by Social Media Houston

Many business owners do not understand the necessity of Social Media and how it can help their business. Thanks for helping to get the word out.

Comment by muscle maximizer

I personally discover something additional difficult on different weblogs every day. It'll always become inspiring to read subject matter from similar authors and exercise something from their store. I’d choose to employ some of your content on my site in case you don’t mind. Needless to say I’ll supply you with a website link on my websites. Thanks for posting.

Comment by watch despicable me online free

Thank you, I have recently been searching for info approximately this topic for a while and yours is the best I've found out till now. But, what in regards to the bottom line? Are you certain in regards to the source?

Comment by watch movies online

Thanks, I have recently been looking for information about this topic for a long time and yours is the greatest I have found out so far. But, what in regards to the conclusion? Are you positive concerning the supply?

Comment by watch twilight new moon

of course like your web site but you have to check the spelling on several of your posts. A number of them are rife with spelling problems and I in finding it very bothersome to inform the truth however I will definitely come back again.

Comment by watch inception online

Some genuinely nice and utilitarian info on this website, too I think the pattern contains wonderful features.

Comment by watch the last airbender online

I got what you intend, thankyou for putting up.Woh I am delighted to find this website through google. "Success is dependent on effort." by Sophocles.