﻿
{"id":25519,"date":"2022-09-04T21:34:29","date_gmt":"2022-09-04T21:34:29","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=25519"},"modified":"2022-09-04T21:34:29","modified_gmt":"2022-09-04T21:34:29","slug":"c-ile-table-data-gateway-design-patterntable-data-gateway-tasarim-deseni","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/c-ile-table-data-gateway-design-patterntable-data-gateway-tasarim-deseni\/","title":{"rendered":"C# \u0130le Table Data Gateway Design Pattern(Table Data Gateway Tasar\u0131m Deseni)"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde herhangi bir ORM kullanmay\u0131 tercih etmedi\u011fimiz projelerimizde veritaban\u0131 ile etkile\u015fime girecek olan operasyonlar\u0131m\u0131z\u0131n sorumluluklar\u0131n\u0131 \u00fcstlenecek olan katmanla i\u015f katman\u0131n\u0131n ileti\u015fimini modellememizi sa\u011flayan <em>Veri Katman\u0131 Modelleme Tasar\u0131m Desenleri<\/em>&#8216;nden olan <em>Table Data Gateway Design Pattern<\/em>&#8216;\u0131 hem teoride hem de pratikte inceliyor olaca\u011f\u0131z.<\/p>\n<h4>Table Data Gateway Design Pattern Nedir?<\/h4>\n<p>ORM kullan\u0131lmayan projelerde geli\u015ftirilen uygulamalar\u0131n veritaban\u0131 i\u015flemleri kod i\u00e7erisinde belirli algoritmik kontrollerle generate edilmi\u015f olan SQL c\u00fcmlecikleriyle giderilmektedir. Ee haliyle bu tarz durumlarda veritaban\u0131 i\u015flemlerini y\u00fcr\u00fctecek operasyonlar\u0131n uygulama mant\u0131\u011f\u0131n\u0131n i\u015flendi\u011fi kodlarla kar\u0131\u015ft\u0131r\u0131lmas\u0131 bir tak\u0131m problemlere sebebiyet verebilmektedir. Bu problemlerin en temel kayna\u011f\u0131, geli\u015ftiricilerin SQL&#8217;e(yahut kullan\u0131lan veritaban\u0131 diline) pek vak\u0131f olmama durumudur diyebiliriz. Ya da geli\u015ftirici ilgili veritaban\u0131n\u0131n diline vak\u0131fsa e\u011fer bu seferde diyagram\u0131na tam hakim olamayabilmektedir. Hal b\u00f6yleyken geli\u015ftiricilerin business logic&#8217;de \u00e7al\u0131\u015f\u0131rken veritaban\u0131na olan ihtiya\u00e7lar\u0131n\u0131 bodoslama koda yerle\u015ftirmeleri bahsi ge\u00e7en bu eksikliklerin s\u00fcre\u00e7te farkl\u0131 problemler olarak kar\u015f\u0131m\u0131za \u00e7\u0131kma ihtimallerini artt\u0131raca\u011f\u0131 ka\u00e7\u0131n\u0131lmazd\u0131r. Halbuki business logic ile veritaban\u0131 operasyonlar\u0131n\u0131n bir \u015fekilde birbirlerinden soyutlanmas\u0131 ve veritaban\u0131 i\u015flemlerinin i\u015fin uzmanlar\u0131 taraf\u0131ndan geli\u015ftirilip, sadece kullan\u0131m\u0131n\u0131 developer&#8217;lara b\u0131rakmas\u0131 olduk\u00e7a ideal bir yakla\u015f\u0131m olacakt\u0131r. \u00d6yle de\u011fil mi?<\/p>\n<p>Hani hat\u0131rlarsan\u0131z benzer problemler <a href=\"https:\/\/www.gencayyildiz.com\/blog\/query-object-design-patternsorgu-nesnesi-tasarim-deseni\/\" rel=\"noopener\" target=\"_blank\">Query Object Design Pattern<\/a>&#8216;\u0131nda da s\u00f6z konusuydu. \u0130lgili pattern&#8217;da bu problemlere veritaban\u0131 sorgusunu temsil edecek olan Query Object nesneleri olu\u015fturularak \u00e7\u00f6z\u00fcm getirilmekteyken, bu pattern&#8217;da ise kod i\u00e7erisinde SQL ile ilgili yap\u0131lacak t\u00fcm(sadece sorguyu de\u011fil, t\u00fcm i\u015flemleri) operasyonlar\u0131 basitlik ilkesi \u0131\u015f\u0131\u011f\u0131nda de\u011ferlendirip business logic mant\u0131\u011f\u0131ndan yal\u0131tarak tek bir nesneyle temsil edip \u00e7\u00f6z\u00fcm getirilmektedir. B\u00f6ylece her iki pattern&#8217;da da veritaban\u0131 sorgu dilini uygulamadan tamamen soyutlam\u0131\u015f bir netice elde edilmektedir.<\/p>\n<blockquote><p><em>Query Object pattern, kendisini bir SQL sorgusuna d\u00f6n\u00fc\u015ft\u00fcrebilen bir nesne yap\u0131s\u0131yken; Table Data Gateway pattern ise veritaban\u0131ndaki bir tabloya kar\u015f\u0131l\u0131k t\u00fcm operasyonlar\u0131 \u00fcstlenen bir s\u0131n\u0131ft\u0131r.<\/em><\/p><\/blockquote>\n<h4>Amac\u0131 Nedir ve Nas\u0131l Tasarlan\u0131r?<\/h4>\n<p>Table Data Gateway deseninin temel amac\u0131 uygulamada SQL sorgular\u0131n\u0131n bir standart e\u015fli\u011finde tek bir merkezi yerde toplanmas\u0131n\u0131 sa\u011flamakt\u0131r. Bunun i\u00e7in veritaban\u0131ndaki her bir tabloya kar\u015f\u0131l\u0131k(bu view ya da stored procedure olabilir) ayr\u0131 bir s\u0131n\u0131f olu\u015fturarak i\u00e7erisinde select, insert, update ve delete operasyonlar\u0131n\u0131 bar\u0131nd\u0131r\u0131r. Bu s\u0131n\u0131flar\u0131n teknik ad\u0131 &#8216;<em>Table Data Gateway<\/em>&#8216;dir. Burada her bir tabloya kar\u015f\u0131 bir s\u0131n\u0131f\u0131n in\u015fas\u0131 her ne kadar zaruri olsa da bazen basit senaryolarda t\u00fcm tablolar i\u00e7in t\u00fcm i\u015flevsellikleri bar\u0131nd\u0131ran tek bir s\u0131n\u0131f tan\u0131mlay\u0131p, kullan\u0131labilmektedir.<\/p>\n<blockquote><p><em style=\"color:green;\">Bir veritaban\u0131 tablosuna kod k\u0131sm\u0131ndan gateway(ge\u00e7it) g\u00f6revi g\u00f6ren ve t\u00fcm select, insert, update ve delete sorumluluklar\u0131n\u0131 \u00fcstlenen s\u0131n\u0131fa <u>Table Data Gateway<\/u> denir.<\/em><\/p><\/blockquote>\n<p>Bir Table Data Gateway instance&#8217;\u0131, kar\u015f\u0131l\u0131\u011f\u0131 olan veritaban\u0131 tablosundaki t\u00fcm sat\u0131rlar\u0131 handler edebilir. Bu s\u00fcre\u00e7te sorgu i\u00e7in gerekli olan parametreleri ilkel olarak metot parametresi \u015feklinde alabilir ve domain nesnesi(entity) hakk\u0131nda hi\u00e7bir \u015fey bilmeksizin operasyonlar\u0131 ger\u00e7ekle\u015ftirebilir. \u00c7\u00fcnk\u00fc her bir domain nesnesine kar\u015f\u0131l\u0131k gateway s\u0131n\u0131f\u0131 olmas\u0131n\u0131 gerektirir. Bu duruma \u00f6rnek olmas\u0131 hasebiyle; &#8216;Person&#8217; ad\u0131nda bir domain class&#8217;\u0131m\u0131z\u0131n oldu\u011funu d\u00fc\u015f\u00fcn\u00fcrsek e\u011fer buna kar\u015f\u0131l\u0131k veritaban\u0131 i\u015flemleri i\u00e7in &#8216;PersonGateway&#8217; s\u0131n\u0131f\u0131n\u0131n olmas\u0131 gerekmektedir. Ayr\u0131ca Table Data Gateway s\u0131n\u0131flar\u0131 sadece tek bir tabloya \u00f6zel olacaklar\u0131 i\u00e7in birbirleriyle herhangi bir etkile\u015fimleri olmayacakt\u0131r. Bu y\u00fczden bu pattern&#8217;da yeniden kullan\u0131labilirlik(reusable) yoktur.<\/p>\n<h4>Ne Zaman Tercih Edilmelidir?<\/h4>\n<p>\u00d6zellikle karma\u015f\u0131k i\u015f kurallar\u0131n\u0131n olmad\u0131\u011f\u0131 durumlarda tercih edilebilir. \u00c7\u00fcnk\u00fc sade \u00e7al\u0131\u015fmalarda ger\u00e7ekle\u015ftirilecek veritaban\u0131 i\u015flemleri Table Data Gateway s\u0131n\u0131flar\u0131 arac\u0131l\u0131\u011f\u0131yla rahatl\u0131kla y\u00f6netilebilir ve ihtiyaca binaen kolayca refactoring edilebilir.<\/p>\n<p>Ayr\u0131ca veritaban\u0131 operasyonlar\u0131n\u0131n tablo baz\u0131nda gruplanmas\u0131 gerekti\u011fi durumlarda da tercih edilebilir. Tabi burada unutulmamas\u0131 gereken husus \u015fudur ki, Table Data Gateway deseni uygulamayla ili\u015fkili t\u00fcm tablolarda ayn\u0131 mant\u0131kta kullan\u0131lmal\u0131d\u0131r. Aksi taktirde belirli bir e\u015fi\u011fin \u00fcst\u00fcndeki tablolara sahip olan \u00e7al\u0131\u015fmalarda refactoring i\u015fleminin yap\u0131labilmesi olduk\u00e7a maliyetli olacakt\u0131r.<\/p>\n<blockquote><p><em style=\"color:orange;\">Table Data Gateway deseni, bir nevi uygulama mant\u0131\u011f\u0131n\u0131 veritaban\u0131 eri\u015fimiyle encapsule etmeye yarar.<\/em><\/p><\/blockquote>\n<h4>\u00d6rneklendirelim<\/h4>\n<p>\u015eimdi Table Data Gateway desenini yukar\u0131daki sat\u0131rlarda bahsedildi\u011fi \u00fczere a\u015fa\u011f\u0131daki &#8216;Persons&#8217; tablosuna uygun bir \u015fekilde \u00f6rnek senaryo ama\u00e7l\u0131 uygulayal\u0131m.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2022\/09\/C-Ile-Table-Data-Gateway-Design-PatternTable-Data-Gateway-Tasarim-Deseni.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2022\/09\/C-Ile-Table-Data-Gateway-Design-PatternTable-Data-Gateway-Tasarim-Deseni.png\" alt=\"C# \u0130le Table Data Gateway Design Pattern(Table Data Gateway Tasar\u0131m Deseni)\" width=\"225\" height=\"110\" class=\"aligncenter size-full wp-image-25532\" \/><\/a>\u0130lk olarak &#8216;SqlConnection&#8217; ve &#8216;SqlCommand&#8217; nesnelerini bizim i\u00e7in organize eden temel bir s\u0131n\u0131f olu\u015ftural\u0131m. <\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic static class Database\r\n{\r\n    static SqlConnection _connection;\r\n    static Database()\r\n    {\r\n        object _lock = new();\r\n        lock (_lock)\r\n            _connection = new(&quot;Server=localhost, 1433;Database=TableDataGatewayDB;User Id=sa;Password=1q2w3e4r+!&quot;);\r\n        _connection.Open();\r\n    }\r\n\r\n    public static async Task&lt;int&gt; ExecuteNonQueryAsync(string query, params SqlParameter&#x5B;] parameters)\r\n    {\r\n        SqlCommand command = new(query, _connection);\r\n        command.Parameters.AddRange(parameters);\r\n        return await command.ExecuteNonQueryAsync();\r\n    }\r\n\r\n    public static async Task&lt;SqlDataReader&gt; ExecuteReaderAsync(string query, params SqlParameter&#x5B;] parameters)\r\n    {\r\n        SqlCommand command = new(query, _connection);\r\n        command.Parameters.AddRange(parameters);\r\n        return await command.ExecuteReaderAsync();\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere yukar\u0131daki &#8216;Database&#8217; isimli static s\u0131n\u0131f temel veritaban\u0131 eri\u015fim sorumlulu\u011funu \u00fcstlenmektedir. Dikkatli incelerseniz e\u011fer i\u00e7erisindeki &#8216;ExecuteNonQueryAsync&#8217; ve &#8216;ExecuteReaderAsync&#8217; metotlar\u0131 arac\u0131l\u0131\u011f\u0131yla sorgu zeminlerini olu\u015fturmakta ve ihtiya\u00e7 olabilecek parametreleri almaktad\u0131r. Ard\u0131ndan &#8216;Persons&#8217; tablosu i\u00e7in Table Data Gateway sorumlulu\u011funu \u00fcstlenecek olan &#8216;PersonGateway&#8217; s\u0131n\u0131f\u0131n\u0131 olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic class PersonGateway\r\n{\r\n    \/\/ Person ekleme\r\n    public async Task&lt;int&gt; AddPersonAsync(string firstName, string lastName, string country)\r\n        =&gt; await Database.ExecuteNonQueryAsync(&quot;INSERT Persons(FirstName, LastName, Country) VALUES(@firstName, @lastName, @country);&quot;\r\n            , new SqlParameter(&quot;firstName&quot;, firstName)\r\n            , new SqlParameter(&quot;lastName&quot;, lastName)\r\n            , new SqlParameter(&quot;country&quot;, country));\r\n\r\n    \/\/Personel silme\r\n    public async Task&lt;int&gt; RemovePersonAsync(int id)\r\n        =&gt; await Database.ExecuteNonQueryAsync(&quot;DELETE FROM Persons WHERE Id = @id&quot;\r\n            , new SqlParameter(&quot;id&quot;, id));\r\n\r\n    \/\/Personel g\u00fcncelleme\r\n    public async Task&lt;int&gt; UpdatePersonAsync(int id, string firstName, string lastName, string country)\r\n        =&gt; await Database.ExecuteNonQueryAsync(&quot;UPDATE Persons Set FirstName = @firstName, LastName = @lastName, Country = @country WHERE Id = @id&quot;\r\n            , new SqlParameter(&quot;id&quot;, id)\r\n            , new SqlParameter(&quot;firstName&quot;, firstName)\r\n            , new SqlParameter(&quot;lastName&quot;, lastName)\r\n            , new SqlParameter(&quot;country&quot;, country));\r\n\r\n    \/\/\u0130sme g\u00f6re personel sorgulama\r\n    public async Task&lt;List&lt;PersonDTO&gt;&gt; GetPersonByFirstNameAsync(string firstName)\r\n    {\r\n        SqlDataReader dataReader = await Database.ExecuteReaderAsync(&quot;SELECT * FROM Persons WHERE FirstName = @firstName&quot;\r\n                 , new SqlParameter(&quot;firstName&quot;, firstName));\r\n\r\n        List&lt;PersonDTO&gt; datas = new();\r\n        while (await dataReader.ReadAsync())\r\n            datas.Add(new()\r\n            {\r\n                Id = int.Parse(dataReader&#x5B;&quot;Id&quot;].ToString()),\r\n                Country = dataReader&#x5B;&quot;Country&quot;].ToString(),\r\n                FirstName = dataReader&#x5B;&quot;FirstName&quot;].ToString(),\r\n                LastName = dataReader&#x5B;&quot;LastName&quot;].ToString()\r\n            });\r\n\r\n        return datas;\r\n    }\r\n\r\n    \/\/Id'ye g\u00f6re personel sorgulama\r\n    public async Task&lt;PersonDTO&gt; GetPersonByIdAsync(int id)\r\n    {\r\n        SqlDataReader dataReader = await Database.ExecuteReaderAsync(&quot;SELECT * FROM Persons WHERE Id = @id&quot;\r\n               , new SqlParameter(&quot;id&quot;, id));\r\n\r\n        PersonDTO data = new();\r\n        await dataReader.ReadAsync();\r\n        data.Id = int.Parse(dataReader&#x5B;&quot;Id&quot;].ToString());\r\n        data.Country = dataReader&#x5B;&quot;Country&quot;].ToString();\r\n        data.FirstName = dataReader&#x5B;&quot;FirstName&quot;].ToString();\r\n        data.LastName = dataReader&#x5B;&quot;LastName&quot;].ToString();\r\n\r\n        return data;\r\n    }\r\n\r\n    \/\/T\u00fcm personeller\r\n    public async Task&lt;List&lt;PersonDTO&gt;&gt; GetPersonsAsync()\r\n    {\r\n        SqlDataReader dataReader = await Database.ExecuteReaderAsync(&quot;SELECT * FROM Persons&quot;);\r\n\r\n        List&lt;PersonDTO&gt; datas = new();\r\n        while (await dataReader.ReadAsync())\r\n            datas.Add(new()\r\n            {\r\n                Id = int.Parse(dataReader&#x5B;&quot;Id&quot;].ToString()),\r\n                Country = dataReader&#x5B;&quot;Country&quot;].ToString(),\r\n                FirstName = dataReader&#x5B;&quot;FirstName&quot;].ToString(),\r\n                LastName = dataReader&#x5B;&quot;LastName&quot;].ToString()\r\n            });\r\n\r\n        return datas;\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131da g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere &#8216;PersonGateway&#8217; s\u0131n\u0131f\u0131n\u0131 m\u00fcmk\u00fcn mertebe t\u00fcm i\u015flemleri \u00f6rneklendirecek \u015fekilde doldurmu\u015f bulunmaktay\u0131m. Tabi burada sorgulama neticesinde gelecek olan verileri a\u015fa\u011f\u0131daki &#8216;PersonDTO&#8217; isimli s\u0131n\u0131f e\u015fli\u011finde modellemekteyim.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\npublic class PersonDTO\r\n{\r\n    public int Id { get; set; }\r\n    public string FirstName { get; set; }\r\n    public string LastName { get; set; }\r\n    public string Country { get; set; }\r\n}\r\n<\/pre>\n<\/div>\n<p>Velhas\u0131l art\u0131k Table Data Gateway deseni sayesinde uygulamam\u0131zdaki &#8216;Persons&#8217; tablosuyla olabilecek t\u00fcm operasyonlar\u0131 &#8216;PersonGateway&#8217; s\u0131n\u0131f\u0131 e\u015fli\u011finde tek bir \u00e7at\u0131 alt\u0131nda a\u015fa\u011f\u0131daki gibi y\u00fcr\u00fctebilmekteyiz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nPersonGateway personGateway = new();\r\nawait personGateway.AddPersonAsync(&quot;Gen\u00e7ay&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\nawait personGateway.AddPersonAsync(&quot;Nevin&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\nawait personGateway.AddPersonAsync(&quot;G\u00fcl\u015fah&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\nawait personGateway.AddPersonAsync(&quot;Emine&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\nawait personGateway.AddPersonAsync(&quot;Elif&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\nawait personGateway.AddPersonAsync(&quot;Muhammet K\u00fcr\u015fad&quot;, &quot;Y\u0131ld\u0131z&quot;, &quot;Ankara&quot;);\r\n\r\nvar persons = await personGateway.GetPersonsAsync();\r\nforeach (var person in persons)\r\n    Console.WriteLine($&quot;{person.FirstName} {person.LastName} - {person.Country}&quot;);\r\n<\/pre>\n<\/div>\n<p>Nihai olarak,<br \/>\nSQL operasyonlar\u0131n\u0131n manuel olarak y\u00fcr\u00fct\u00fcld\u00fc\u011f\u00fc uygulamalar \u00fczerinde bu i\u015flemlerin bir yerde fiziksel olarak toplan\u0131p merkeziyet kazand\u0131r\u0131lmas\u0131n\u0131 hedefleyen Table Data Gateway pattern&#8217;\u0131 uygulama zorlu\u011fu a\u00e7\u0131s\u0131ndan olduk\u00e7a yal\u0131n ve kullan\u0131m a\u00e7\u0131s\u0131ndan ise basit yahut orta \u00f6l\u00e7ekli uygulamalar i\u00e7in olduk\u00e7a elveri\u015flidir. Tabi bu pattern&#8217;\u0131n teknik yap\u0131s\u0131ndan ziyade projedeki davran\u0131\u015flar\u0131n i\u015flevselli\u011fine g\u00f6re merkezile\u015ftirilmesi gereklili\u011fi prensibinin kavran\u0131lmas\u0131 esas \u00f6nemi ta\u015f\u0131maktad\u0131r kanaatindeyim.<\/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 uygulaman\u0131n kaynak kodlar\u0131na a\u015fa\u011f\u0131daki github adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/Table_Data_Gateway_Design_Pattern\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/Table_Data_Gateway_Design_Pattern<\/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 i\u00e7eri\u011fimizde herhangi bir ORM kullanmay\u0131 tercih etmedi\u011fimiz projelerimizde veritaban\u0131 ile etkile\u015fime girecek olan operasyonlar\u0131m\u0131z\u0131n sorumluluklar\u0131n\u0131 \u00fcstlenecek olan katmanla i\u015f katman\u0131n\u0131n ileti\u015fimini modellememizi sa\u011flayan Veri Katman\u0131 Modelleme Tasar\u0131m Desenleri&#8216;nden olan Table Data Gateway&#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":25536,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[153],"tags":[1114,4655,4654,4656,4657],"class_list":["post-25519","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-design-pattern","tag-design-patterns","tag-table-data-gateway","tag-table-data-gateway-design-pattern","tag-veri-katmani-modelleme","tag-veri-katmani-modelleme-tasarim-desenleri"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/25519","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=25519"}],"version-history":[{"count":16,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/25519\/revisions"}],"predecessor-version":[{"id":25537,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/25519\/revisions\/25537"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/25536"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=25519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=25519"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=25519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}