﻿
{"id":27190,"date":"2024-10-02T05:06:24","date_gmt":"2024-10-02T05:06:24","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=27190"},"modified":"2024-10-02T05:06:24","modified_gmt":"2024-10-02T05:06:24","slug":"value-objects-nedir-domain-driven-designddd-yaklasimindaki-rolu-nedir","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/value-objects-nedir-domain-driven-designddd-yaklasimindaki-rolu-nedir\/","title":{"rendered":"Value Objects Nedir? Domain-Driven Design(DDD) Yakla\u015f\u0131m\u0131ndaki Rol\u00fc Nedir?"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Value Objects, programlama s\u00fcre\u00e7lerinde entity&#8217;ler gibi kendisine ait kimli\u011fe yani id de\u011ferine sahip olmayan lakin ta\u015f\u0131d\u0131klar\u0131 de\u011ferlerle anlam ifade eden nesnelerdir ve DDD yakla\u015f\u0131m\u0131nda \u00f6nemli rol oynayan konseptlerden birisidir. Haliyle bu a\u00e7\u0131dan bakt\u0131\u011f\u0131m\u0131zda nesnenin kimli\u011fi onun sahip oldu\u011fu \u00f6zellikler taraf\u0131ndan k\u00fcm\u00fclatif olarak tan\u0131mlanmaktad\u0131r diyebiliriz. Evet, bu da ak\u0131llara <a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-9-0-records-ile-immutable-datalar\/\" rel=\"noopener\" target=\"_blank\">record<\/a>&#8216;lar\u0131 getirmektedir. Biliyorsunuz ki record&#8217;lar, bir nesnedir lakin de\u011ferleri \u00f6n planda olan bir nesnedir. Yani ayn\u0131  de\u011ferlere sahip olan iki farkl\u0131 record nesnesi kar\u015f\u0131la\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda bu bizim i\u00e7in ayn\u0131 olarak de\u011ferlendirilmektedir. \u0130\u015fte value object&#8217;lerde de mant\u0131k tam da budur. Yani ayn\u0131 de\u011ferlere sahip olan iki value object, fiziksel olarak farkl\u0131 nesneler olsalar da teoride ayn\u0131 kabul edilmektedirler. \u00c7\u00fcnk\u00fc bu nesnelerin kimlikleri, ta\u015f\u0131d\u0131klar\u0131 \u00f6zellikler ve de\u011ferler \u00fczerinden b\u00fct\u00fcnsel elde edilmektedir. Bu y\u00fczden value object&#8217;ler de\u011fi\u015ftirilemezdirler(immutable) Dolay\u0131s\u0131yla bir value object \u00fczerinde de\u011fi\u015fiklik yap\u0131lmas\u0131 gerekti\u011finde genellikle yeni bir nesne olu\u015fturulmakta ve de\u011fi\u015fiklik bu nesneye yans\u0131t\u0131lmaktad\u0131r. <\/p>\n<h3>Value Object&#8217;ler Nas\u0131l Tan\u0131mlan\u0131r?<\/h3>\n<p>C#&#8217;ta value object tasar\u0131m\u0131 i\u00e7in a\u015fa\u011f\u0131daki gibi dikkat edilmesi gereken birka\u00e7 husus mevcuttur.<\/p>\n<ul>\n<li>Value object&#8217;ler, yukar\u0131daki sat\u0131rlarda bahsedildi\u011fi gibi de\u011fi\u015ftirilemez olmal\u0131d\u0131rlar. Bu y\u00fczden t\u00fcm field ve property&#8217;leri readonly olarak tan\u0131mlanmal\u0131d\u0131r.<\/li>\n<li>Value object&#8217;lerin de\u011ferleri \u00f6n planda olaca\u011f\u0131ndan dolay\u0131 e\u015fitlik durumlar\u0131nda bu mant\u0131kta bir kar\u015f\u0131la\u015ft\u0131rma yap\u0131lmal\u0131d\u0131r. Bu y\u00fczden Equals ve GetHashCode metotlar\u0131 property&#8217;lere dayal\u0131 e\u015fitli\u011fi sa\u011flamak i\u00e7in override edilmelidir.\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\n.\r\n    public override int GetHashCode()\r\n        =&gt; (AProperty, BProperty).GetHashCode();\r\n\r\n    public override bool Equals(object? obj)\r\n    {\r\n        if (obj is X other)\r\n            return AProperty == other.AProperty &amp;&amp; BProperty == other.BProperty;\r\n\r\n        return false;\r\n    }\r\n.\r\n.\r\n.\r\n<\/pre>\n<\/div>\n<\/li>\n<li>Ve son olarak value object&#8217;ler ta\u015f\u0131yacaklar\u0131 de\u011ferlere dair ge\u00e7erlilik kontrollerini kendileri \u00fcstlenmelidirler. Bu durum <em>self-validation \/ \u00f6z do\u011frulama<\/em> olarak nitelendirilmektedir. Bu davran\u0131\u015f sembolik olarak a\u015fa\u011f\u0131daki gibi olabilir;\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nclass X\r\n{\r\n    public int AProperty { get; set; }\r\n    public int BProperty { get; set; }\r\n\r\n    public X(int aProperty, int bProperty)\r\n    {\r\n        if (aProperty &lt; 0)\r\n            throw new ArgumentException($&quot;{nameof(X.AProperty)} cannot be negative.&quot;);\r\n\r\n        if (bProperty &lt; 0)\r\n            throw new ArgumentException($&quot;{nameof(X.BProperty)} cannot be negative.&quot;);\r\n\r\n        AProperty = aProperty;\r\n        BProperty = bProperty;\r\n    }\r\n\r\n    .\r\n    .\r\n    .\r\n}\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<p>T\u00fcm bu hususlar\u0131 g\u00f6zeterek a\u015fa\u011f\u0131daki gibi ger\u00e7ek\u00e7i bir value object tan\u0131mlayabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nclass Money\r\n{\r\n    public decimal Amount { get; init; }\r\n    public string Currency { get; init; }\r\n    public Money(decimal amount, string currency)\r\n    {\r\n        \/\/Self-validation\r\n        Validate(amount, currency);\r\n\r\n        Amount = amount;\r\n        Currency = currency;\r\n    }\r\n\r\n    public override bool Equals(object? obj)\r\n    {\r\n        if (obj is Money other)\r\n            return Amount == other.Amount &amp;&amp; Currency == other.Currency;\r\n\r\n        return false;\r\n    }\r\n\r\n    public override int GetHashCode()\r\n        =&gt; (Amount, Currency).GetHashCode();\r\n\r\n    private void Validate(decimal amount, string currency)\r\n    {\r\n        if (amount &lt; 0)\r\n            throw new ArgumentException($&quot;Amount cannot be negative.&quot;);\r\n\r\n        if (string.IsNullOrEmpty(currency))\r\n            throw new ArgumentException($&quot;Currency cannot be null or empty.&quot;);\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00f6rnek kod blo\u011funu incelerseniz e\u011fer ilgili s\u0131n\u0131f\u0131n constructor&#8217;\u0131ndan gerekli de\u011ferler parametre olarak al\u0131nmakta ve Validate metodu arac\u0131l\u0131\u011f\u0131yla i\u015f kural\u0131 gere\u011fi self-validation ger\u00e7ekle\u015ftirilmektedir. Bu kontrol\u00fcn constructor&#8217;da yap\u0131lmas\u0131yla, ilgili value object&#8217;in kurallar\u0131 d\u0131\u015f\u0131nda bir instance&#8217;\u0131n aya\u011fa kald\u0131r\u0131lmas\u0131 engellenmektedir. O y\u00fczden value object tasar\u0131mlar\u0131nda self-validation davran\u0131\u015f\u0131 genellikle yap\u0131c\u0131da ger\u00e7ekle\u015ftirilmektedir.<\/p>\n<p>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere value object a\u015fa\u011f\u0131 yukar\u0131 bu mant\u0131kta tan\u0131mlanmakta ve bir nesneden ziyade b\u00fct\u00fcnsel olarak bir veriye kar\u015f\u0131l\u0131k gelen olguyu ifade etmektedir. Tabi bu tan\u0131m, tecr\u00fcbe edildi\u011fi \u00fczere i\u00e7erisinde di\u011fer nesnelerle olacak olan kar\u015f\u0131la\u015ft\u0131rmalar\u0131n fonksiyonel tan\u0131mlar\u0131n\u0131 da(Equals, GetHashCode vs.) bar\u0131nd\u0131rmakta ve bu esas\u0131nda operat\u00f6rler i\u00e7in de uygulanmas\u0131 gereken daha kompleks bir \u00e7al\u0131\u015fma gerektirmektedir. Nihayetinde bu nesneler madem veriye kar\u015f\u0131l\u0131k gelmektedirler o halde kendi aralar\u0131nda <code>==<\/code> yahut <code>!=<\/code> operat\u00f6rleriyle de kar\u015f\u0131la\u015ft\u0131r\u0131labilmelidirler. Do\u011fru de\u011fil mi?<\/p>\n<p>\u0130\u015fte bu durumda bu operat\u00f6rleri tan\u0131mlad\u0131\u011f\u0131m\u0131z t\u00fcm value object&#8217;ler i\u00e7in overload etmeli ve davran\u0131\u015f\u0131 veri \u00f6ncelikli olacak \u015fekilde kurgulamal\u0131y\u0131z. Ee bu ihtiyac\u0131 t\u00fcm value object&#8217;ler i\u00e7in ameleus mant\u0131\u011f\u0131nda tekrar tekrar yapmaktansa a\u015fa\u011f\u0131daki gibi tasarlanm\u0131\u015f bir base class&#8217;ta kar\u015f\u0131lamak hem kodlama a\u00e7\u0131s\u0131ndan daha makul olacak, hem de biryandan uygulamadaki value object&#8217;lerin zahiren marker&#8217;\u0131n\u0131 da olu\u015fturmu\u015f olaca\u011f\u0131z.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nabstract class ValueObject : IEquatable&lt;ValueObject&gt;\r\n{\r\n    protected abstract IEnumerable&lt;object&gt; GetEqualityComponents();\r\n\r\n    private bool ValuesAreEqual(ValueObject valueObject)\r\n        =&gt; GetEqualityComponents().SequenceEqual(valueObject.GetEqualityComponents());\r\n\r\n    public virtual bool Equals(ValueObject? other)\r\n        =&gt; other is not null &amp;&amp; ValuesAreEqual(other);\r\n\r\n    public override bool Equals(object? obj)\r\n        =&gt; obj is ValueObject valueObject &amp;&amp; ValuesAreEqual(valueObject);\r\n\r\n    public override int GetHashCode()\r\n        =&gt; GetEqualityComponents().Aggregate(default(int), (hashCode, value) =&gt; HashCode.Combine(hashCode, value.GetHashCode()));\r\n\r\n    public static bool operator ==(ValueObject? left, ValueObject? right)\r\n    {\r\n        if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))\r\n            return false;\r\n\r\n        return left.Equals(right);\r\n    }\r\n\r\n    public static bool operator !=(ValueObject? left, ValueObject? right)\r\n        =&gt; !(left == right);\r\n}\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011fundaki metotlar\u0131 tek tek incelersek e\u011fer;<\/p>\n<ul>\n<li><code>GetEqualityComponents<\/code> metodu ile bu abstract class&#8217;\u0131 implemente edecek olan value object&#8217;lerdeki hangi property&#8217;lerin de\u011fersel kar\u015f\u0131la\u015ft\u0131rmaya tabi tutulaca\u011f\u0131 referans edilmektedir. Haliyle bu metodun i\u00e7eri\u011fi concrete class&#8217;lar da belirlenecektir.<\/li>\n<li><code>ValuesAreEqual<\/code> metodunda ise ilgili value object&#8217;in <code>GetEqualityComponents<\/code> metodunda belirtilen property&#8217;lerinin de\u011fersel e\u015fitlik durumu de\u011ferlendirilmektedir. Bu de\u011ferlendirme s\u00fcrecinde dikkat ederseniz koleksiyonel de\u011fer kar\u015f\u0131la\u015ft\u0131rmam\u0131z\u0131 yapmam\u0131z\u0131 sa\u011flayan <code>SequenceEqual<\/code> metodu kullan\u0131lmaktad\u0131r.<\/li>\n<li><code>==<\/code> ve <code>!=<\/code> operator overloading&#8217;ler ise ilgili operat\u00f6rlere gerekli davran\u0131\u015flar\u0131 kazand\u0131rmaktad\u0131r.<\/li>\n<\/ul>\n<p>Evet, b\u00f6ylece art\u0131k bir value object&#8217;i tan\u0131mlamam\u0131z\u0131 sa\u011flayacak olan base class&#8217;\u0131 tam teferruatl\u0131ca olu\u015fturmu\u015f bulunuyoruz. Art\u0131k bu \u00e7al\u0131\u015fma neticesinde uygulamadaki value object&#8217;leri a\u015fa\u011f\u0131daki gibi &#8216;ValueObject&#8217; implementasyonu neticesinde a\u015fik\u00e2rene bir \u015fekilde tan\u0131mlayabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nclass Money : ValueObject\r\n{\r\n    public decimal Amount { get; init; }\r\n    public string Currency { get; init; }\r\n    public Money(decimal amount, string currency)\r\n    {\r\n        \/\/Self-validation\r\n        Validate(amount, currency);\r\n\r\n        Amount = amount;\r\n        Currency = currency;\r\n    }\r\n\r\n    private void Validate(decimal amount, string currency)\r\n    {\r\n        if (amount &lt; 0)\r\n            throw new ArgumentException($&quot;Amount cannot be negative.&quot;);\r\n\r\n        if (string.IsNullOrEmpty(currency))\r\n            throw new ArgumentException($&quot;Currency cannot be null or empty.&quot;);\r\n    }\r\n\r\n    protected override IEnumerable&lt;object&gt; GetEqualityComponents()\r\n    {\r\n        yield return Amount;\r\n        yield return Currency;\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Evet, value object tan\u0131mlama s\u00fcrecinde bu \u015fekilde daha kullan\u0131\u015fl\u0131 ve az maliyetli bir \u00e7al\u0131\u015fma yap\u0131ld\u0131\u011f\u0131 kanaatinde mutab\u0131k oldu\u011fumuzu d\u00fc\u015f\u00fcn\u00fcyorum \ud83d\ude42<\/p>\n<h3>record Kullanarak Value Object Tasarlama<\/h3>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-9-0-records-ile-immutable-datalar\/\" rel=\"noopener\" target=\"_blank\">record<\/a>&#8216;lar, yap\u0131sal olarak de\u011ferleri \u00f6n planda olan nesneleri temsil ettikleri i\u00e7in do\u011fal olarak value object ihtiya\u00e7lar\u0131n\u0131 kar\u015f\u0131layan nesnelerdir. Haliyle a\u015fa\u011f\u0131daki gibi tan\u0131mlanm\u0131\u015f bir record, \u00fcst sat\u0131rlarda class ile tasarlamaya \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131z value object&#8217;in esas\u0131nda birebir ayn\u0131 mahiyetinde varsay\u0131lan bir halidir ve direkt olarak value object&#8217;ten beklenen davran\u0131\u015flar\u0131 ve \u00f6zellikleri sergilemektedir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nrecord Money(decimal Amount, string Currency);\r\n<\/pre>\n<\/div>\n<p>record yap\u0131sal olarak immutable&#8217;d\u0131r. T\u00fcm property&#8217;leri \u00fczerinde otomatik olarak Equals ve GetHashCode metotlar\u0131n\u0131 override etmektedir ve <a href=\"https:\/\/www.gencayyildiz.com\/blog\/c-7-0-deconstruct-metodu\/\" rel=\"noopener\" target=\"_blank\">deconstruct<\/a> \u00f6zelli\u011fi sayesinde de kolayca par\u00e7alara ayr\u0131labilmektedir.<\/p>\n<p>Haliyle record&#8217;lar sayesinde class versiyonuna nazaran olduk\u00e7a k\u0131sa ve pratik bir \u015fekilde value object tan\u0131m\u0131 ger\u00e7ekle\u015ftirilebilmektedir. Ancak record&#8217;\u0131n getirdi\u011fi bu kolayl\u0131\u011fa nazaran, &#8216;ValueObject&#8217; base class&#8217;\u0131n\u0131 kullanarak yap\u0131lan \u00e7al\u0131\u015fmalarda da yap\u0131land\u0131rma ve \u00f6zelle\u015ftirme a\u00e7\u0131s\u0131ndan t\u00fcrl\u00fc avantajlar\u0131n olaca\u011f\u0131n\u0131 da belirtmeden ge\u00e7emeyece\u011fim.<\/p>\n<p>Ayr\u0131ca record&#8217;lar da self-validation uygulanmak istendi\u011finde de yine benzer mant\u0131kla a\u015fa\u011f\u0131daki gibi sanki s\u0131n\u0131flarda \u00e7al\u0131\u015f\u0131yormu\u015fcas\u0131na ger\u00e7ekle\u015ftirilebilmektedir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nrecord Money\r\n{\r\n    public decimal Amount { get; set; }\r\n    public string Currency { get; set; }\r\n    public Money(decimal amount, string currency)\r\n    {\r\n        \/\/Self-validation\r\n        Validate(amount, currency);\r\n\r\n        Amount = amount;\r\n        Currency = currency;\r\n    }\r\n\r\n    private void Validate(decimal amount, string currency)\r\n    {\r\n        if (amount &lt; 0)\r\n            throw new ArgumentException($&quot;Amount cannot be negative.&quot;);\r\n\r\n        if (string.IsNullOrEmpty(currency))\r\n            throw new ArgumentException($&quot;Currency cannot be null or empty.&quot;);\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Tabi bundan sonras\u0131 i\u00e7in programatik a\u00e7\u0131dan record&#8217;larla ilgili bilginiz ve tecr\u00fcbeniz ge\u00e7erli olacakt\u0131r.<\/p>\n<h3>EF Core &#8211; Persisting Value Objects<\/h3>\n<p>Value object&#8217;in kullan\u0131ld\u0131\u011f\u0131 \u00e7al\u0131\u015fmalarda, \u00f6zellikle EF Core ile birlikte bu nesnelerin y\u00f6netilmesi ve de\u011ferlerinin veritaban\u0131na yans\u0131t\u0131lmas\u0131(persisting) olduk\u00e7a \u00f6nem arz eden kritik bir konudur. \u00c7\u00fcnk\u00fc bu nesnelerde primary key&#8217;e kar\u015f\u0131l\u0131k de\u011fer bulunmamakta ve genellikle bir entity e\u015fli\u011finde veritaban\u0131nda depolanmaktad\u0131rlar. Yani anlayaca\u011f\u0131n\u0131z hem id&#8217;leri yoktur, hem de ili\u015fkisel mant\u0131kta veritaban\u0131nda tutulmak mecburiyetindedirler. Haliyle bir kimli\u011fi olmayan veriyi, kimli\u011fi olan bir veriyle ili\u015fkilendirip tutmak her ne kadar kulaklara mant\u0131ks\u0131z geliyor olsa da esas\u0131nda EF Core a\u00e7\u0131s\u0131ndan bu durum <em>Owned Types<\/em> ve <em>Complex Types<\/em> kavramlar\u0131 e\u015fli\u011finde \u00e7\u00f6z\u00fcme kavu\u015fturulmaktad\u0131r. \u015eimdi gelin bu kavramlar e\u015fli\u011finde EF Core&#8217;da value object kullan\u0131m\u0131n\u0131 de\u011ferlendirmeye ba\u015flayal\u0131m.<\/p>\n<ul>\n<li><strong><em>Owned Types<\/em><\/strong><br \/>\nTee zaman\u0131nda <a href=\"https:\/\/www.gencayyildiz.com\/blog\/entity-framework-core-owned-entities-and-table-splitting\/\" rel=\"noopener\" target=\"_blank\">Entity Framework Core \u2013 Owned Entities and Table Splitting<\/a> ba\u015fl\u0131kl\u0131 makalemizle inceledi\u011fimiz bu \u00f6zellik sayesinde bir entity&#8217;i par\u00e7alayabilmekte ve fiziksel olarak farkl\u0131 class&#8217;lardan meydana getirebilmekteyiz.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting.png\" alt=\"Entity Framework Core - Owned Entities and Table Splitting\" width=\"1377\" height=\"503\" class=\"aligncenter size-full wp-image-19937\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting.png 1377w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting-300x110.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting-1024x374.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2020\/12\/Entity-Framework-Core-Owned-Entities-and-Table-Splitting-768x281.png 768w\" sizes=\"auto, (max-width: 1377px) 100vw, 1377px\" \/><\/a>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere bu mant\u0131kla bir entity&#8217;nin kod taraf\u0131nda value object olarak ayr\u0131lan k\u0131sm\u0131 veritaban\u0131na esas\u0131nda bir b\u00fct\u00fcn olarak yans\u0131t\u0131labilmektedir.\n<\/li>\n<li><strong><em>Complex Types<\/em><\/strong><br \/>\n.NET 8 ile gelmi\u015f olan yeni bir EF Core \u00f6zelli\u011fidir. Owned Types&#8217;a benzer i\u015fleve sahip olsa da, davran\u0131\u015fsal olarak daha esnek ve geli\u015fmi\u015f bir yap\u0131dad\u0131r. Complex Type&#8217;lar, birden fazla entity taraf\u0131ndan kullan\u0131labilmekte b\u00f6ylece tekrar kullan\u0131labilirlik daha elveri\u015fli olabilmektedir. Ayr\u0131ca complex type&#8217;lar, ayr\u0131 bir tabloda saklanarak daha esnek bir veri modeli de olu\u015fturmam\u0131za imkan tan\u0131yabilmektedir.\n<\/li>\n<\/ul>\n<h3>Peki, Value Object&#8217;ler Hangi Durumlarda Kullan\u0131l\u0131r?<\/h3>\n<p>Asl\u0131nda bu sorunun cevab\u0131 olduk\u00e7a basit, ihtiya\u00e7 oldu\u011funda \ud83d\ude42 Ama tabi kullan\u0131m s\u0131n\u0131rlar\u0131n\u0131 biraz daha netle\u015ftirmemiz gerekirse e\u011fer domain de\u011fi\u015fmezlerini kaps\u00fcllemek veya d\u0131\u015far\u0131dan gelecek olan de\u011fer t\u00fcrl\u00fc verileri t\u00fcr g\u00fcvenli bir \u015fekilde elde edebilmek i\u00e7in kullan\u0131laca\u011f\u0131na dair bir genellemede bulunabiliriz. Misal olarak;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\ninterface ILeaveService\r\n{\r\n    int CalculateLeaveDays(User user, DateOnly startDate, DateOnly endDate);\r\n}\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki interface i\u00e7erisindeki <em>CalculateLeaveDays<\/em> imzas\u0131, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ba\u015flang\u0131\u00e7 ve biti\u015f tarihlerini parametre olarak almaktad\u0131r. Halbuki bu de\u011fer t\u00fcrlerini value object ile temsil ederek a\u015fa\u011f\u0131daki gibi t\u00fcr g\u00fcvenli hale getirebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\ninterface ILeaveService\r\n{\r\n    int CalculateLeaveDays(User user, DateRange dateRange);\r\n}\r\n\r\nrecord DateRange(DateOnly StartDate, DateOnly EndDate)\r\n{\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>\u0130\u015fte \u00f6zellikle kod aras\u0131nda bu tarz durumlar i\u00e7in value object&#8217;ler olduk\u00e7a efektiftir.<\/p>\n<h3>Onion Architecture&#8217;da Value Object&#8217;ler Hangi Katmanda, Nerede Tan\u0131mlanmal\u0131d\u0131r?<\/h3>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/nedir-bu-onion-architecture-tam-teferruatli-inceleyelim\/\" rel=\"noopener\" target=\"_blank\">Onion Architecture<\/a>&#8216;da domain ile ilgili temel i\u015f kurallar\u0131 ve yap\u0131 ta\u015flar\u0131 Domain(Core) katman\u0131nda tan\u0131mlanmaktad\u0131r, ee haliyle value object&#8217;ler de bu katmanda tutulmal\u0131d\u0131rlar. \u00c7\u00fcnk\u00fc her ne kadar entity&#8217;den farkl\u0131 olsalar da \u00f6z\u00fcnde bir sistemin i\u015f kural\u0131n\u0131 temsil etmektedirler ve bu minvalde di\u011fer katmanlardan ba\u011f\u0131ms\u0131zl\u0131k sergilemeleri gerekmektedir.<\/p>\n<p>Evet, b\u00f6ylece value object kavram\u0131n\u0131 teorik ve pratik olarak incelemi\u015f ve yaz\u0131l\u0131m s\u00fcre\u00e7lerindeki esas mahiyetine dair gerekli kriti\u011fi yapm\u0131\u015f bulunuyoruz. Bundan sonras\u0131 art\u0131k sizlerin ihtiya\u00e7lar\u0131 do\u011frultusunda ilgili yap\u0131y\u0131 kullanman\u0131z ve edinece\u011finiz tecr\u00fcbelerinizle bizlere d\u00f6n\u00fctler sa\u011flay\u0131p var olan eksikleri de tamamlatman\u0131zd\u0131r \ud83d\ude42<\/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<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Value Objects, programlama s\u00fcre\u00e7lerinde entity&#8217;ler gibi kendisine ait kimli\u011fe yani id de\u011ferine sahip olmayan lakin ta\u015f\u0131d\u0131klar\u0131 de\u011ferlerle anlam ifade eden nesnelerdir ve DDD yakla\u015f\u0131m\u0131nda \u00f6nemli rol oynayan konseptlerden birisidir. Haliyle bu a\u00e7\u0131dan bakt\u0131\u011f\u0131m\u0131zda&#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":22222,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3573],"tags":[5097,4331,4330,2851,4144,5154,5152,5153,5151,5150],"class_list":["post-27190","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microservices","tag-complex-types","tag-ddd","tag-domain-driven-design","tag-ef-core","tag-onion-architecture","tag-owned-types","tag-oz-dogrulama","tag-persisting-value-objects","tag-self-validation","tag-value-objects"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27190","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=27190"}],"version-history":[{"count":8,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27190\/revisions"}],"predecessor-version":[{"id":27199,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27190\/revisions\/27199"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/22222"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=27190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=27190"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=27190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}