{"id":174,"date":"2019-09-30T22:26:29","date_gmt":"2019-09-30T19:26:29","guid":{"rendered":"http:\/\/www.potansif.com\/?p=174"},"modified":"2019-10-01T16:31:49","modified_gmt":"2019-10-01T13:31:49","slug":"tasarim-desenleri-fluent-design","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=174","title":{"rendered":"Tasar\u0131m Desenleri : Fluent Design"},"content":{"rendered":"<p>Bir XML belgesini t\u0131pk\u0131 a\u015fa\u011f\u0131daki gibi \u00e7ok sade ve \u201cANLA\u015eILIR\u201d bir \u015fekilde olu\u015fturabilseydik daha iyi olmaz m\u0131yd\u0131?<!--more--><\/p>\n<pre><code>procedure TForm1.Button2Click(Sender: TObject);\r\nvar\r\n&nbsp;XML: TXML2;\r\nbegin\r\n&nbsp;try\r\n&nbsp; &nbsp;XML := New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Version(1.0)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Encoding(TEncoding.UTF8)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.NameSpace('')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Kutuphane'\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Kitap', [ 'ID=\"1000\"', 'Indirimli=\"Hayir\"' ]\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Adi' &nbsp; , 'Mastering Delphi')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Fiyat' , 50)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Stok' &nbsp;, 40)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazarlar'\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazar', 'Marco CANTU')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Kitap', [ 'ID=\"1001\"', 'Indirimli=\"Evet\"' ]\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Adi' &nbsp; ,'PHP, MySQL ve Apache')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Fiyat' , 65)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Stok' &nbsp;, 30)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazarlar'\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazar', 'Julie C. MELONI')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Kitap', [ 'ID=\"1002\"', 'Indirimli=\"Evet\"' ]\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Adi' &nbsp; ,'Delphi Cookbook')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Fiyat' , 35)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Stok' &nbsp;, 300)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazarlar'\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;,New\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Add('Yazar', 'Daniele TET\u0130')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;\r\n&nbsp; &nbsp;Memo1.Text := XML.SaveToFile(\u2018C:\\Temp\\Demo.xml\u2019).AsString;\r\n&nbsp;finally\r\n&nbsp; &nbsp;FreeAndNil(XML);\r\n&nbsp;end;\r\nend;<\/code><\/pre>\n<p>( Yaz\u0131n\u0131n sonunda yukar\u0131daki \u00f6rne\u011fi kullanaca\u011f\u0131m\u0131z XML s\u0131n\u0131f\u0131n\u0131n da kaynak kodlar\u0131n\u0131 bulabilirsiniz. )<\/p>\n<p>Bazen, uzun uzun kod yazmak o kadar s\u0131k\u0131c\u0131, o kadar bunalt\u0131c\u0131 oluyor ki insan (bu i\u015fi sevmese) illallah edebiliyor. Kendimizi k\u0131s\u0131r bir d\u00f6ng\u00fcn\u00fcn i\u00e7inde hapsolmu\u015f gibi hissetti\u011fimiz zamanlarda \u201cyahu \u015funu daha basit bir \u015fekilde halledemiyor muyuz\u201d diye sorarken bulabiliyoruz. B\u00f6yle bir ruh halindeyken bunal\u0131p web\u2019de dola\u015fmaya \u00e7\u0131kt\u0131\u011f\u0131m bir vakitte rastlad\u0131\u011f\u0131m sitelerden birinde Fluent Interface konusunda ufak bir \u00f6rnek ile kar\u015f\u0131la\u015ft\u0131m; biraz inceleyince \u201cHAH!\u201d dedim. \u201cOnca property, onca de\u011fi\u015fken, onca \u00f6znitelik onca yard\u0131mc\u0131 nesne tan\u0131mla, yok parentine \u015funu ownerine bunu ata gibi kodun aras\u0131nda kaybolmaya ne gerek var, class\u2019\u0131n\u0131 zincirleme tan\u0131mla olsun bitsin\u201d diyebildim\u2026<br \/>\nFluent Design, Fluent Interface, seveni de var sevmeyeni de, san\u0131r\u0131m dozunda ve yerinde kulland\u0131k\u00e7a sevmemek elde de\u011fil\u2026<\/p>\n<p><b>Nedir<\/b><\/p>\n<p>Fluent Interface konusuna bu forumda da birka\u00e7 arkada\u015f\u0131m\u0131z g\u00f6z k\u0131rpm\u0131\u015f, ufak bir \u00f6rnek verilmi\u015f fakat nedir, ne de\u011fildir pek irdelenmemi\u015f. Bu tekni\u011fin baz\u0131 alanlarda i\u015fimizi daha basite indirgememize yard\u0131m edece\u011fini d\u00fc\u015f\u00fcn\u00fcyorum, \u00e7\u00fcnk\u00fc kullan\u0131m\u0131 hakikaten \u00e7ok basit ve yap\u0131s\u0131 ger\u00e7ekten sade\u2026 Fakat bu sadeli\u011fi hafife almay\u0131n, asl\u0131nda \u00e7ok b\u00fcy\u00fck bir i\u015f ba\u015fard\u0131\u011f\u0131n\u0131 siz de g\u00f6receksiniz\u2026<\/p>\n<p>Bir tan\u0131m yapmam\u0131z gerekirse o da \u015f\u00f6yle bir \u015fey olabilir; Fluent Interface, bir s\u0131n\u0131f\u0131n kendi metodlar\u0131n\u0131 zincirleme olarak kendi i\u00e7inde kullanabilmemize imk\u00e2n tan\u0131yan ve kodun okunabilirli\u011finden ziyade \u201canla\u015f\u0131labilirli\u011fini\u201d hedefleyen bir programlama tekni\u011fidir. Bu teknik, PHP, Java, C# programc\u0131lar\u0131 aras\u0131nda yayg\u0131n bir bi\u00e7imde kullan\u0131lmaktad\u0131r. Bununla birlikte Delphi\u2019nin baz\u0131 nesnelerinde de bu teknik kullan\u0131la gelmi\u015ftir. ( Bak\u0131n\u0131z http:\/\/docwiki.embarcadero.com\/Libraries\/XE2\/en\/System.SysUtils.TStringBuilder gibi&#8230;)<\/p>\n<p>Olay\u0131n can damar\u0131nda asl\u0131nda ufak bir \u201chile\u201d var; Basit bir s\u0131n\u0131f tan\u0131ml\u0131yorsunuz, ard\u0131ndan o s\u0131n\u0131f\u0131n t\u00fcm fonksiyonlar\u0131n\u0131n RESULT de\u011ferini SELF yap\u0131yorsunuz. B\u00f6ylece s\u0131n\u0131f\u0131 kulland\u0131\u011f\u0131n\u0131z yerde zincirleme olarak s\u0131n\u0131f\u0131n t\u00fcm elemanlar\u0131n\u0131 birbirine \u201c.\u201d Operat\u00f6r\u00fcyle ba\u011flayabiliyorsunuz. B\u00f6ylece aradaki olu\u015fturma ve atama i\u015flemlerine girmeden (asl\u0131nda arka tarafta yap\u0131l\u0131yor) do\u011frudan zincirleme kodlar yazabiliyorsunuz. Bu da size yaz\u0131lan kodun daha kolay anla\u015f\u0131labilmesini sa\u011fl\u0131yor.<\/p>\n<p>Bu tekni\u011fi yans\u0131tan basit bir fluent interface y\u00f6ntemi i\u00e7in a\u015fa\u011f\u0131daki gibi bir s\u0131n\u0131f tan\u0131m\u0131 ba\u015flang\u0131\u00e7 i\u00e7in yeterli olacakt\u0131r.<\/p>\n<pre><code>Interface\r\n\r\ntype\r\n&nbsp;TKelimeler = class\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;Cumle: String;\r\n&nbsp; &nbsp; &nbsp;function Ekle(aString: String): TKelimeler;&nbsp;\r\n&nbsp;end;\r\n\r\nfunction Yeni: TKelimeler;\r\n\r\nImplementation<\/code><\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi normal bir s\u0131n\u0131f tan\u0131m\u0131 yapt\u0131k. Tek fark \u201cEkle\u201d fonksiyonunun veri tipinin s\u0131n\u0131f tan\u0131m\u0131 ile ayn\u0131 olmas\u0131. \u0130\u015fte bu nokta bu tekni\u011fin temel yap\u0131ta\u015f\u0131n\u0131 olu\u015fturuyor.<\/p>\n<p>Bunu bir class i\u00e7in de\u011fil de bir record i\u00e7in de benzer bir \u015fekilde tan\u0131mlayabiliriz. Biz anlat\u0131m\u0131m\u0131zda Class \u00fczerinden devam edece\u011fiz.<\/p>\n<p><b>NOT: Verdi\u011fim \u00f6rnekte \u00f6zellikle bir TInterfacedObject ve Interface kullanmad\u0131m. Bunun sebebini konunun alt k\u0131sm\u0131nda \u201cDezavantajlar\u0131\u201d ba\u015fl\u0131kl\u0131 b\u00f6l\u00fcmde inceleyebilirsiniz.<\/b><\/p>\n<p>Kald\u0131\u011f\u0131m\u0131z yerden bu \u00f6nemli noktaya devam edip \u015fu \u201cekle\u201d fonksiyonunun i\u00e7eride neler \u00e7evirdi\u011fine bir bakal\u0131m;<\/p>\n<pre><code>function TKelimeler.Ekle(aString: String): TKelimeler;\r\nbegin\r\n&nbsp;Cumle := Trim(Cumle + aString) + \u2018 \u2018;\r\n&nbsp;Result := Self; \/\/ \u00d6nemli olan bu sat\u0131r, bu zincir kurmam\u0131z\u0131 sa\u011fl\u0131yor.\r\nend;<\/code><\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi kendisine verilen parametreyi Cumle adl\u0131 bir de\u011fi\u015fkende araya bir bo\u015fluk koyarak biriktiriyor <b>( Cumle := Trim(Cumle + aString) + \u2018 \u2018; )<\/b> ve ard\u0131ndan sonu\u00e7 olarak <b>(Result := Self)<\/b> yine kendisini veriyor.<\/p>\n<p>Buraya kadar anlat\u0131lanlar, her ne kadar fluent intefacenin basit anlamda yap\u0131s\u0131n\u0131 anlamam\u0131z\u0131 yard\u0131mc\u0131 olsa da potansiyelini anlamam\u0131z a\u00e7\u0131s\u0131ndan pek de doyurucu bir \u00f6rnek olmad\u0131. (Bunu as\u0131l i\u015f ba\u015f\u0131ndayken g\u00f6rmek laz\u0131m.) Bu yap\u0131y\u0131 biraz daha karma\u015f\u0131kla\u015ft\u0131ral\u0131m ve s\u0131n\u0131f\u0131m\u0131z\u0131 a\u015fa\u011f\u0131daki gibi geni\u015fletelim.<\/p>\n<pre><code>interface\r\n\r\nuses\r\n&nbsp;System.SysUtils, System.Variants;\r\n\r\nType\r\n&nbsp;TVarArray = array of Variant;\r\n&nbsp;TKelimeler = class \/\/ record \/\/ (TInterfacedObject, IInterface)\r\n&nbsp;strict private\r\n&nbsp; &nbsp;function OzNitelik(Value: Variant): TKelimeler;\r\n&nbsp;public\r\n&nbsp; &nbsp;Cumle: String;\r\n&nbsp; &nbsp;property Nitelik[Value: Variant]: TKelimeler read OzNitelik; default;\r\n&nbsp; &nbsp;function enter: TKelimeler;\r\n&nbsp; &nbsp;function Ekle(Value: Variant): TKelimeler; overload;\r\n&nbsp; &nbsp;function Ekle(Value: TVarArray): TKelimeler; overload;\r\n&nbsp; &nbsp;function Parantez(Value: TKelimeler; Yoket: Boolean = TRUE): TKelimeler;\r\n&nbsp;end;\r\n\r\nfunction Yeni: TKelimeler;\r\n\r\nimplementation<\/code><\/pre>\n<p>\u00d6rne\u011fimize devam edecek olursak, senaryomuzu da ba\u015ftan belirtelim; amac\u0131m\u0131z TKelimeler nesnesine kelimeler ekleyip bunu bize bir c\u00fcmle olarak vermesini sa\u011flamak olsun. Fakat bunu yaparken tip d\u00f6n\u00fc\u015f\u00fcmleriyle u\u011fra\u015fmayal\u0131m, ayn\u0131 zamanda c\u00fcmlemizin i\u00e7ine parantezler ekleyip yine bu parantezlerde de ayn\u0131 zincir yap\u0131s\u0131n\u0131 kullanabilelim. Hatta herhangi bir fonksiyonu kullanmadan, do\u011frudan \u201csadece\u201d de\u011ferleri de i\u015fleyebilelim. (Biraz abartt\u0131k galiba \ud83d\ude00 ) Bunun i\u00e7in nesnemizin mutfa\u011f\u0131ndaki yemek nas\u0131l pi\u015fiyor \u00f6nce onu bir inceleyelim. Buyurun, kodumuzun devam\u0131;<\/p>\n<pre><code>implementation\r\n\r\nfunction Yeni: TKelimeler;\r\nbegin\r\n&nbsp;Result := TKelimeler.Create;\r\nend;\r\n\r\n{ TKelimeler }\r\n\r\nfunction TKelimeler.Ekle(Value: Variant): TKelimeler;\r\nbegin\r\n&nbsp;\/\/ Elimize ge\u00e7irdi\u011fimiz t\u00fcm variant de\u011ferlerini stringe \u00e7eviriyoruz\r\n&nbsp;\/\/ bu sayede tip d\u00f6n\u00fc\u015f\u00fcmleri ile ilgili bir endi\u015feye kap\u0131lmam\u0131za gerek kalm\u0131yor.\r\n&nbsp;Cumle := Cumle + VarToStr( Value ) + ' ';\r\n&nbsp;Result := Self;\r\nend;\r\n\r\nfunction TKelimeler.enter: TKelimeler;\r\nbegin\r\n&nbsp;\/\/ Alt sat\u0131ra ge\u00e7i\u015f i\u00e7in \u00f6zel bir fonksiyon tan\u0131mlam\u0131\u015f olal\u0131m\r\n&nbsp;\/\/ (Pek bir esprisi yok asl\u0131nda\u2026 Sadece enter ve sat\u0131r ba\u015f\u0131 karakterlerini basar)\r\n&nbsp;Cumle := Cumle.Trim + #13#10;\r\n&nbsp;Result := Self;\r\nend;\r\n\r\nfunction TKelimeler.Ekle(Value: TVarArray): TKelimeler;\r\nvar\r\n&nbsp;I: Integer;\r\nBegin\r\n&nbsp;\/\/ Burada elimize z\u00fcmre halinde bir grup veri tipi belirsiz parametre geliyor\r\n&nbsp;\/\/ Tip d\u00f6n\u00fc\u015f\u00fcm\u00fc meselesini a\u015fmak i\u00e7in hepsini teker teker stringe \u00e7evirip\r\n&nbsp;\/\/ C\u00fcmlemizin sonuna ekliyoruz\u2026\r\n&nbsp;for I := Low(Value) to High(Value)\r\n&nbsp; do Cumle := Cumle + VarToStr( Value[I] ) + ' ';\r\n&nbsp;Result := Self;\r\nend;\r\n\r\nfunction TKelimeler.OzNitelik(Value: Variant): TKelimeler;\r\nbegin\r\n&nbsp;\/\/ S\u0131n\u0131f\u0131m\u0131za bir \u00f6znitelik eklemi\u015ftik. Bu, bizim \u201cEkle\u201d fonksiyonumuzu\r\n&nbsp;\/\/ daha da k\u0131saltmam\u0131za hizmet ediyor asl\u0131nda. Konudan uzakla\u015fmamak ad\u0131na\r\n&nbsp;\/\/ \u00d6zNitelikler ba\u015fka bir makalenin konusu oldu\u011fu i\u00e7in burada de\u011finmiyorum.\r\n&nbsp;Result := Self.Ekle( Value );\r\nend;\r\n\r\nfunction TKelimeler.Parantez(Value: TKelimeler; Yoket: Boolean = TRUE): TKelimeler;\r\nbegin\r\n&nbsp;\/\/ \u0130\u00e7 i\u00e7e c\u00fcmleler kurabilmek i\u00e7in yine s\u0131n\u0131f\u0131m\u0131z\u0131n bir kopyas\u0131n\u0131 kullan\u0131yoruz.\r\n&nbsp;Cumle := Cumle + '(' + Value.Cumle.Trim + ')';\r\n\r\n&nbsp;\/\/ Zincir s\u0131ras\u0131nda \u00fcretilen kopyay\u0131 MEMORY LEAK olu\u015fmamas\u0131 i\u00e7in yok etmek zorunday\u0131z...\r\n&nbsp;if Yoket then FreeAndNil(Value);\r\n\r\n&nbsp;Result := Self;\r\nend;\r\n\r\nend.\r\n<\/code><\/pre>\n<p>Gelelim, bu yap\u0131n\u0131n nas\u0131l kullan\u0131ld\u0131\u011f\u0131na. \u00d6nce en yal\u0131n haliyle bir \u00f6rnekleme yapal\u0131m, ard\u0131ndan di\u011fer karma\u015f\u0131k \u00f6rneklere ge\u00e7eriz;<\/p>\n<pre><code>var\r\n&nbsp;Replik: TKelimeler;\r\nbegin\r\n&nbsp;try\r\n&nbsp; &nbsp;Replik :=Yeni\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;. Ekle('Ali').Ekle('topu').Ekle('tut')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;\r\n&nbsp; &nbsp;Memo1.Lines.Text := Replik.Cumle;\r\n&nbsp;finally\r\n&nbsp; &nbsp;FreeAndNil(Replik);\r\n&nbsp;end;\r\nend;\r\n<\/code><\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere bir s\u00fcr\u00fc \u201cEkle\u201d fonksiyonu kulland\u0131k ve o kadar da sadeymi\u015f gibi durmuyor. Bu \u00f6rne\u011fi biraz daha sadele\u015ftirmekte yarar var, \u015f\u00f6yle yapsak nas\u0131l olurdu;<\/p>\n<pre><code>Replik :=Yeni ['Ali']['topu']['tut'] ;<\/code><\/pre>\n<p>Bir \u00f6ncekine nazaran daha basit bir \u00f6rnek olmu\u015f oldu. Peki bu c\u00fcmleye parantez i\u00e7inde ba\u015fka bir c\u00fcmle eklemek istesek ne yapard\u0131k? \u015e\u00f6yle;<\/p>\n<pre><code>Replik :=Yeni['Ali']['topu']['tut']\r\n&nbsp; &nbsp; &nbsp; &nbsp;.Parantez( Yeni ['Kalemi'] ['B\u0131rakma'] [10] [\u2018kalem\u2019] [\u2018getir\u2019] ) ;<\/code><\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere nesnemizi recursive bir bi\u00e7imde i\u00e7 i\u00e7e \u00e7a\u011f\u0131rarak okunabilirli\u011fi hem bozmam\u0131\u015f hem de mevcut bir c\u00fcmlenin i\u00e7ine ba\u015fka bir c\u00fcmleyi ekleyebilmi\u015f olduk.<\/p>\n<p>Farkl\u0131 veri tiplerinin zincirleme bir reaksiyon i\u00e7inde nas\u0131l kullan\u0131ld\u0131\u011f\u0131na dair bir \u00f6rnek te\u015fkil etmesi a\u00e7\u0131s\u0131ndan a\u015fa\u011f\u0131daki kodu inceleyebilirsiniz. Sizin de fark edebilece\u011finiz gibi bir \u00e7ok parametre asl\u0131nda birbirine benzer \u015fekilde kullan\u0131labilmi\u015f. Bir ekle fonksiyonuyla kelime baz\u0131nda ekleme yap\u0131lm\u0131\u015f, bir variant array arac\u0131l\u0131\u011f\u0131yla yine ekle fonksiyonu i\u00e7inde bir s\u00fcr\u00fc kelime ve say\u0131 tan\u0131mlanabilmi\u015f, hatta TDateTime tipinde tarih verileri bile eklenmi\u015f. Normalde a\u015fa\u011f\u0131daki kodun \u00fcretece\u011fi veriyi kodlayacak bir kod yazmak istesek klasik y\u00f6ntemlerle bu daha uzun olur, arada bir \u00e7ok toplama i\u015flemi yapmam\u0131z gerekebilirdi.<\/p>\n<pre><code>var\r\n&nbsp;Replik: TKelimeler;\r\nbegin\r\n&nbsp;try\r\n&nbsp; &nbsp;Replik :=Yeni\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle( ['\"','Bazen', 'daha', 'y\u00fcr\u00fcmeyi', '\u00f6\u011frenmeden', 'ko\u015fmak', 'gerekebilir','\"']).enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle('Veya').enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;['\"']['Bazen']['daha']['y\u00fcr\u00fcmeyi']['\u00f6\u011frenmeden']['ko\u015fmak']['gerekebilir']['\"'].enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle('\u00c7al\u0131\u015ft\u0131r').Ekle('\u015funu').Ekle('Jarvis!').enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Parantez( Yeni ['Demir'] ['Adam'] [1] ).enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle( 'VEYA \u015e\u00d6YLE B\u0130R \u00d6RNEK VEREL\u0130M' ).enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Parantez( Yeni.Ekle('Demir').Ekle('Adam').Ekle(1) ).enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle( ['Replik Zaman\u0131 =', EncodeTime(1,1,30,0)] ).enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.Ekle( 'Filmin Vizyon Tarihi =' )[EncodeDate(2008,5,2)].enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.enter\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;\r\n&nbsp; &nbsp;Memo1.Lines.Text := Replik.Cumle;\r\n&nbsp;finally\r\n&nbsp; &nbsp;FreeAndNil(Replik);\r\n&nbsp;end;\r\nend;\r\n<\/code><\/pre>\n<p><b>Dezavantajl\u0131 Oldu\u011fu Durumlar<\/b><\/p>\n<p>Her g\u00fczelin bir kusuru vard\u0131r derler, do\u011fru, Fluent Interface\u2019nin de kendine \u00f6zg\u00fc kusurlar\u0131 var. San\u0131r\u0131m bunlar\u0131n kusur mu yoksa nimet mi oldu\u011funa karar vermek, olaya hangi pencereden bakt\u0131\u011f\u0131n\u0131zla ilgili, kimisi bunlar\u0131 bir kan davas\u0131 sebebi olarak g\u00f6r\u00fcr, kimisi ise bir ho\u015fg\u00f6r\u00fc kayna\u011f\u0131 olarak bakar, dolay\u0131s\u0131yla bunun takdiri sizin. Gelelim g\u00fczelimizin kusurlar\u0131na.<\/p>\n<ul>\n<li>Derleyici Sorunlar\u0131; TObjects ve t\u00fcrevlerinden ziyade, Interface\u2019leri kullan\u0131yorsan\u0131z zincirdeki her \u00e7a\u011fr\u0131 ayn\u0131 Interface her seferinde geri d\u00f6nse bile Referance Count y\u0131\u011f\u0131lmas\u0131na sebep olacakt\u0131r. Derleyicinin bunu tespit etmesinin bir yolu oldu\u011funu d\u00fc\u015f\u00fcnm\u00fcyorum (En az\u0131ndan hen\u00fcz ben ke\u015ffedemedim) O nedenle Fluent Interface tan\u0131mlarken bir Interface\u2019den miras al\u0131n\u0131yorsa (makinan\u0131n belle\u011finde) daha karma\u015f\u0131k bir y\u0131\u011f\u0131n i\u00e7eren daha b\u00fcy\u00fck bir kod k\u00fcmesi \u00fcretilmi\u015f olacakt\u0131r. O nedenle bu t\u00fcr tasar\u0131mlarda Interface kullanmay\u0131 iki kere d\u00fc\u015f\u00fcnmek gerekir\u2026<\/li>\n<li>Hata Ay\u0131klama Sorunlar\u0131; Fluent Interface kullan\u0131m\u0131n\u0131z s\u0131ras\u0131nda zincirin herhangi bir halkas\u0131nda hata olu\u015ftu\u011funda Derleyici bunu bir b\u00fct\u00fcn olarak g\u00f6rd\u00fc\u011f\u00fc i\u00e7in, hatan\u0131n nereden kaynakland\u0131\u011f\u0131n\u0131 tespit etmeniz ger\u00e7ekten \u00e7ok zaman al\u0131r. E\u011fer hatal\u0131 bir metod birden \u00e7ok kez zincir i\u00e7inde kullan\u0131lm\u0131\u015fsa debug yapmak zorla\u015f\u0131r.<\/li>\n<li>Kod Bi\u00e7imlendirme Sorunu; Delphi\u2019nin \u201cFormat Source\u201d i\u015flevi, Fluent Interface kullan\u0131lm\u0131\u015f bir zinciri bi\u00e7imlendirme a\u00e7\u0131s\u0131ndan bir b\u00fct\u00fcn olarak g\u00f6rd\u00fc\u011f\u00fc i\u00e7in bunu alg\u0131layamaz. Bunun tek \u00e7\u00f6z\u00fcm\u00fc sizin bu hizalamalar\u0131 el ile yapman\u0131zd\u0131r.<\/li>\n<\/ul>\n<p>Art\u0131k s\u00f6z\u00fcm\u00fcz\u00fc tutma vakti geldi.<\/p>\n<p><b>XML Generator<\/b><\/p>\n<p>Makalenin ba\u015f\u0131nda XML kodu \u00fcreten bir \u00f6rnek Delphi kodu g\u00f6stermi\u015f ve bunun kaynak kodunu payla\u015faca\u011f\u0131m\u0131z\u0131 belirtmi\u015ftik. Basit ve \u201cANLA\u015eILIR\u201d bir \u015fekilde XML kodu \u00fcretmek eminin ki hepimizin ortak iste\u011fidir. \u0130\u015fte kodlar;<\/p>\n<pre><code>{*******************************************************}\r\n{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\r\n{ &nbsp; &nbsp; &nbsp; Fluent XML Class &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}\r\n{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\r\n{ &nbsp; &nbsp; &nbsp; Copyright \u00a9 2017 U\u011fur PARLAYAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}\r\n{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ugurparlayan@gmail.com &nbsp; &nbsp; &nbsp; &nbsp; }\r\n{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\r\n{*******************************************************}\r\n\r\nunit XML2_;\r\n\r\ninterface\r\n\r\nuses\r\n&nbsp; System.SysUtils, System.StrUtils, System.Variants, System.Classes, Vcl.Dialogs;\r\n\r\ntype\r\n&nbsp; TVarArray = array of Variant;\r\n&nbsp; TVarArrayHelper = record helper for TVarArray\r\n&nbsp; &nbsp; public\r\n&nbsp; &nbsp; &nbsp; function Ayracli(aAyrac: String): String;\r\n&nbsp; end;\r\n&nbsp; TEncodingHelper = class Helper for TEncoding\r\n&nbsp; &nbsp; public\r\n&nbsp; &nbsp; &nbsp; function AsEncoderName: String;\r\n&nbsp; end;\r\n&nbsp; TXML2 = class\r\n&nbsp; &nbsp; private\r\n&nbsp; &nbsp; &nbsp; _Version &nbsp; &nbsp;: Double;\r\n&nbsp; &nbsp; &nbsp; _Encoding &nbsp; : TEncoding;\r\n&nbsp; &nbsp; &nbsp; _NameSpace &nbsp;: string;\r\n&nbsp; &nbsp; &nbsp; _Source &nbsp; &nbsp; : String;\r\n&nbsp; &nbsp; strict private\r\n&nbsp; &nbsp; &nbsp; function _if(aKosul: Boolean; aTrue, aFalse: String): String;\r\n&nbsp; &nbsp; &nbsp; function _f(const aFormat: string; const Args: array of const): string;\r\n&nbsp; &nbsp; &nbsp; function _NS: String;\r\n&nbsp; &nbsp; public\r\n&nbsp; &nbsp; &nbsp; function AsString: String; \/\/ Bu noktada zincir k\u0131r\u0131l\u0131r...\r\n&nbsp; &nbsp; &nbsp; function Version(Value: Double): TXML2;\r\n&nbsp; &nbsp; &nbsp; function Encoding(Value: TEncoding): TXML2;\r\n&nbsp; &nbsp; &nbsp; function NameSpace(Value: String): TXML2;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string; aValue: Variant): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string; aSubNode: TXML2): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string; aAttributes: TVarArray): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string; aAttributes: TVarArray; aValue: Variant): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function Add(aNode: string; aAttributes: TVarArray; aSubNode: TXML2): TXML2; overload;\r\n&nbsp; &nbsp; &nbsp; function SaveToFile(aFileName: TFileName): TXML2;\r\n&nbsp; end;\r\n&nbsp; function New: TXML2; overload;\r\n\r\nimplementation\r\n\r\nfunction New: TXML2;\r\nbegin\r\n&nbsp; Result := TXML2.Create;\r\nend;\r\n\r\n{ TXML2 }\r\n\r\nfunction TXML2.AsString: String;\r\nvar\r\n&nbsp; Tmp: String;\r\n&nbsp; FS: TFormatSettings;\r\nbegin\r\n&nbsp; FS := FormatSettings;\r\n&nbsp; FormatSettings.DecimalSeparator := '.';\r\n&nbsp; Tmp := _Encoding.AsEncoderName;\r\n&nbsp; if (Pos( '<!--?xml',_Source,1) &lt;= 0) then begin\r\n\u00a0 \u00a0 \u00a0 _Source := _if( ((_Version &lt;&gt; 0) or (Tmp.IsEmpty = False))\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 , _f ( '&lt;?xml%s%s?-->',\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[ _if(_Version &lt;&gt; 0, _f(' version=\"%s\"', [ formatfloat('0.0',_Version)]), '')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;, _if(Tmp.IsEmpty = False, _f(' encoding=\"%s\"', [Tmp]), '')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;])\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , '')\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+ _Source\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;\r\n&nbsp; end;\r\n&nbsp; FormatSettings := FS;\r\n&nbsp; Result := StringReplace(_Source, '&gt;&lt;', '&gt;'#13#10'&lt;', [rfReplaceAll, rfIgnoreCase]); \/\/ CDATA i\u00e7inde ge\u00e7erse s\u0131k\u0131nt\u0131 olabilir...\r\nend;\r\n\r\nfunction TXML2.Version(Value: Double): TXML2;\r\nbegin\r\n&nbsp; _Version := Value;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.Encoding(Value: TEncoding): TXML2;\r\nbegin\r\n&nbsp; _Encoding := Value;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.NameSpace(Value: String): TXML2;\r\nbegin\r\n&nbsp; _NameSpace := Value.Trim;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string): TXML2;\r\nbegin\r\n&nbsp; _Source := _Source + _f('&lt;%s\/&gt;', [aNode.Trim]) ;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string; aValue: Variant): TXML2;\r\nbegin\r\n&nbsp; _Source := _Source + _f('&lt;%0:s%1:s&gt;%2:s&lt;\/%0:s%1:s&gt;', [_NS, aNode.Trim, VarToStr(aValue).Trim]) ;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string; aSubNode: TXML2): TXML2;\r\nvar\r\n&nbsp; Tmp: Variant;\r\nbegin\r\n&nbsp; if (Assigned(aSubNode) = TRUE) then begin\r\n&nbsp; &nbsp; &nbsp; Tmp := aSubNode.AsString;\r\n&nbsp; &nbsp; &nbsp; FreeAndNil(aSubNode);\r\n&nbsp; &nbsp; &nbsp; Result := Self.Add(aNode, Tmp);\r\n&nbsp; end else begin\r\n&nbsp; &nbsp; &nbsp; Result := Self;\r\n&nbsp; end;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string; aAttributes: TVarArray; aValue: Variant): TXML2;\r\nvar\r\n&nbsp; Tmp: String;\r\nbegin\r\n&nbsp; Tmp := aAttributes.Ayracli(' ').Trim;\r\n&nbsp; _Source := _Source\r\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+ _f('&lt;%0:s%1:s%2:s&gt;%3:s&lt;\/%0:s%1:s&gt;', [_NS, aNode.Trim, _if(Tmp.IsEmpty = True, '', ' ' + Tmp), VarToStr(aValue).Trim]) ;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string; aAttributes: TVarArray; aSubNode: TXML2): TXML2;\r\nvar\r\n&nbsp; Tmp: Variant;\r\nbegin\r\n&nbsp; if (Assigned(aSubNode) = TRUE) then begin\r\n&nbsp; &nbsp; &nbsp; Tmp := aSubNode.AsString;\r\n&nbsp; &nbsp; &nbsp; FreeAndNil(aSubNode);\r\n&nbsp; &nbsp; &nbsp; Result := Self.Add(aNode, aAttributes, Tmp);\r\n&nbsp; end else begin\r\n&nbsp; &nbsp; &nbsp; Result := Self;\r\n&nbsp; end;\r\nend;\r\n\r\nfunction TXML2.Add(aNode: string; aAttributes: TVarArray): TXML2;\r\nvar\r\n&nbsp; Tmp: String;\r\nbegin\r\n&nbsp; Tmp := aAttributes.Ayracli(' ').Trim;\r\n&nbsp; _Source := _Source + _f('&lt;%0:s%1:s%2:s\/&gt;', [_NS, aNode.Trim, _if(Tmp.IsEmpty = True, '', ' ' + Tmp)]) ;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\nfunction TXML2._f(const aFormat: string; const Args: array of const): string;\r\nbegin\r\n&nbsp; Result := Format(aFormat, Args);\r\nend;\r\n\r\nfunction TXML2._if(aKosul: Boolean; aTrue, aFalse: String): String;\r\nbegin\r\n&nbsp; if (aKosul = TRUE) then Result := aTrue else Result := aFalse;\r\nend;\r\n\r\nfunction TXML2._NS: String;\r\nbegin\r\n&nbsp; Result := _if( (_NameSpace.Trim.IsEmpty = True), '', _NameSpace.Trim+':');\r\nend;\r\n\r\nfunction TXML2.SaveToFile(aFileName: TFileName): TXML2;\r\nvar\r\n&nbsp; Dosya : TStreamWriter;\r\nbegin\r\n&nbsp; if (directoryExists(ExtractFileDir(aFileName), True) = TRUE) then begin\r\n&nbsp; &nbsp; &nbsp; try\r\n&nbsp; &nbsp; &nbsp; &nbsp; Dosya := TStreamWriter.Create(aFileName, False, TEncoding.UTF8);\r\n&nbsp; &nbsp; &nbsp; &nbsp; Dosya.Write(Self.AsString);\r\n&nbsp; &nbsp; &nbsp; &nbsp; Dosya.Close;\r\n&nbsp; &nbsp; &nbsp; finally\r\n&nbsp; &nbsp; &nbsp; &nbsp; FreeAndNil(Dosya);\r\n&nbsp; &nbsp; &nbsp; end;\r\n&nbsp; end else begin\r\n&nbsp; &nbsp; &nbsp; ShowMessage('Dosya adresinde belirtilen klas\u00f6r yok');\r\n&nbsp; end;\r\n&nbsp; Result := Self;\r\nend;\r\n\r\n{ TVarArrayHelper }\r\n\r\nfunction TVarArrayHelper.Ayracli(aAyrac: String): String;\r\nvar\r\n&nbsp;I: Integer;\r\nbegin\r\n&nbsp;for I := Low(Self) to High(Self)\r\n&nbsp; do if &nbsp;(I &lt; High(Self) )\r\n&nbsp; &nbsp; &nbsp;then Result := Result + VarToStrDef(Self[I], '').Trim + aAyrac\r\n&nbsp; &nbsp; &nbsp;else Result := Result + VarToStrDef(Self[I], '').Trim;\r\nend;\r\n\r\n{ TEncodingHelper }\r\n\r\nfunction TEncodingHelper.AsEncoderName: String;\r\nbegin\r\n&nbsp; {---Kaynaklar-----------------------------------------------------------------------}\r\n&nbsp; { https:\/\/docs.microsoft.com\/en-us\/dotnet\/standard\/base-types\/character-encoding &nbsp; &nbsp;}\r\n&nbsp; { http:\/\/www.iana.org\/assignments\/character-sets\/character-sets.xhtml &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }\r\n&nbsp; {-----------------------------------------------------------------------------------}\r\n&nbsp; if (Self = TEncoding.ANSI) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; then Result := 'ANSI' &nbsp; &nbsp; &nbsp; &nbsp; else\r\n&nbsp; if (Self = TEncoding.ASCII) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then Result := 'ASCII' &nbsp; &nbsp; &nbsp; &nbsp;else\r\n&nbsp; if (Self = TEncoding.UTF7) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; then Result := 'UTF-7' &nbsp; &nbsp; &nbsp; &nbsp;else\r\n&nbsp; if (Self = TEncoding.UTF8) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; then Result := 'UTF-8' &nbsp; &nbsp; &nbsp; &nbsp;else\r\n&nbsp; if (Self = TEncoding.Unicode) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then Result := 'UTF-16' &nbsp; &nbsp; &nbsp; else\r\n&nbsp; if (Self = TEncoding.BigEndianUnicode) then Result := 'UTF-16BE' &nbsp; &nbsp; else\r\n&nbsp; if (Self = TEncoding.Default) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;then Result := 'Windows-1254' else\r\n&nbsp; Result := '';\r\nend;\r\n\r\nend.<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Bir XML belgesini t\u0131pk\u0131 a\u015fa\u011f\u0131daki gibi \u00e7ok sade ve \u201cANLA\u015eILIR\u201d bir \u015fekilde olu\u015fturabilseydik daha iyi olmaz m\u0131yd\u0131?<\/p>\n","protected":false},"author":1,"featured_media":264,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[4,35,39,36],"class_list":["post-174","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-delphi","tag-design-patterns","tag-fluent","tag-tasarim-desenleri"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=174"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/174\/revisions"}],"predecessor-version":[{"id":181,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/174\/revisions\/181"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/media\/264"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=174"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}