﻿
{"id":26419,"date":"2023-08-22T00:06:02","date_gmt":"2023-08-22T00:06:02","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=26419"},"modified":"2023-08-22T00:24:40","modified_gmt":"2023-08-22T00:24:40","slug":"loosely-coupled-sistemler-olusturmak-icin-domain-eventler-nasil-kullanilir","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/loosely-coupled-sistemler-olusturmak-icin-domain-eventler-nasil-kullanilir\/","title":{"rendered":"Loosely Coupled Sistemler Olu\u015fturmak \u0130\u00e7in Domain Event&#8217;ler Nas\u0131l Kullan\u0131l\u0131r?"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu yaz\u0131m\u0131zda, g\u00fcn\u00fcm\u00fczde bir\u00e7ok modern yaz\u0131l\u0131m tasar\u0131m\u0131 ve mimarisi taraf\u0131ndan tercih edilmekte olan <em>Domain Event<\/em>&#8216;ler e\u015fli\u011finde loosely coupled(gev\u015fek ba\u011fl\u0131) sistemler olu\u015fturma yakla\u015f\u0131m\u0131 \u00fczerine biraz hasbihalde bulunal\u0131m istiyorum. Bu s\u00fcre\u00e7te domain event&#8217;ler ile integration event&#8217;lerden bahsedecek ve ikisi aras\u0131ndaki temel farklar\u0131n neler oldu\u011funu de\u011ferlendirecek ve biryandan da domain event&#8217;lerin nas\u0131l uyguland\u0131\u011f\u0131na ve \u00f6zellikle EF Core gibi bir framework ile nas\u0131l i\u015flendi\u011fine ve MediatR gibi k\u00fct\u00fcphaneyle de nas\u0131l handle edildi\u011fine pratiksel olarak de\u011finiyor olaca\u011f\u0131z. O halde buyrun ba\u015flayal\u0131m&#8230;<\/p>\n<p>Bir yaz\u0131l\u0131m sisteminde birbirinden farkl\u0131 bile\u015fenler\/servisler\/yap\u0131lar birbirlerine ne kadar s\u0131k\u0131 ba\u011f\u0131ml\u0131 ise o sistemde ihtiya\u00e7 dahilinde olan de\u011fi\u015fikliklere kar\u015f\u0131n olas\u0131 diren\u00e7lerin bir o kadar y\u00fcksek ihtimal oldu\u011funu s\u00f6yleyebiliriz. Bu mant\u0131kla bu bile\u015fenleri m\u00fcmk\u00fcn mertebe loosely coupling(gev\u015fek ba\u011fl\u0131) olacak \u015fekilde tasarlarsak e\u011fer sistemdeki herhangi bir de\u011fi\u015fiklik durumunda di\u011fer k\u0131s\u0131mlar b\u00fcy\u00fck sorunlara yol a\u00e7mayacak, bahsi konu olan de\u011fi\u015fikli\u011fe kar\u015f\u0131 diren\u00e7 olduk\u00e7a zay\u0131f olacakt\u0131r.<\/p>\n<p>\u0130\u015fte, bizler birbirleriyle gev\u015fek ba\u011fl\u0131 bile\u015fenler olu\u015fturmak istiyorsak e\u011fer Domain-Driven Design(DDD) felsefesinin taktiksel bir deseni olan domain event&#8217;lerden istifade edebiliriz.<\/p>\n<p>Domain event&#8217;ler sayesinde sistem bile\u015fenleri aras\u0131ndaki <u>s\u0131k\u0131 ba\u011flant\u0131lar\u0131 gev\u015fetebilir<\/u> ve b\u00f6ylece bir bile\u015fende meydana gelen\/gelecek olan de\u011fi\u015fim(ler) neticesinde di\u011fer bile\u015fenlerin do\u011frudan etkilenmesinin b\u00fcy\u00fck \u00f6l\u00e7\u00fcde \u00f6n\u00fcne ge\u00e7ebiliriz. B\u00f6ylece var olan \u00f6zellikleri modifiye etmenin d\u0131\u015f\u0131nda, sisteme yeni \u00f6zellikleri ekleme s\u00fcrecinde de <u>esneklik<\/u>ler kazand\u0131r\u0131labilmetkedir.<\/p>\n<p>Bile\u015fenler aras\u0131ndaki gev\u015fek ba\u011fl\u0131l\u0131\u011f\u0131n bir di\u011fer getirisi, bile\u015fenlerin <u>daha iyi bir \u015fekilde mod\u00fcler<\/u> olmas\u0131n\u0131 ve b\u00f6ylece bir bile\u015fenin, di\u011fer bile\u015fenlerin nas\u0131l tepki vereceklerine dair bilgi edinmek zorunda olmama gibi bir \u00f6zg\u00fcrl\u00fc\u011fe sahip olmas\u0131n\u0131 sa\u011flamaktad\u0131r. Bu durum da sistemdeki ba\u011f\u0131ms\u0131zl\u0131k d\u00fczeyini artt\u0131racak ve \u00f6zellikle <u>da\u011f\u0131t\u0131k mod\u00fclerli\u011fe uygun<\/u> bir nitelik arz edecektir.<\/p>\n<p>T\u00fcm bunlar\u0131n d\u0131\u015f\u0131nda domain event&#8217;ler, olaylar\u0131n g\u00f6nderildi\u011fi anda i\u015flenebilece\u011fi gibi hedef bile\u015fenin i\u015f yo\u011funlu\u011funa yahut durumuna uygun olacak \u015fekilde de belirli bir zamanlamada ele al\u0131nabilmekte ve b\u00f6ylece <u>zamanlama ve uygulama ba\u011f\u0131ms\u0131zl\u0131\u011f\u0131<\/u> a\u00e7\u0131s\u0131ndan uyum sa\u011flayabilmektedirler.<\/p>\n<p>\u015eimdi gelin t\u00fcm bu alt\u0131n\u0131 \u00e7izdi\u011fimiz prensipleri uygulamada ger\u00e7ekle\u015ftirebilmemizi sa\u011flayan domain event&#8217;lerin tam teferruatl\u0131 bir tan\u0131m\u0131n\u0131 ger\u00e7ekle\u015ftirerek i\u00e7eri\u011fimizin seyrine devam edelim.<\/p>\n<h3>Domain Events Nedir?<\/h3>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/Loosely-Coupled-Sistemler-Olusturmak-Icin-Domain-Eventler-Nasil-Kullanilir.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/Loosely-Coupled-Sistemler-Olusturmak-Icin-Domain-Eventler-Nasil-Kullanilir.png\" alt=\"Loosely Coupled Sistemler Olu\u015fturmak \u0130\u00e7in Domain Event&#039;ler Nas\u0131l Kullan\u0131l\u0131r\" width=\"713\" height=\"350\" class=\"aligncenter size-full wp-image-26422\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/Loosely-Coupled-Sistemler-Olusturmak-Icin-Domain-Eventler-Nasil-Kullanilir.png 713w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/07\/Loosely-Coupled-Sistemler-Olusturmak-Icin-Domain-Eventler-Nasil-Kullanilir-300x147.png 300w\" sizes=\"auto, (max-width: 713px) 100vw, 713px\" \/><\/a>Domain Event, bir yaz\u0131l\u0131m sisteminde ger\u00e7ekle\u015fen \u00f6nemli olaylar\u0131 temsil eden ve di\u011fer bile\u015fenlerle ileti\u015fimi sa\u011flayan bir kavramd\u0131r. Yukar\u0131daki sat\u0131rlarda da bahsedildi\u011fi gibi Domain-Driven Design(DDD) yakla\u015f\u0131m\u0131n\u0131n bir par\u00e7as\u0131d\u0131r ve mimaride loosely coupling&#8217;i te\u015fvik etmek i\u00e7in kullan\u0131l\u0131r.<\/p>\n<p>Domain event&#8217;i, sistemdeki \u00f6nemli bir i\u015flemin ger\u00e7ekle\u015fmesi neticesinde, etki(fact) olarak nitelendirebilece\u011fimiz anahtar noktalar olarak d\u00fc\u015f\u00fcnebiliriz. Misal olarak; bir e-ticaret uygulamas\u0131nda bir sipari\u015fin tamamlanmas\u0131 neticesinde &#8216;OrderCompleted&#8217; gibi bir domain event olu\u015fturulabilir ve b\u00f6ylece bu event sayesinde sistemin farkl\u0131 katmanlar\u0131na sipari\u015fin tamamland\u0131\u011f\u0131na dair bilgi g\u00f6ndererek ileti\u015fim sa\u011flanabilir. Tabi bu ileti\u015fimin kurulabilmesi ve di\u011fer bile\u015fenler taraf\u0131ndan ger\u00e7ekle\u015fen olaya kar\u015f\u0131l\u0131k uygun tepkinin verilebilmesi i\u00e7in yay\u0131nlanm\u0131\u015f olan domain event&#8217;e di\u011fer bile\u015fenler taraf\u0131ndan abone olunmas\u0131 gerekmektedir.<\/p>\n<p>Domain event&#8217;ler, ayr\u0131ca sistemde asenkron i\u015flemleri destelemek i\u00e7in de kullan\u0131labilmektedirler. Buna da bir \u00f6rnek vermemiz gerekirse e\u011fer; sipari\u015f tamamland\u0131ktan sonra arka planda m\u00fc\u015fteriye bir te\u015fekk\u00fcr maili g\u00f6ndermek isteyebiliriz. Bunun i\u00e7in asenkron bir tutum sergilememizi sa\u011flayan domain event&#8217;lerden yine istifade edebiliriz.<\/p>\n<blockquote><p><em>Bir olay\/event, ge\u00e7mi\u015fte olmu\u015f bir \u015feyi\/olay\u0131 ifade eder. O y\u00fczden domain event&#8217;lere s\u00fcrekli ge\u00e7mi\u015f bir isim verilmelidir!<\/em><\/p><\/blockquote>\n<h3>Integration Events Nedir?<\/h3>\n<p>Integration event ise distributed sistemlerdeki farkl\u0131 bile\u015fenlerin ve hizmetlerin ileti\u015fimini kolayla\u015ft\u0131rmak i\u00e7in kullan\u0131lan bir kavramd\u0131r. Genellikle microservice mimarisinde, servisler aras\u0131 etkile\u015fimi ve ileti\u015fimi kurgulamak i\u00e7in kullan\u0131lmaktad\u0131rlar. Yani integration event i\u00e7in domain event&#8217;in da\u011f\u0131t\u0131k mimarideki muadilidir diyebiliriz.<\/p>\n<p>Integration event&#8217;lerin temel \u00f6zellikleri \u015funlard\u0131r;<\/p>\n<ul>\n<li><strong><em>Asenkron \u0130leti\u015fim<\/em><\/strong><br \/>\nIntegration event&#8217;ler, yap\u0131lar\u0131 gere\u011fi asenkron bir davran\u0131\u015f sergilerler. Bir servis taraf\u0131ndan yay\u0131nlanm\u0131\u015f olan integration event, di\u011fer servisler taraf\u0131ndan al\u0131nana kadar o servis beklemek zorunda kalmamaktad\u0131r. Haliyle bu durumda asenkron bir s\u00fcre\u00e7 oldu\u011fu g\u00f6zlemlenmektedir. B\u00f6ylece, servislerin daha h\u0131zl\u0131 ve verimli bir \u015fekilde \u00e7al\u0131\u015fmas\u0131na ve aralar\u0131nda ileti\u015fim kurmas\u0131na olanak tan\u0131nmaktad\u0131r.\n<\/li>\n<li><strong><em>Ba\u011f\u0131ms\u0131zl\u0131k<\/em><\/strong><br \/>\nIntegration event&#8217;ler, di\u011fer bile\u015fenlerin veya servislerin i\u00e7 yap\u0131s\u0131n\u0131 bilmek zorunda de\u011fildirler. Yay\u0131nlanan event&#8217;ler, hedef servislerin ihtiyac\u0131na uygun \u015fekilde i\u015flenebilirler.\n<\/li>\n<li><strong><em>Entegrasyon Noktas\u0131<\/em><\/strong><br \/>\nIntegration event&#8217;ler, farkl\u0131 bile\u015fenlerin ve hizmetlerin birbirleriyle ileti\u015fim kurmas\u0131n\u0131 sa\u011flayan bir entegrasyon noktas\u0131d\u0131r ve bu event&#8217;ler sayesinde sistemdeki bile\u015fenlerin ba\u011f\u0131ms\u0131z olarak geli\u015ftirilmesi ve \u00f6l\u00e7eklendirilmesi kolayla\u015fmaktad\u0131r.\n<\/li>\n<li><strong><em>Entegrasyon Senaryolar\u0131<\/em><\/strong><br \/>\nIntegration event&#8217;ler, farkl\u0131 sistemler aras\u0131nda entegrasyon senaryolar\u0131n\u0131 kolayla\u015ft\u0131r\u0131r ve bir sistemdeki de\u011fi\u015fikli\u011fi, di\u011fer sistemleri do\u011frudan etkilemeden haberle\u015fme yoluyla bildirebilir.\n<\/li>\n<\/ul>\n<h3>Domain Event ile Integration Event Aras\u0131ndaki Farklar Nelerdir?<\/h3>\n<p>Domain event ile integration event anlamsal olarak birebir ayn\u0131yken, ama\u00e7sal olarak ise tamamen farkl\u0131 vizyonlara sahip kavramlard\u0131r.<\/p>\n<p>Evet, anlamsal olarak ayn\u0131d\u0131rlar&#8230; \u00c7\u00fcnk\u00fc, her ikisi de ge\u00e7mi\u015fte meydana gelen bir olay\u0131 temsil etmektedirler ve biryandan da olay tabanl\u0131 ileti\u015fim yakla\u015f\u0131m\u0131n\u0131n bir \u00fcr\u00fcn\u00fcd\u00fcrler.<\/p>\n<p>Ama\u00e7sal a\u00e7\u0131dan ise farkl\u0131l\u0131k arz ederler. Domain event&#8217;ler; bir yaz\u0131l\u0131m sisteminin i\u00e7indeki bile\u015fenler aras\u0131ndaki ileti\u015fimi kolayla\u015ft\u0131rmak i\u00e7in kullan\u0131l\u0131rken, integration event&#8217;ler ise farkl\u0131 sistemler veya servisler aras\u0131ndaki ileti\u015fimi kolayla\u015ft\u0131rmak i\u00e7in kullan\u0131l\u0131rlar. Yani domain event&#8217;ler ayn\u0131 yaz\u0131l\u0131m sistemi i\u00e7erisindeki bile\u015fenler aras\u0131nda in-memory \u00fczerinden senkron veya asenkron i\u015flev g\u00f6r\u00fcrken, integration event&#8217;ler ise genellikle farkl\u0131 sistemler aras\u0131nda message broker&#8217;lar vas\u0131tas\u0131yla asenkron varl\u0131k g\u00f6sterirler.<\/p>\n<p>Ayr\u0131ca domain event&#8217;ler, genelikle bir bile\u015fen taraf\u0131ndan \u00fcretilir ve yay\u0131nlan\u0131r. Di\u011fer bile\u015fenler ise bu olaylara abone olarak, dinleme i\u015flevini y\u00fcr\u00fct\u00fcrler. Integration event&#8217;ler ise daha geni\u015f bir ortamda ileti\u015fimi sa\u011flad\u0131\u011f\u0131ndan, genellikle bir message broker arac\u0131l\u0131\u011f\u0131yla y\u00f6netilir. Bir servis taraf\u0131ndan olay yay\u0131nland\u0131\u011f\u0131nda, bu message broker&#8217;a g\u00f6nderilir ve di\u011fer bile\u015fenler bu olaylar\u0131 oradan takip ederek b\u00fct\u00fcnsel i\u015flevsellik ve ileti\u015fim sa\u011flanm\u0131\u015f olur.<\/p>\n<h3>Domain Events Nas\u0131l Olu\u015fturulur ve Uygulan\u0131r?<\/h3>\n<p>\u015eimdi i\u00e7eri\u011fimizi esas konu olan domain event&#8217;lere odakl\u0131 bir \u015fekilde seyretmeye devam edelim ve domain event&#8217;leri tasarlama detaylar\u0131ndan bahsederken biryandan da nas\u0131l uygulanabilece\u011fini pratiksel olarak inceleyelim.<\/p>\n<p>.NET&#8217;te domain event&#8217;leri uygulamak i\u00e7in \u015fuana kadar akl\u0131ma gelen a\u015fa\u011f\u0131daki d\u00f6rt farkl\u0131 y\u00f6ntemden istifade edebiliriz;<\/p>\n<ul>\n<li><strong style=\"color:green;\"><em>Basit C# Delegate Kullanarak Domain Event Uygulama<\/em><\/strong><br \/>\nC#&#8217;ta ki <a href=\"https:\/\/www.gencayyildiz.com\/blog\/cta-delegatetemsilci-ve-eventolay-kullanimi\/\" rel=\"noopener\" target=\"_blank\">delegate<\/a>&#8216;leri, domain event&#8217;leri basit bir \u015fekilde uygulamak i\u00e7in kullanabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Order\r\n    {\r\n        \/\/Domain Event Delegate\r\n        public delegate void OrderCompletedEventHandler();\r\n\r\n        \/\/Domain Event\r\n        public event OrderCompletedEventHandler OrderCompleted;\r\n\r\n        \/\/Event Tetikleme Metodu\r\n        public virtual void OnOrderCompleted()\r\n        {\r\n            OrderCompleted();\r\n        }\r\n\r\n        \/\/Sipari\u015f Tamamland\u0131\u011f\u0131nda Bu Metot \u00c7a\u011fr\u0131labilir\r\n        public void CompleteOrder()\r\n        {\r\n            \/\/Sipari\u015f Tamamland\u0131...\r\n            \/\/...\r\n\r\n            \/\/Domain Event'i Tetikle\r\n            OnOrderCompleted();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011funu incelersek e\u011fer; <strong><em>4.<\/em><\/strong> sat\u0131rda domain event&#8217;in metodunu temsil edecek olan bir delegate tan\u0131mlanmakta ve <strong><em>7.<\/em><\/strong> sat\u0131rda ise bu delegate&#8217;i kullanan bir domain event olu\u015fturulmaktad\u0131r. Bu event ne zaman tetiklenir, i\u015fte o zaman bu event&#8217;i dinleyen di\u011fer bile\u015fenler yahut s\u0131n\u0131flar uyar\u0131lacak ve kendilerinde bu event&#8217;i i\u015flemek \u00fczere tan\u0131mlanm\u0131\u015f olan metotlar \u00e7al\u0131\u015ft\u0131r\u0131lacakt\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class OrdersController : ControllerBase\r\n    {\r\n        &#x5B;HttpPost(&quot;create-order-delegate&quot;)]\r\n        public IActionResult CreateOrderDelegate()\r\n        {\r\n            Domain_Events.Delegate.Order order = new();\r\n            order.OrderCompleted += () =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Sipari\u015f tamamland\u0131\u011f\u0131nda buradaki kodlar tetiklenecektir!&quot;);\r\n            };\r\n\r\n            order.CompleteOrder();\r\n\r\n            return Ok();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Burada s\u0131rf olay\u0131 sim\u00fcle edebilmek i\u00e7in bir controller \u00fczerinden \u00f6rneklendirme yap\u0131lm\u0131\u015ft\u0131r.\n<\/li>\n<li><strong style=\"color:green;\"><em>EventHandler Kullanarak Domain Event Uygulama<\/em><\/strong><br \/>\n.NET Framework&#8217;\u00fc taraf\u0131ndan sa\u011flanan ve olay tabanl\u0131 bir model olan <code>EventHandler<\/code>&#8216;\u0131 da kullanarak domain event&#8217;leri uygulayabiliriz. \u015e\u00f6yle ki;<\/p>\n<p>\u00d6ncelikle, domain event&#8217;inin ta\u015f\u0131yaca\u011f\u0131 verileri temsil edecek olan bir olay s\u0131n\u0131f\u0131 olu\u015fturuyoruz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class OrderEventArgs : EventArgs\r\n    {\r\n        public OrderEventArgs(Order order)\r\n        {\r\n            Order = order;\r\n        }\r\n\r\n        public Order Order { get; }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ard\u0131ndan event&#8217;i temsil edecek olan bir delegate tan\u0131mlamas\u0131na ihtiyac\u0131m\u0131z olacak. Bunu da bir \u00f6nceki ad\u0131mda yapt\u0131\u011f\u0131m\u0131z gibi &#8216;Order&#8217; modeli i\u00e7erisinde a\u015fa\u011f\u0131daki gibi <code>EventHandler<\/code> delegate t\u00fcr\u00fcnden \u015fekillendirebiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Order\r\n    {\r\n        \/\/Domain Event\r\n        public event EventHandler&lt;OrderEventArgs&gt; OrderCompleted;\r\n\r\n        \/\/Event Tetikleme Metodu\r\n        public virtual void OnOrderCompleted(OrderEventArgs e)\r\n        {\r\n            OrderCompleted(this, e);\r\n        }\r\n\r\n        \/\/Sipari\u015f Tamamland\u0131\u011f\u0131nda Bu Metot \u00c7a\u011fr\u0131labilir\r\n        public void CompleteOrder()\r\n        {\r\n            \/\/Sipari\u015f Tamamland\u0131...\r\n            \/\/...\r\n\r\n            \/\/Domain Event'i Tetikleme\r\n            OnOrderCompleted(new OrderEventArgs(this));\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere <strong><em>4.<\/em><\/strong> sat\u0131rda <code>EventHandler<\/code> kullan\u0131larak &#8216;OrderEventArgs&#8217;a \u00f6zel bir event olu\u015fturulmaktad\u0131r. Esas\u0131nda buradan da anla\u015f\u0131l\u0131yor ki, <code>EventHandler<\/code>&#8216;da \u00f6z\u00fcnde genel bir delegate t\u00fcr\u00fcd\u00fcr.<\/p>\n<p>Ve bu <code>EventHandler<\/code> ile yap\u0131lan domain event \u00e7al\u0131\u015fmas\u0131n\u0131 da a\u015fa\u011f\u0131daki gibi kullanabilirsiniz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class OrdersController : ControllerBase\r\n    {\r\n        &#x5B;HttpPost(&quot;create-order-eventhandlers&quot;)]\r\n        public IActionResult CreateOrderEventHandlers()\r\n        {\r\n            Domain_Events.EventHandlers.Order order = new();\r\n            order.OrderCompleted += (sender, e) =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Sipari\u015f tamamland\u0131\u011f\u0131nda buradaki kodlar tetiklenecektir!&quot;);\r\n            };\r\n\r\n            order.CompleteOrder();\r\n\r\n            return Ok();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong style=\"color:green;\"><em>Mediator Tasar\u0131m Desenini Kullanarak Domain Event Uygulama<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-mediator-design-patternmediator-tasarim-deseni\/\" rel=\"noopener\" target=\"_blank\">Mediator<\/a> tasar\u0131m desenini uygulayarakta domain event&#8217;leri etkin bir \u015fekilde y\u00f6netebiliriz.<\/p>\n<p>\u00d6ncelikle domain event&#8217;i temsil edecek bir interface olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    \/\/Domain Event Interface\r\n    public interface IOrderCompletedEvent\r\n    {\r\n        void OrderCompleted(Order order);\r\n    }\r\n<\/pre>\n<\/div>\n<p>Sonras\u0131nda ise bu domain event&#8217;i y\u00f6netecek ve bunu dinleyen di\u011fer bile\u015fenlere y\u00f6nlendirecek olan Mediator s\u0131n\u0131f\u0131n\u0131 olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    \/\/Mediator S\u0131n\u0131f\u0131\r\n    public class OrderMediator : IOrderCompletedEvent\r\n    {\r\n        readonly List&lt;IOrderCompletedEvent&gt; _eventListener = new();\r\n        public void Register(IOrderCompletedEvent @event)\r\n        {\r\n            _eventListener.Add(@event);\r\n        }\r\n\r\n        public void OrderCompleted(Order order)\r\n        {\r\n            _eventListener.ForEach(l =&gt; l.OrderCompleted(order));\r\n            \/\/Sipari\u015f Tamamland\u0131...\r\n            \/\/...\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Art\u0131k uygun bile\u015fenleri olu\u015fturdu\u011fumuza g\u00f6re Mediator ile ili\u015fkilendirilecek servisleri olu\u015fturabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class SmsService : IOrderCompletedEvent\r\n    {\r\n        public void OrderCompleted(Order order)\r\n        {\r\n            Console.WriteLine(&quot;Sms g\u00f6nderildi.&quot;);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class EmailService : IOrderCompletedEvent\r\n    {\r\n        public void OrderCompleted(Order order)\r\n        {\r\n            Console.WriteLine(&quot;Email g\u00f6nderildi.&quot;);\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ve art\u0131k Mediator pattern ile tasarlanan bu domain event \u00e7al\u0131\u015fmas\u0131n\u0131 da a\u015fa\u011f\u0131daki gibi kullanabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class OrdersController : ControllerBase\r\n    {\r\n        &#x5B;HttpPost(&quot;create-order-mediator-design-pattern&quot;)]\r\n        public IActionResult CreateOrderMediatorDesignPattern()\r\n        {\r\n            Domain_Events.MediatorDesignPattern.Order order = new();\r\n            OrderMediator mediator = new();\r\n            EmailService emailService = new();\r\n            SmsService smsService = new();\r\n\r\n            mediator.Register(emailService);\r\n            mediator.Register(smsService);\r\n\r\n            mediator.OrderCompleted(order);\r\n\r\n            return Ok();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong style=\"color:green;\"><em>MediatR K\u00fct\u00fcphanesi E\u015fli\u011finde Domain Event Uygulama<\/em><\/strong><br \/>\nYukar\u0131daki t\u00fcm y\u00f6ntemlerin d\u0131\u015f\u0131nda, domain event&#8217;leri olu\u015fturmak ve uygulamak i\u00e7in esnek ve okunakl\u0131 bir yakla\u015f\u0131m sa\u011flayan, y\u00fcksek seviyeli ve olay tabanl\u0131 ileti\u015fim a\u00e7\u0131s\u0131ndan olduk\u00e7a kullan\u0131\u015fl\u0131 olan MediatR k\u00fct\u00fcphanesinden istifade edilmesi elzemdir diyebiliriz. Evet, di\u011fer y\u00f6ntemlerde \u00e7\u00f6z\u00fcm getirecektirler ama bizler bu i\u00e7eri\u011fimizde(ki bu konuyla e\u015f de\u011fer kategoride olabilecek di\u011fer i\u00e7eriklerde de) domain event&#8217;lerin tasar\u0131m\u0131n\u0131 ve uygulanmas\u0131n\u0131 MediatR k\u00fct\u00fcphanesi ile ger\u00e7ekle\u015ftiriyor olaca\u011f\u0131z.<\/p>\n<p>MediatR k\u00fct\u00fcphanesi ile domain event olu\u015fturabilmek i\u00e7in \u00f6ncelikle ilgili projeye <a href=\"https:\/\/www.nuget.org\/packages\/MediatR\" rel=\"noopener\" target=\"_blank\">MediatR<\/a> k\u00fct\u00fcphanesini y\u00fckleyelim.<\/p>\n<p>Ard\u0131ndan domain event&#8217;i temsil edecek bir interface olu\u015ftural\u0131m ve bunu <code>INotification<\/code> interface&#8217;inden t\u00fcretelim.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface IDomainEvent : INotification\r\n    {\r\n\r\n    }\r\n<\/pre>\n<\/div>\n<p>Bu interface, bir veya daha fazla handler s\u0131n\u0131f\u0131na domain event yay\u0131nlayabilmek i\u00e7in MediatR&#8217;\u0131n publish-subscribe deste\u011fini kullanabilece\u011fimiz bir abstraction g\u00f6revi g\u00f6recektir.<\/p>\n<p>Bu tan\u0131mlamadan sonra <code>IDomainEvent<\/code> interface&#8217;ini implement eden concrete bir domain event olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class OrderCreatedEvent : IDomainEvent\r\n    {\r\n        public Guid OrderId { get; set; }\r\n        public List&lt;object&gt; OrderItems { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Devam\u0131nda ise bu event&#8217;i i\u015fleyecek olan bir &#8216;handler&#8217; s\u0131n\u0131f\u0131 olu\u015ftural\u0131m ve <code>INotificationHandler&lt;T&gt;<\/code> interface&#8217;inden implement edelim.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class OrderCreatedEventHandler : INotificationHandler&lt;OrderCreatedEvent&gt;\r\n    {\r\n        public Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)\r\n        {\r\n            \/\/Olay\u0131 i\u015fleyecek kodlar...\r\n            Console.WriteLine($&quot;Yeni sipari\u015f verildi... {notification.OrderId}&quot;);\r\n            return Task.CompletedTask;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ve son olarak MediatR&#8217;\u0131n IoC Provider&#8217;a eklenmesini ve olu\u015fturdu\u011fumuz domain event&#8217;in uygulamada yap\u0131land\u0131r\u0131lmas\u0131n\u0131 sa\u011flayal\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\nbuilder.Services.AddMediatR(configuration =&gt; configuration.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<p>Art\u0131k ilgili event&#8217;i a\u015fa\u011f\u0131daki gibi tetikleyebiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class OrdersController : ControllerBase\r\n    {\r\n        readonly IMediator _mediator;\r\n        public OrdersController(IMediator mediator)\r\n        {\r\n            _mediator = mediator;\r\n        }\r\n\r\n        &#x5B;HttpPost(&quot;create-order-mediatr&quot;)]\r\n        public IActionResult CreateOrderMediatR()\r\n        {\r\n            OrderCreatedEvent orderCreatedEvent = new()\r\n            {\r\n                OrderId = Guid.NewGuid(),\r\n                OrderItems = new List&lt;object&gt; { &quot;A&quot;, &quot;B&quot;, &quot;C&quot; }\r\n            };\r\n            _mediator.Publish(orderCreatedEvent);\r\n            return Ok();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p><strong><em>Peki neden MediatR k\u00fct\u00fcphanesi e\u015fli\u011finde domain event&#8217;leri uygulamal\u0131y\u0131z?<\/em><\/strong> diye sorarsan\u0131z e\u011fer bunu birka\u00e7 maddeyle izah etmek isterim;<\/p>\n<ul>\n<li><strong><em>Y\u00fcksek Seviyeli ve Kolay Kullan\u0131m<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi, domain event&#8217;lerin ve olay tabanl\u0131 ileti\u015fimin daha y\u00fcksek seviyeli bir aray\u00fczle uygulanmas\u0131n\u0131 sa\u011flamakta ve b\u00f6ylece kodun y\u00f6netilebilirli\u011fiyle, okunakl\u0131l\u0131\u011f\u0131n\u0131 artt\u0131rmaktad\u0131r.\n<\/li>\n<li><strong><em>CQRS Entegrasyonu<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi, <a href=\"https:\/\/www.gencayyildiz.com\/blog\/cqrs-pattern-nedir-mediatr-kutuphanesi-ile-nasil-uygulanir\/\" rel=\"noopener\" target=\"_blank\">CQRS<\/a> desenini uygulamak i\u00e7in haz\u0131r bir yap\u0131 sunmaktad\u0131r.\n<\/li>\n<li><strong><em>Request\/Response Modeli<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi; bir olay\u0131n yay\u0131nlanmas\u0131n\u0131n yan\u0131 s\u0131ra, olay\u0131n ger\u00e7ekle\u015fti\u011fi bile\u015fenlerden bir yan\u0131t almak i\u00e7in request\/response modelini de destekler. Bu sayede olaylar\u0131n yan\u0131tlanmas\u0131 ve i\u015flem sonu\u00e7lar\u0131n\u0131n daha d\u00fczenli bir \u015fekilde ele al\u0131nmas\u0131 sa\u011flan\u0131r.\n<\/li>\n<li><strong><em>Farkl\u0131 Tipler \u0130\u00e7in Tek Bir Yerde Y\u00f6netim<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi, farkl\u0131 tipteki olaylar ve istekler i\u00e7in ayn\u0131 yap\u0131y\u0131 kullanmam\u0131za olanak tan\u0131r. B\u00f6ylece, uygulaman\u0131n farkl\u0131 k\u0131s\u0131mlar\u0131nda farkl\u0131 tiplerdeki olaylar\u0131 y\u00f6netmek i\u00e7in birden \u00e7ok yerde kod yazmak yerine, tek bir yerde t\u00fcm olaylar y\u00f6netilebilmektedir.\n<\/li>\n<li><strong><em>Test Edilebilirlik ve Gev\u015fek Ba\u011fl\u0131l\u0131k(Loose Coupling)<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi, uygulaman\u0131n bile\u015fenlerini gev\u015fek ba\u011fl\u0131 hale getirir. B\u00f6ylece test edilebilirli\u011fi art\u0131r\u0131r ve kodun bak\u0131m\u0131n\u0131 kolayla\u015ft\u0131r\u0131r.\n<\/li>\n<li><strong><em>Daha Zengin ve Olay Odakl\u0131 \u00d6zellikler<\/em><\/strong><br \/>\nMediatR k\u00fct\u00fcphanesi, olaylar\u0131 i\u015flemek i\u00e7in olduk\u00e7a zengin \u00f6zellikler ve yetenekler sunar. Misal olarak; istekleri filtreleme, consumer \u00f6nceliklendirme, olaylar\u0131 arabelle\u011fe alma vs. gibi yetenekleriyle domain event y\u00f6netimini daha esnek hale getirebilmektedir.\n<\/li>\n<\/ul>\n<p>Anlayaca\u011f\u0131n\u0131z MediatR k\u00fct\u00fcphanesi, domain event&#8217;ler a\u00e7\u0131s\u0131ndan daha y\u00fcksek seviyeli, mod\u00fcler ve esnek bir \u00e7\u00f6z\u00fcm sunmakla birlikte, projenin s\u00fcrd\u00fcr\u00fclebilirli\u011fini sa\u011flamaktad\u0131r.\n<\/li>\n<\/ul>\n<p><strong><em>Peki hoca! Domain event&#8217;ler nerede tetiklenmelidirler?<\/em><\/strong> \u015feklinde sorunuzu duyar gibiyim&#8230; Bu hakl\u0131 soruyu hemen cevapland\u0131rmaya \u00e7al\u0131\u015f\u0131rsak e\u011fer, domain event&#8217;ler genellikle domain modelinde ger\u00e7ekle\u015fen kimi \u00f6nemli olaylar \u00fczerinde tetiklenirler diyebiliriz. Bu olaylar, genellikle i\u015f mant\u0131\u011f\u0131n\u0131n bir sonucu olarak ortaya \u00e7\u0131kar ve uygulaman\u0131n farkl\u0131 par\u00e7alar\u0131 aras\u0131nda ileti\u015fimi sa\u011flamak i\u00e7in kullan\u0131l\u0131rlar. Ayr\u0131ca terminolojik olarak domain event&#8217;lerin tetiklenmesini <code style=\"color:purple;\"><strong>Raising<\/strong><\/code> kavram\u0131yla ifade etmeyi tercih ederiz. Yani bir sipari\u015f olu\u015fturuldu\u011funda &#8216;OrderCreatedEvent&#8217; event&#8217;ini tetiklemeyiz de, raise etmi\u015f oluruz&#8230; \ud83d\ude42 Ha tabi \u00e7ok isterseniz &#8216;tetikleme&#8217; terimini de kullanabilirsiniz&#8230;<\/p>\n<p>\u015eimdi domain event&#8217;lerin raising edilmesi i\u00e7in baz\u0131 yayg\u0131n noktalar\u0131 ele alal\u0131m;<\/p>\n<ul>\n<li><strong>Aggregate Root \u0130\u00e7inde<\/strong><br \/>\nE\u011fer CQRS yahut Event Sourcing gibi tasar\u0131m desenlerini kullan\u0131yorsan\u0131z, aggregate root&#8217;un i\u00e7inde domain event&#8217;leri raising edebilirsiniz. Aggregate root, bir veya daha fazla ili\u015fkili nesneyi gruplayan ve bu nesneler \u00fczerinden i\u015flemleri y\u00f6neten bir nesnedir. Misal olarak; &#8216;Product&#8217; aggregate root&#8217;u i\u00e7erisinde, bir \u00fcr\u00fcn olu\u015fturuldu\u011fu taktirde &#8216;ProductCreatedEvent&#8217;ini tetikleyebilirsiniz.\n<\/li>\n<li><strong>Servislerde<\/strong><br \/>\n\u0130\u015f mant\u0131\u011f\u0131n\u0131z\u0131n bir sonucu olarak domain event&#8217;lerin raising edilebilece\u011fi servisler olu\u015fturabilirsiniz. Bu servisler ile birden fazla domain nesnesi aras\u0131nda koordinasyon sa\u011flayabilir ve olaylar\u0131 tetikleyebilirsiniz.\n<\/li>\n<li><strong>Repository Metotlar\u0131 \u0130\u00e7inde<\/strong><br \/>\nVeritaban\u0131 i\u015flemleri s\u0131ras\u0131nda domain event&#8217;ler raising edilebilir. Misal olarak; bir product eklendi\u011finde yahut g\u00fcncellendi\u011finde durumu ifade edecek bir domain event ilgili repository metodu i\u00e7erisinde tetiklenebilir.\n<\/li>\n<li><strong>Business Layer&#8217;da<\/strong><br \/>\nYap\u0131lan operasyonlar neticesinde domain event&#8217;lerinizi raising etmeniz gerekebilir. Haliyle bunun i\u00e7in business layer&#8217;da uygun yerleri kullanabilirsiniz.\n<\/li>\n<li><strong>Entityler&#8217;de<\/strong><br \/>\nDomain event&#8217;ler, entity&#8217;ler i\u00e7inde de raise edilebilirler. Ancak bu durumun uygulaman\u0131n tasar\u0131m\u0131na ve gereksinimlerine ba\u011fl\u0131 olarak dikkatli bir \u015fekilde ele al\u0131nmas\u0131 gerekmektedir. Bunu direkt pratiksel olarak \u00f6rneklendirmekte fayda g\u00f6rmekteyim. \u0130lk olarak a\u015fa\u011f\u0131daki gibi base bir &#8216;Entity&#8217; class&#8217;\u0131 olu\u015fturarak ba\u015flayal\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public abstract class Entity\r\n    {\r\n        private readonly List&lt;IDomainEvent&gt; _domainEvents;\r\n        public Entity()\r\n            =&gt; _domainEvents = new();\r\n\r\n        public IReadOnlyList&lt;IDomainEvent&gt; GetDomainEvents()\r\n            =&gt; _domainEvents.ToList();\r\n\r\n        public void ClearDomainEvents()\r\n            =&gt; _domainEvents.Clear();\r\n\r\n        protected void RaiseDomainEvent(IDomainEvent domainEvent)\r\n            =&gt; _domainEvents.Add(domainEvent);\r\n    }\r\n<\/pre>\n<\/div>\n<p>Bu s\u0131n\u0131fta, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere entity i\u00e7erisinde raise edilecek olan domain event&#8217;ler <code>RaiseDomainEvent<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla tutulmaktad\u0131r.<\/p>\n<p>\u015eimdi de, bu s\u0131n\u0131ftan t\u00fcretilen esas entity s\u0131n\u0131flar\u0131m\u0131z\u0131 a\u015fa\u011f\u0131daki gibi tan\u0131mlayarak, domain event&#8217;leri olu\u015fturabiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Order : Entity\r\n    {\r\n        public Guid Id { get; set; }\r\n        public List&lt;object&gt; OrderItems { get; set; }\r\n        public void Complete()\r\n        {\r\n            RaiseDomainEvent(new OrderCreatedEvent()\r\n            {\r\n                OrderId = Id,\r\n                OrderItems = OrderItems\r\n            });\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere &#8216;Order&#8217; nesnesi ba\u015far\u0131yla \u00fcretildikten sonra &#8216;Complete&#8217; fonksiyonu tetiklendi\u011fi zaman bir &#8216;OrderCreatedEvent&#8217; olay\u0131 olu\u015fturulacak ve <code>RaiseDomainEvent<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla bu olay raise edilmek \u00fczere base&#8217;de ki(entity) koleksiyona eklenecektir.<\/p>\n<p>\u0130\u015fte bu \u015fekilde bir tasar\u0131m e\u015fli\u011finde, entity&#8217;lerimiz de, raise etmek i\u00e7in bir veya birden fazla domain event tan\u0131mlayabiliriz.<\/p>\n<p>\u015eimdi yapt\u0131\u011f\u0131m\u0131z bunca \u00e7al\u0131\u015fmay\u0131 kullanabilece\u011fimiz uygun bir senaryo d\u00fc\u015f\u00fcn\u00fcrsek e\u011fer, entity&#8217;de yap\u0131lan bu yap\u0131y\u0131 kullanabilece\u011fimiz en uygun yerlerden biri EF Core&#8217;un SaveChanges metodu olabilir gibi. \u015e\u00f6yle ki;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class ApplicationDbContext : DbContext\r\n    {\r\n        public DbSet&lt;Order&gt; Orders { get; set; }\r\n        readonly IMediator _mediator;\r\n        public ApplicationDbContext(DbContextOptions options, IMediator mediator) : base(options)\r\n        {\r\n            _mediator = mediator;\r\n        }\r\n\r\n        public override async Task&lt;int&gt; SaveChangesAsync(CancellationToken cancellationToken = default)\r\n        {\r\n            var result = await base.SaveChangesAsync(cancellationToken);\r\n\r\n            async Task PublishDomainEventsAsync()\r\n            {\r\n                var domainEvents = ChangeTracker\r\n                    .Entries&lt;Entity&gt;()\r\n                    .Select(entry =&gt; entry.Entity)\r\n                        .SelectMany(entity =&gt;\r\n                        {\r\n                            var domainEvents = entity.GetDomainEvents();\r\n                            entity.ClearDomainEvents();\r\n                            return domainEvents;\r\n                        })\r\n                    .ToList();\r\n\r\n                foreach (var domainEvent in domainEvents)\r\n                {\r\n                    await _mediator.Publish(domainEvent);\r\n                }\r\n            }\r\n\r\n            await PublishDomainEventsAsync();\r\n\r\n            return result;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131da tan\u0131mlanan <code>ApplicationDbContext<\/code> s\u0131n\u0131f i\u00e7eri\u011fine g\u00f6z atarsan\u0131z, <code>SaveChangesAsync<\/code> metodu override edilmekte ve i\u00e7erisinde <strong><em>12.<\/em><\/strong> sat\u0131rda oldu\u011fu gibi de\u011fi\u015fiklikler veritaban\u0131na yans\u0131t\u0131ld\u0131ktan sonra, local function olarak tan\u0131mlanm\u0131\u015f olan <code>PublishDomainEventsAsync<\/code> metodu \u00e7a\u011fr\u0131lmaktad\u0131r. Bu metot i\u00e7eri\u011finde, ChangeTracker \u00fczerinden i\u015flem yap\u0131lan nesnenin &#8216;GetDomainEvents&#8217; fonksiyonuyla domain event&#8217;leri elde edilmekte ve ard\u0131ndan MediatR k\u00fct\u00fcphanesiyle bu event&#8217;ler publish edilmektedir.\n<\/li>\n<\/ul>\n<p>Nihai olarak;<br \/>\nDomain event&#8217;ler e\u015fli\u011finde, uygulama b\u00fcnyesindeki bile\u015fenler aras\u0131nda loosely coupled(gev\u015fek ba\u011fl\u0131) davran\u0131\u015flar sergileyebilir ve domain logic&#8217;i asenkron s\u00fcre\u00e7lerdeki olas\u0131 yan etkilerden ar\u0131nd\u0131rarak \u00e7al\u0131\u015fmalar\u0131m\u0131z\u0131 rahatl\u0131kla ger\u00e7ekle\u015ftirebiliriz. Bu i\u00e7eri\u011fimizde bu durumlar\u0131 teorik olarak masaya yat\u0131rmaya \u00e7al\u0131\u015f\u0131p, pratiksel olarakta m\u00fcmk\u00fcn mertebe tecr\u00fcbe etmeye \u00e7al\u0131\u015fm\u0131\u015f bulunuyoruz.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek projeyi a\u015fa\u011f\u0131daki github adresinden edinebilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/Loosely_Coupled_Systems_Domain_Events_Examples\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/Loosely_Coupled_Systems_Domain_Events_Examples<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu yaz\u0131m\u0131zda, g\u00fcn\u00fcm\u00fczde bir\u00e7ok modern yaz\u0131l\u0131m tasar\u0131m\u0131 ve mimarisi taraf\u0131ndan tercih edilmekte olan Domain Event&#8216;ler e\u015fli\u011finde loosely coupled(gev\u015fek ba\u011fl\u0131) sistemler olu\u015fturma yakla\u015f\u0131m\u0131 \u00fczerine biraz hasbihalde bulunal\u0131m istiyorum. Bu s\u00fcre\u00e7te domain event&#8217;ler ile integration&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26422,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,3573],"tags":[4896,4898,4901,4897,4902,4903,4899,4900,943,4153,3575],"class_list":["post-26419","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-microservices","tag-domain-event","tag-domain-event-mediatr","tag-domain-event-nedir","tag-domain-events","tag-domain-events-nedir","tag-integration-event-nedir","tag-integration-events","tag-integration-events-nedir","tag-loosely-coupled","tag-mediatr","tag-microservice"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26419","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=26419"}],"version-history":[{"count":17,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26419\/revisions"}],"predecessor-version":[{"id":26441,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26419\/revisions\/26441"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26422"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=26419"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=26419"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=26419"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}