├── code-smells ├── other-smells.md ├── change-preventers.md ├── couplers.md ├── object-orientation-abusers.md ├── dispensables.md └── bloaters.md ├── introduction.md ├── refactoring-techniques ├── moving-features-between-objects.md ├── simplifying-conditional-expressions.md ├── composing-methods.md ├── dealing-with-generalization.md └── simplifying-method-calls.md └── README.md /code-smells/other-smells.md: -------------------------------------------------------------------------------- 1 | # Diğer Kokular (Other Smells) 2 | 3 | Aşağıda herhangi bir geniş kategoriye girmeyen kokular bulunmaktadır. 4 | 5 | ## 1️⃣ Tamamlanmamış Kütüphane Sınıfı (Incomplete Library Class) 6 | 7 | **🤢 Belirti ve Semptomlar** 8 | 9 | Er ya da geç kütüphaneler kullanıcı ihtiyaçlarını karşılamayı bırakır. Sorunun tek çözümü, kitaplığı değiştirmek olacaktır. Ancak kitaplık salt okunur olduğundan dolayı bu durum da çoğu zaman imkansızdır. Böyle bir durumda soru işaretleri oluşmaya başlar. 10 | 11 | ![](https://refactoring.guru/images/refactoring/content/smells/incomplete-library-class-01-2x.png) 12 | 13 | **🤒 Sorunun Nedenleri** 14 | 15 | Kütüphanenin yazarı ihtiyacınız olan özellikleri sağlamadı veya bunları uygulamayı reddettiği durumlarda bu sorunla karşılaşılabilir. 16 | 17 | **💊 Tedavi** 18 | 19 | - Bir kütüphane sınıfına birkaç yöntem tanıtmak için **Introduce Foreign Method** tekniği kullanılabilir. 20 | 21 | - Sınıf kitaplığında büyük değişiklikler için **Introduce Local Extension** yöntemini kullanabilirsiniz. 22 | 23 | **💰 Hesaplaşma** 24 | 25 | - Kod tekrarını azaltır (kendi kitaplığınızı sıfırdan oluşturmak yerine, mevcut kitaplığınızı biraz düzenleme ile yine de kullanabilirsiniz). 26 | 27 | ![](https://refactoring.guru/images/refactoring/content/smells/incomplete-library-class-02-2x.png) 28 | 29 | **🤫 Ne Zaman Yok Sayılmalı?** 30 | 31 | Kitaplıkta yapılan değişiklikler kodda değişiklik içeriyorsa, kitaplığı genişletmek ek iş üretebilir. Böyle bir durumda, bu kokuyu yoksayabilirsiniz. 32 | 33 | -------------------------------------------------------------------------------- /code-smells/change-preventers.md: -------------------------------------------------------------------------------- 1 | # Change Preventers (Önleyicileri Değiştirme) 2 | 3 | Bu başlık altındaki kokular, kodunuzun bir yerinde bir şeyi değiştirmeniz gerekiyorsa, diğer yerlerde de birçok değişiklik yapmanız gerektiği anlamına gelir. Sonuç olarak program geliştirme çok daha karmaşık ve maliyetli hale gelir. 4 | 5 | ## 1️⃣ Iraksak Değişim (Divergent Change) 6 | 7 | Divergent Change, Shotgun Surgery'e benzese de aslında tam tersi bir kokudur. Iraksak Değişim (Divergent Change), tek bir sınıfta birçok değişikliğin yapılmasıdır. Shotgun Surgery ise, birden fazla sınıfta aynı anda tek bir değişiklik yapılması anlamına gelir. 8 | 9 | **🤢 Belirti ve Semptomlar** 10 | 11 | Bir sınıfta değişiklik yaptığınızda, ilgisiz birçok yöntemi değiştirmek zorunda kalabilirsiniz. Örneğin, yeni bir ürün türü eklerken ürünleri bulma, sergileme ve sipariş etme yöntemlerini değiştirmeniz gerekir. Böyle bir durumla karşı karşıya kaldığınızda soru işaretleri oluşmalıdır. 12 | 13 | ![](https://refactoring.guru/images/refactoring/content/smells/divergent-change-01-2x.png) 14 | 15 | 16 | **🤒 Sorunun Nedenleri** 17 | 18 | Çoğu zaman bu farklı değişiklikler zayıf program yapısından veya kopya yapıştır geliştirmelerden kaynaklanmaktadır. 19 | 20 | **💊 Tedavi** 21 | 22 | - Sınıfın davranışını **Extract Class** tekniğini kullanarak parçalara bölebilirsiniz. 23 | 24 | - Farklı sınıfların aynı davranışa sahip olması durumunda, sınıfları miras yoluyla birleştirmek isteyebilirsiniz (**Extract Superclass** ve **Extract Subclass**). 25 | 26 | 27 | **💰 Hesaplaşma** 28 | 29 | - Kod organizasyonunu geliştirir. 30 | - Kod tekrarını azaltır. 31 | - Desteği basitleştirir. 32 | 33 | 34 | ## 2️⃣ Shotgun Surgery 35 | 36 | **🤢 Belirti ve Semptomlar** 37 | 38 | Herhangi bir değişiklik yaptığınızda, birçok farklı sınıfta birçok küçük değişiklik yapmanızı gerekebilir. Bu tarz durumlarda soru işaretleriniz oluşmalıdır. 39 | 40 | ![](https://refactoring.guru/images/refactoring/content/smells/shotgun-surgery-01-2x.png) 41 | 42 | **🤒 Sorunun Nedenleri** 43 | 44 | Tek bir sorumluluk çok sayıda sınıfa dağıtıldığı durumlarda ortaya çıkar. Bu, Iraksak Değişim (Divergent Change.) tekniğini aşırı agrasif bir şekilde kullanılmasından sonra gerçekleşebilir. 45 | 46 | ![](![](https://refactoring.guru/images/refactoring/content/smells/shotgun-surgery-02-2x.png) 47 | 48 | **💊 Tedavi** 49 | 50 | - Sınıfın davranışını **Extract Class** tekniğini kullanarak parçalara ayırabilirsiniz. 51 | 52 | - Farklı sınıfların aynı davranışa sahip olması durumunda, sınıfları miras yoluyla birleştirmek isteyebilirsiniz (**Extract Superclass** ve **Extract Subclass**). 53 | 54 | 55 | 56 | ![](https://refactoring.guru/images/refactoring/content/smells/shotgun-surgery-03-2x.png) 57 | 58 | **💰 Hesaplaşma** 59 | 60 | - Daha iyi organizasyon. 61 | - Daha az kod kopyası. 62 | - Daha kolay bakım. 63 | 64 | ## 3️⃣ Parallel Inheritance Hierarchies 65 | 66 | **🤢 Belirti ve Semptomlar** 67 | 68 | Bir sınıf için bir alt sınıf oluşturduğunuzda, kendinizi başka bir sınıf için bir alt sınıf yaratmaya ihtiyaç duyarken bulabilirsiniz. Böyle bir durumla karşılaştığınızda soru işaretleri oluşmalıdır. 69 | 70 | ![](https://refactoring.guru/images/refactoring/content/smells/parallel-inheritance-hierarchies-01-2x.png) 71 | 72 | **🤒 Sorunun Nedenleri** 73 | 74 | Hiyerarşi küçük kaldığı sürece her şey yolundadır. Ancak proje/program geliştiçe bu hiyeraşi büyüyecektir. Yeni sınıfların eklenmesiyle değişiklik yapmak giderek zorlaşır. 75 | 76 | **💊 Tedavi** 77 | 78 | - İki adımda paralel sınıf hiyerarşilerini tekrarsız hale getirebilirsiniz. Bu adımlar şu şekildedir: 79 | - İlk olarak, bir hiyerarşinin örneklerinin başka bir hiyerarşinin örneklerine (instance) gönderme (referans) yapmasını sağlayın. 80 | - Sonra, **Move Method** ve **Move Field** tekniklerini kullanarak atıfta bulunan sınıftaki hiyerarşiyi kaldırın. 81 | 82 | 83 | **💰 Hesaplaşma** 84 | 85 | - Kod tekrarını azaltır. 86 | - Kodun organizasyonunu geliştirebilir. 87 | 88 | ![](https://refactoring.guru/images/refactoring/content/smells/parallel-inheritance-hierarchies-02-2x.png) 89 | 90 | 91 | **🤫 Ne Zaman Yok Sayılmalı?** 92 | 93 | Bazen paralel sınıf hiyerarşilerine sahip olmak, program mimarisinde daha da büyük karışıklıkları önlemenin bir yoludur. Hiyerarşileri tekilleştirme girişimlerinizin daha da kirli kod ürettiğini fark edebilirsiniz. Böyle bir durumda dışarı çıkın, temiz hava alın ve geri döndüğünüzde tüm değişikliklerinizi geri alın ve bu koda alışın. 94 | 95 | 96 | -------------------------------------------------------------------------------- /code-smells/couplers.md: -------------------------------------------------------------------------------- 1 | # Bağlayıcılar (Couplers) 2 | 3 | Bu tür kokular sınıflar arasında fazla bağlantıya neden olabilir veya bağlantının aşırı derecede delege etmeye çalıştığında ortaya çıkar. Yani bu durum şu iki şekilde orytaya çıkabilir: 4 | - Bir sistemdeki farklı parçalar arasındaki ilişkilerin ya çok sıkı olduğu ve bu durumun da kodun bakımını ve değişiklik yapmayı zorlaştırdığı, - İlişkilerin çok zayıf olduğu ve bu durumun da kodun karmaşık hale gelmesine neden olur. 5 | 6 | ## 1️⃣ Özellik Kıskançlığı (Feature Envy) 7 | 8 | **🤢 Belirti ve Semptomlar** 9 | 10 | Bir yöntem kendi verisinden çok başka bir nesnenin verisine erişiyorsa soru işaretleri oluşmalıdır. 11 | 12 | ![](https://refactoring.guru/images/refactoring/content/smells/feature-envy-01-2x.png) 13 | 14 | **🤒 Sorunun Nedenleri** 15 | 16 | Bu koku, alanlar bir veri sınıfına (data class) taşındıktan sonra ortaya çıkabilir. Eğer durum buysa veriler üzerindeki işlemleri de bu sınıfa taşımak isteyebilirsiniz. 17 | 18 | **💊 Tedavi** 19 | 20 | Temel bir kural olarak, eğer bir şeyler aynı anda değişiyorsa, onları aynı yerde tutmalısınız. İstisnaları olsa da genellikle bu veriyi kullanan fonksiyonlar birlikte değiştirilir. 21 | 22 | - Bir metodun açıkça başka bir yere taşınması gerekiyorsa **Move Method** tekniğini kullanın. 23 | 24 | - Eğer bir metodun sadece bir kısmı başka bir nesnenin verisine erişiyorsa, bu kısmı taşımak için **Extract Method** tekniğini kullanın. 25 | 26 | - Bir metodun birkaç başka sınıftan fonksiyonları kullandığı durumlarda, önce kullanılan verinin çoğunu içeren sınıfı belirleyin. Sonra metodunuzu bu sınıfa diğer verilerle birlikte yerleştirin. Alternatif olarak, metodu farklı sınıflardaki farklı yerlere yerleştirilebilecek birkaç parçaya ayırmak için **Extract Method** tekniğini de kullanabilirsiniz. 27 | 28 | ![](https://refactoring.guru/images/refactoring/content/smells/feature-envy-02-2x.png) 29 | 30 | 31 | **💰 Hesaplaşma** 32 | 33 | - Daha az kod kopyası (duplication). 34 | 35 | - Daha iyi kod organizasyonu. 36 | 37 | ![](https://refactoring.guru/images/refactoring/content/smells/feature-envy-03-2x.png) 38 | 39 | **🤫 Ne Zaman Yok Sayılmalı?** 40 | 41 | Bazen davranışlar, verileri tutan sınıftan kasıtlı olarak ayrı tutulur. Bunun genel avantajı davranışı dinamik olarak değiştirebilme yeteneğidir (bkz. Strateji (Strategy), Ziyaretçi (Visitor) ve diğer tasarım desenleri). 42 | 43 | ## 2️⃣ Uygunsuz Yakınlık (Inappropriate Intimacy) 44 | 45 | **🤢 Belirti ve Semptomlar** 46 | 47 | Bir sınıf başka bir sınıfın dahili (internal) alanlarını ve yöntemlerini kullandığı durumlarda soru işaretleri oluşmalıdır. 48 | 49 | ![](https://refactoring.guru/images/refactoring/content/smells/inappropriate-intimacy-01-2x.png) 50 | 51 | **🤒 Sorunun Nedenleri** 52 | 53 | Birlikte çok fazla zaman geçiren sınıfları yakından inceleyin. İyi bir sınıf yapısında, sınıflar birbirleri hakkında mümkün olduğunca az bilgiye sahibi olmalıdır. Bu tür sınıfların bakımı ve yeniden kullanımı daha kolaydır. 54 | 55 | **💊 Tedavi** 56 | 57 | - En basit çözüm, bir sınıfın bir kısmını gerçekten ihtiyaç duymadığı bir sınıfa taşımak için **Move Method** ve **Move Field** tekniklerini kullanmaktır. Ancak bu, ilk sınıfın bu parçalara gerçekten ihtiyaç duymadığı durumdlarda işe yaracaktır. 58 | 59 | - Başka bir çözüm, kod ilişkilerini resmi (official) hale getirmek için **Extract Class** ve **Hide Delegate** teknikleri kullanmaktır. 60 | 61 | - Eğer sınıflar karşılıklı bağımlıysa, **Change Bidirectional Association to Unidirectional** tekniği kullanmalısınız. 62 | 63 | - Bu sıkı bağ bir alt sınıf ile üst sınıf arasındaysa, **Replace Delegation with Inheritance** yöntemi düşünülebilir. 64 | 65 | 66 | ![](https://refactoring.guru/images/refactoring/content/smells/inappropriate-intimacy-03-2x.png) 67 | 68 | 69 | **💰 Hesaplaşma** 70 | 71 | - Kod organizasyonunu geliştirir. 72 | - Desteği ve kodun yeniden kullanımını basitleştirir. 73 | 74 | ## 3️⃣ Mesaj Zincirleri (Message Chains) 75 | 76 | **🤢 Belirti ve Semptomlar** 77 | 78 | Kodda şuna benzeyen bir dizi çağrı görüyorsunuz: 79 | 80 | ``` 81 | $a->b()->c()->d() 82 | ``` 83 | 84 | soru işaretleri oluşmaya başlamalıdır. 85 | 86 | ![](https://refactoring.guru/images/refactoring/content/smells/message-chains-01-2x.png) 87 | 88 | **🤒 Sorunun Nedenleri** 89 | 90 | Bir istemci başka bir nesne istediğinde, o nesne başka bir nesne istediğinde vb. bir mesaj zinciri oluşur. Bu zincirler, istemcinin sınıf yapısı boyunca gezinmeye bağımlı olduğu anlamına gelir. Bu ilişkilerdeki herhangi bir değişiklik istemcinin değiştirilmesini gerektirir. 91 | 92 | **💊 Tedavi** 93 | 94 | - Bir mesaj zincirini silmek için **Hide Delegate** yöntemi kullanın. 95 | 96 | - Bazı durumlarda, neden son nesnenin kullanıldığını düşünmek daha iyidir. Belki de bu işlevselliği **Extract Method** yöntemi kullanarak çıkarmak ve **Move Method** yöntemi kullanarak zincirin başına taşımak mantıklı olabilir. 97 | 98 | 99 | ![](https://refactoring.guru/images/refactoring/content/smells/message-chains-02-2x.png) 100 | 101 | **💰 Hesaplaşma** 102 | 103 | - Bir zincirin sınıfları arasındaki bağımlılıkları azaltır. 104 | - Şişirilmiş kod miktarını azaltır. 105 | 106 | ![](https://refactoring.guru/images/refactoring/content/smells/message-chains-03-2x.png) 107 | 108 | **🤫 Ne Zaman Yok Sayılmalı?** 109 | 110 | Aşırı agresif temsilci (delegate) gizleme, işlevselliğin gerçekte nerede gerçekleştiğini görmenin zor olduğu kodlara neden olabilir. Temelde bu durum, Orta Adam (Middle Man) kokusundan da kaçının demenin başka bir yoludur. 111 | 112 | 113 | ## 4️⃣ Orta Adan (Middle Man) 114 | 115 | **🤢 Belirti ve Semptomlar** 116 | 117 | Bir sınıf, işi başka bir sınıfa devrederek yalnızca tek bir eylem gerçekleştiriyorsa, o sınıf neden var? Bu tarz bir soru aklınıza geldiyse, varsa diğer gelecek soru işaretlerine hazır olun. 118 | 119 | ![](https://refactoring.guru/images/refactoring/content/smells/middle-man-01-2x.png) 120 | 121 | **🤒 Sorunun Nedenleri** 122 | 123 | Bu koku, Mesaj Zincirleri yönteminin aşırı agrasif bir şekilde ortadan kaldırılmasının bir sonucu olabilir. 124 | 125 | Diğer durumlarda, bir sınıfın faydalı çalışmasının kademeli olarak diğer sınıflara taşınmasının sonucu olabilir. Sınıf, yetki vermekten başka hiçbir şey yapmayan boş bir kabuk olarak kalır. 126 | 127 | **💊 Tedavi** 128 | 129 | Bir yöntemin sınıflarının çoğu başka bir sınıfa devrediliyorsa **Remove Middle Man** işlemi uygundur. 130 | 131 | 132 | **💰 Hesaplaşma** 133 | 134 | - Daha az hacimli kod sağlar. 135 | 136 | ![](https://refactoring.guru/images/refactoring/content/smells/middle-man-02.png) 137 | 138 | **🤫 Ne Zaman Yok Sayılmalı?** 139 | 140 | Aşağıdaki nedenlerden dolayı oluşturulan orta adamı silmenizi tavsiye etmem: 141 | 142 | - Sınıflar arası bağımlılıkları önlemek için bir orta adam eklenmiş olabilir. 143 | 144 | - Bazı tasarım desenleri kasıtlı olarak orta adam yaratır (Proxy veya Dekoratör gibi). 145 | 146 | -------------------------------------------------------------------------------- /code-smells/object-orientation-abusers.md: -------------------------------------------------------------------------------- 1 | # Object-Orientation Abusers (Nesne Yönelimini Kötüye Kullanma) 2 | 3 | Aşağıdaki tüm kod kokuları nesne yönelimli programlama (OOP) ilkelerinin eksik veya yanlış uygulanmasından kaynaklanmaktadır. 4 | 5 | ## 1️⃣ Switch Statements 6 | 7 | **🤢 Belirti ve Semptomlar** 8 | 9 | Karmaşık bir `switch` operatörünüz veya `if` ifadeleri diziniz var ise soru işaretleri oluşmalıdır. 10 | 11 | ![](https://refactoring.guru/images/refactoring/content/smells/switch-statements-01-2x.png) 12 | 13 | 14 | **🤒 Sorunun Nedenleri** 15 | 16 | `switch` ve `case` operatörlerinin nispeten nadir kullanımı, nesne yönelimli kodun belirgin özelliklerinden biridir. Genellikle tek bir `switch` için kod, programın farklı yerlerine dağılmış olabilir. Yeni bir koşul eklediğinizde, tüm `switch` kodlarını bulup değiştirmeniz gerekebilir. 17 | 18 | Genel bir düşünce şu kanıdadır; `switch` gördüğünüzde polimorfizmi düşünmelisiniz. 19 | 20 | **💊 Tedavi** 21 | 22 | - `switch`'i izole etmek ve doğru sınıfa koymak için **Extract Method** tekniğini ve ardından **Move Method** tekniği kullanmanız gerekebilir. 23 | 24 | - Eğer bir `switch`, tip koduna (type code) dayanıyorsa, **Replace Type Code with Subclasses** veya **Replace Type Code with State/Strategy** tekniğini kullanın. 25 | 26 | - Miras yapısını belirledikten sonra **Replace Conditional with Polymorphism** tekniğini kullanın. 27 | 28 | - Eğer operatörde çok fazla koşul yoksa ve hepsi farklı parametrelerle aynı metodunu çağırıyorsa, polimorfizm gereksiz olacaktır. Bu durumda, o metodunu **Replace Parameter with Explicit Methods** tekniğini kullanarak birden çok küçük metoda bölebilir ve switch'i buna göre değiştirebilirsiniz. 29 | 30 | - Koşullardan biri `null` ise, **Introduce Null Object** tekniğini kullanın. 31 | 32 | 33 | 34 | **💰 Hesaplaşma** 35 | 36 | Geliştirilmiş kod organizasyonu sunar. 37 | 38 | ![](https://refactoring.guru/images/refactoring/content/smells/switch-statements-02-2x.png) 39 | 40 | **🤫 Ne Zaman Yok Sayılmalı?** 41 | 42 | - Bir switch operatörü basit işlemleri gerçekleştiriyorsa, kod değişikliği yapmaya gerek yoktur. 43 | 44 | - Sıkça switch operatörleri, fabrika tasarım desenleri (**Factory Method** veya **Abstract Factory**) tarafından oluşturulan bir sınıfı seçmek için kullanılır. Bu durumda yok sayılabilir. 45 | 46 | 47 | ## 2️⃣ Temporary Field (Geçici Alan) 48 | 49 | **🤢 Belirti ve Semptomlar** 50 | 51 | Geçici alanlar yalnızca belirli koşullar altında değer alır. Bu koşullar dışında boş kalırlar. 52 | 53 | ![](https://refactoring.guru/images/refactoring/content/smells/temporary-field-01-2x.png) 54 | 55 | **🤒 Sorunun Nedenleri** 56 | 57 | Çoğu zaman, büyük miktarda girdi gerektiren bir algoritmada kullanılmak üzere geçici alanlar oluşturulur. Dolayısıyla programcı, yöntemde çok sayıda parametre oluşturmak yerine sınıfta bu veriler için alanlar oluşturmaya karar verir. Bu alanlar yalnızca algoritmada kullanılır ve geri kalan zamanda kullanılmaz. 58 | 59 | Bu tür bir kodu anlamak zordur. Nesne alanlarında veri görmeyi beklersiniz ancak çeşitli nedenden dolayı bu nesneler neredeyse çoğu zaman boştur. 60 | 61 | ![](![](https://refactoring.guru/images/refactoring/content/smells/temporary-field-02-2x.png) 62 | 63 | **💊 Tedavi** 64 | 65 | - Geçici alanlar ve onlar üzerinde çalışan tüm kodlar **Extract Class** tekniği kullanılarak ayrı bir sınıfa taşınabilir. Başka bir deyişle, bir metod nesnesi oluşturmuş olursunuz ve **Replace Method with Method Object** yöntemini kullanmak ile aynı sonuca ulaşmış olursunuz. 66 | 67 | - **Introduce Null Object** tekniğini kullanın ve geçici alan değerlerini kontrol etmek için kullanılan koşullu kodun yerine entegre edin. 68 | 69 | 70 | ![](https://refactoring.guru/images/refactoring/content/smells/temporary-field-03-2x.png) 71 | 72 | **💰 Hesaplaşma** 73 | 74 | Daha iyi kod okunurluğu ve organizasyonu sağlar. 75 | 76 | ## 3️⃣ Refused Bequest (Reddedilen Miras) 77 | 78 | **🤢 Belirti ve Semptomlar** 79 | 80 | Bir alt sınıf, ebeveynlerinden miras alınan yöntem ve özelliklerin yalnızca bazılarını kullanıyorsa hiyerarşi bozulur. OOP gereği alt sınıf, üst sınıftan aldığı neredeyse tüm işlevleri kullanmalıdır. Gereksiz yöntemler kullanılmadan kalabilir veya yeniden tanımlanabilir, ayrıca hatalar (exceptions) ortaya çıkabilir. Böyle durumlarda soru işaretleri oluşmalıdır. 81 | 82 | ![](https://refactoring.guru/images/refactoring/content/smells/refused-bequest-01-2x.png) 83 | 84 | **🤒 Sorunun Nedenleri** 85 | 86 | Birisi, yalnızca kodu bir üst sınıfta yeniden kullanma arzusuyla sınıflar arasında miras yaratmayı mantıklı bulduğunu düşünün. Ancak üst sınıf ve alt sınıf tamamen farklı bir hale evrildi. Alt sınıf, üst sınıftan miras aldığı birkaç yöntem hariç hiçbir değeri kullanmıyor. 87 | 88 | ![](https://refactoring.guru/images/refactoring/content/smells/refused-bequest-02-2x.png) 89 | 90 | **💊 Tedavi** 91 | 92 | - Eğer mirasın anlam taşımadığı ve alt sınıfın gerçekten üst sınıf ile hiçbir ortak noktasının olmadığı bir durum var ise, **Replace Inheritance with Delegation** tekniği ile lehine mirası ortadan kaldırın. 93 | 94 | - Eğer miras uygunsa, alt sınıfta bulunan gereksiz alanları ve metotları ortadan kaldırın. Alt sınıf tarafından ihtiyaç duyulan tüm değerleri ve metotları üst sınıftan kaldırım, bunları yeni bir üst sınıfa koyun ve her iki sınıfı da ondan miras alacak şekilde ayarlayın (**Extract Superclass**). 95 | 96 | ![](https://refactoring.guru/images/refactoring/content/smells/refused-bequest-03-2x.png) 97 | 98 | **💰 Hesaplaşma** 99 | 100 | Kodun netliğini ve organizasyonunu geliştirir. Artık her ikisinin de 4 bacağı olmasına rağmen, Köpek (`Dog`) sınıfının neden Sandalye (`Chair`) sınıfından miras alındığını merak etmenize gerek kalmayacak! 101 | 102 | ## 4️⃣ Alternative Classes with Different Interfaces (Farklı Arayüzlerle Alternatif Sınıflar) 103 | 104 | **🤢 Belirti ve Semptomlar** 105 | 106 | İki sınıf aynı işlevleri yerine getirmesine rağmen farklı yöntem adlarına sahipse soru işaretleri oluşmalıdır. 107 | 108 | ![](https://refactoring.guru/images/refactoring/content/smells/alternative-classes-with-different-interfaces-01-2x.png) 109 | 110 | **🤒 Sorunun Nedenleri** 111 | 112 | Sınıflardan birini oluşturan programcı muhtemelen işlevsel olarak aynı işlemi yapan eşdeğer bir sınıfın hali hazırda var olduğunu bilmiyordu. Bu yüzden aynı amaca hizmet eden iki metot oluşmuş oldu. 113 | 114 | **💊 Tedavi** 115 | 116 | Sınıfların arayüzünü ortak bir paydada ifade etmeye çalışın: 117 | 118 | - Metodları aynı hale getirmek için **Rename Methods** tekniğini kullanın. 119 | 120 | - Metodların imzasını ve uygulamasını aynı yapmak için **Move Method**, **Add Parameter** ve **Parameterize Method** tekniklerini kullanın. 121 | 122 | - Sınıfların sadece bir kısmı tarafından kullanılan işlevsellik varsa, **Extract Superclass** tekniğini kullanmayı deneyin. Bu durumda, mevcut sınıflar, alt sınıflar haline gelecektir. Böylelikle duplicate yöntem sorunu ortadan kalkar. 123 | 124 | - Hangi tedavi yöntemini kullanacağınızı belirledikten ve uyguladıktan sonra, sınıflardan birini silebilirsiniz. 125 | 126 | **💰 Hesaplaşma** 127 | 128 | - Gereksiz yinelenen kodlardan kurtulursunuz, böylece ortaya çıkan kod az hacimli ve daha temiz olur. 129 | 130 | - Kod daha okunabilir ve anlaşılır hale gelir. Böylelikle artık birinciyle aynı işlevleri yerine getiren ikinci bir sınıfın yaratılmasının nedenini tahmin etmenize gerek yoktur. Çünkü ikinci sınıf çoktan ortadan kalkmış olacaktır! 131 | 132 | ![](https://refactoring.guru/images/refactoring/content/smells/alternative-classes-with-different-interfaces-02-2x.png) 133 | 134 | **🤫 Ne Zaman Yok Sayılmalı?** 135 | 136 | Bazen sınıfları birleştirmek imkansızdır veya anlamsız olacak kadar zordur. Bunun bir örneği, alternatif sınıfların her birinin kendi sınıf sürümüne sahip farklı kitaplıklarda olmasıdır. Böyle bir durumda bu koku yok sayılabilir. 137 | 138 | 139 | -------------------------------------------------------------------------------- /introduction.md: -------------------------------------------------------------------------------- 1 | # Refactoring Nedir? 2 | 3 | ## Temiz Kod (Clean Code) 4 | 5 | Refactoringin ana amacı teknik borçla (technical debt) mücadele etmektir. Refactoring, bir kodda bulunan karışıklığı temiz bir koda ve basit bir tasarıma dönüştürmemize yardımcı olur. 6 | 7 | Bu kısmı cebe koyduk! Peki, herkesin dilinden düşmeyen bu temiz kod nedir? Bazı özelliklerini kısaca saymak gerekirse: 8 | 9 | **🚿 Temiz kod, diğer programcılar için de oldukça nettir.** 10 | 11 | Burada süper karmaşık algoritmalardan bahsetmiyoruz. Yanlış değişken isimlendirmesi, içeriği şişmiş sınıflar ve metotlar, sihirli (magic) sayılar ve değişkenler tüm bunlar kodu kirli ve anlaşılması zor hale getirir. 12 | 13 | ------------ 14 | 15 | **🚿 Temiz kod, tekrarlı kod (duplication) içermez.** 16 | 17 | Birka yerde yinelenen yani tekrarlanan bir kod parçası olduğunu düşünün. Bu tekrarlanan kod üzerinde her değişiklik yapmanız gerektiğinde, bu değişikliği her tekrarlanan kod üzerinde yapmayı ihmal etmemeniz gerekir. Bu durum bilişsel yükü artırır ve projenizin ilerlemesini yavaşlatır. 18 | 19 | ------------ 20 | 21 | **🚿 Temiz kod minimum sayıda sınıf, method, fonskiyon ve değişken içerir.** 22 | 23 | Az kod, aklınızda tutmanız gereken az şey demektir. Az kod, daha az bakım demektir. Az kod, daha az hata demektir. Kod bir yükümdür, kodu kısa ve basit tutmak hem siz hem de projede çalışan diğer yazılımcılar için verimi arttıracaktır. 24 | 25 | ------------ 26 | 27 | **🚿 Temiz kod, tüm testleri geçer.** 28 | 29 | Testlerinizin yalnızca %95'i başarıyla testi geçtiğinde kodunuzda bir sorun olduğunu bilirsiniz. Test kapsamınız %0 olduğunda da yanıldığınızı bilirsiniz. 30 | 31 | ------------ 32 | 33 | **🚿 Temiz kodun bakımı daha kolay ve maliyetsizdir!** 34 | 35 | 36 | ## Teknik Borç (Technical Debt) 37 | 38 | Herkes başlangıçta harika bir kod yazmak için elinden gelenin en iyisini yapar. Projeye zarar vermek amacıyla kasıtlı olarak kirli kod yazan bir programcı olmadığı söylenebilir. Ancak temiz kod ne zaman kirli hale gelir? Geliştirme aşamasında hangi süreçler projedeki temiz kodu bozar? 39 | 40 | Temiz olmayan kodla ilgili **teknik borç** (technical debt) metaforu aslında Ward Cunningham tarafından önerilmiştir. 41 | 42 | Bir bankadan kredi alırsanız, bu size daha hızlı alışveriş yapma imkanı sunar. Alışveriş sürecini hızlandırmak için ekstra (banka faizi) ödeme yaparsınız. Sadece ana parayı değil, aynı zamanda kredi üzerinden bankanın belirlediği ek faizleri de ödemeniz gerekir. Elbette ki, alışverişle birlikte birleşen faiz miktarı toplam gelirinizi aşacak kadar çok olabilir. Bu da borcunuzu tam olarak geri ödemenizi yani borcun tamamını ödemeyi imkansız hale getirir. 43 | 44 | Aynı şey kodda da olabilir. Yeni özellikler için test yazmadan geliştirme sürecini geçici olarak hızlanabilirsiniz. Ancak bu durum, sonunda testler yazarak borcunuzu ödeyene kadar ilerlemenizi her gün parça parça yavaşlatacaktır. 45 | 46 | ### Technical Debt Nedenleri 47 | 48 | **▶️ İş Baskısı** 49 | 50 | Bazen iş koşulları, sizi yeni özellikleri (feature) tamamen bitmeden devreye sokmanıza yani kullanıma sunmaya zorlayabilir.. Bu durumda, projenin tamamlanmamış kısımlarını gizlemek için kod içinde yamalar ve geçici çözümler ortaya kullanırsınız. 51 | 52 | -------- 53 | 54 | **▶️ Teknik Borcun Sonuçlarının Anlaşılmaması** 55 | 56 | Bazen işvereniniz, teknik borcun birikmesiyle birlikte gelişimin hızını düşürdüğü durumu yani **faiz** konseptini anlamayabilir. Bu durum, yönetimin bunun değerini görmemesi nedeniyle, ekip zamanını refaktöre etmeye ayıramaz. 57 | 58 | -------- 59 | 60 | **▶️ Bileşenlerin (Components) Katı Tutarlılığıyla Mücadele Edememek** 61 | 62 | Bu, projenin bireysel modüllerin değil, bir monolit gibi görünmesi durumudur. Bu durumda, projenin bir bölümünde yapılan herhangi bir değişiklik, projenin/kodun diğer kısımları üzerinde etkili olacaktır. Bireysel üye çalışmasını izole etmek zor olduğu için ekip geliştirmesi daha zor hale gelir. 63 | 64 | -------- 65 | 66 | **▶️ Test Eksikliği** 67 | 68 | Anında geri bildirimin eksikliği, geliştiriciyi hızlı ancak riskli çözümler veya geçici çözümlere sürükler. En kötü durumlarda, bu değişiklikler önceden test edilmeden doğrudan production'a yani yayında olan projeye uygulanabilir, dağıtılabilir yani deploy alınabilir. Böyle bir durumda sonuçlar felaket olabilir. Örneğin, masum görünen bir hata düzeltmesi, binlerce müşteriye tuhaf bir test e-postası gönderebilir veya daha da kötüsü, bütün bir veritabanını bozabilir hatta silebilir. 69 | 70 | -------- 71 | 72 | **▶️ Belgeleme Eksikliği** 73 | 74 | Bu, yeni insanların projeye tanıtılmasını yavaşlatır ve projeden önemli kişiler ayrıldığında gelişimi duraklatabilir. 75 | 76 | -------- 77 | 78 | **▶️ Ekip Üyeleri Arasındaki Etkileşim Eksikliği** 79 | 80 | Eğer bilgi tabanı şirket genelinde dağılmamışsa, insanlar süreçler ve projeye ilişkin bilgilerle güncel olmayan bir anlayışla çalışma eğiliminde olabilirler. Bu durum, genç geliştiricilerin mentörleri tarafından yanlış eğitildiğinde daha da kötüleşebilir. 81 | 82 | -------- 83 | 84 | **▶️ Aynı Anda Birkaç Dalda (Branch) Uzun Vadeli Geliştirme** 85 | 86 | Bu, teknik borcun birikmesine yol açabilir ve değişiklikler birleştirildiğinde bu borç artar. İzolasyon içinde yapılan değişiklikler ne kadar fazlaysa, toplam teknik borç o kadar büyük olur. 87 | 88 | -------- 89 | 90 | **▶️ Refaktörün Gecikmesi/Ertelenmesi** 91 | 92 | Projelerin gereksinimleri sürekli olarak değişiyor ve bir noktada kodun bazı kısımlarının eski moda, ağır ve yeni gereksinimlere uyacak şekilde yeniden tasarlanması gerektiği açık hale gelir. 93 | 94 | Öte yandan, projenin programcıları her gün eski parçalarla çalışan yeni kod yazacaklardır. Bu nedenle, refaktör geciktikçe, gelecekte değiştirilmesi gereken alana bağımlı kod parçaları kar topu etkisiyle büyümüş olacaktır. 95 | 96 | -------- 97 | 98 | **▶️ Uyumluluk İzleme Eksikliği** 99 | 100 | Bu, proje üzerinde çalışan herkesin uygun gördüğü şekilde (yani son projeyi yazdığı şekilde) kod yazdığında gerçekleşir. 101 | 102 | -------- 103 | 104 | **▶️ Yetersizlik** 105 | 106 | Bu, geliştiricinin sadece düzgün kod yazmayı bilmediği durumdur. 107 | 108 | 109 | ## Ne Zaman Refactoring Yapılmalı? 110 | 111 | Bu konuda oldukça popüler olan ve takip edilen bir kural vardır. Rule of Three: 112 | 113 |
114 | 115 | ![](https://refactoring.guru/images/refactoring/content/pages/r1.svg) 116 | 117 |
118 | 119 | - Bir şeyi ilk kez yapıyorsanız, hemen yapın. 120 | - Benzer bir şeyi ikinci kez yaptığınızda, tekrarlamak zorunda kaldığınız için utanın ama yine de aynı şeyi yapın. 121 | - Bir şeyi üçüncü kez yaptığınızda refaktör etmeye başlayın. 122 | 123 | ### Yeni Bir Özellik Eklerken 124 | 125 |
126 | 127 | ![](https://refactoring.guru/images/refactoring/content/pages/r2.svg) 128 | 129 |
130 | 131 | - Refaktör, başkalarının kodunu anlamanıza yardımcı olur. Başkalarının kirli koduyla karşı karşıya kalırsanız, önce onu refaktör etmeye çalışın. Temiz kodu anlamak çok daha kolaydır. Bunu sadece kendiniz için değil, sizden sonra kullananlar için de iyileştireceksiniz bunu unutmayın. 132 | 133 | - Refaktör, yeni özellik eklemeyi kolaylaştırır. Temiz kod üzerinde değişiklik yapmak çok daha kolaydır. 134 | 135 | 136 | ### Bir Hatayı Düzeltirken 137 | 138 |
139 | 140 | ![](https://refactoring.guru/images/refactoring/content/pages/r3.svg) 141 | 142 |
143 | 144 | Kodun içindeki hatalar (bugs), gerçek hayattaki gibi davranır: kodun en karanlık, en kirli yerlerinde yaşarlar. Kodunuzu temizleyin ve hatalar neredeyse kendiliğinden ortaya çıkacaktır. 145 | 146 | Yöneticiler, proaktif refaktörü, sonradan özel refaktör görevlerine gerek bırakmadığı için daha çok severler. Ayrıca takdir ederler. Mutlu patronlar, mutlu programcılar demektir! 147 | 148 | ### Kod İncelemesi (Review) Sırasında 149 | 150 | - Kod incelemesi, kodun genel kullanıma sunulmadan önce düzenlenmesi için son şanstır. 151 | - Bu incelemeleri geliştirmeyi yapan programcı ile birlikte çift olarak yapmak en iyisidir. Bu şekilde basit problemleri hızlı bir şekilde çözebilir ve daha zor olanları düzeltmek için zamanı planlayabilirsiniz. 152 | 153 | ## Refactoring Nasıl Yapılır? 154 | 155 | Refaktör, mevcut kodu küçük değişiklikler serisi olarak ele almalıdır. Her bir değişiklik, mevcut programı çalışır durumda bırakarak mevcut kodu biraz daha iyi hale getirmelidir. 156 | 157 | ### Doğru Yapılan Refaktör İçin Kontrol Listesi 158 | 159 | **✅ Kod temiz hale gelmelidir.** 160 | 161 | Kod, yeniden düzenleme sonrasında da aynı şekilde kirli kalırsa... eh, üzgünüm ama hayatınızın bir saatini boşa harcadınız. Bu durumun neden olduğunu anlamaya çalışın. 162 | 163 | Bu durum sıklıkla, küçük değişikliklerle yeniden düzenlemeden uzaklaştığınızda ve bir sürü yeniden düzenlemeyi tek bir büyük değişiklikte karıştırdığınızda meydana gelir. Bu nedenle aklınızı kaybetmeniz çok kolaydır, özellikle de zaman konusunda endişeniz varsa. 164 | 165 | Bununla beraber aynı zamanda, son derece dağınık bir kodla çalışırken de gerçekleşebilir. Ne kadar iyileştirme yaparsanız yapın, genel olarak kod hâlâ bir felaket olabilir. 166 | 167 | Bu durumda, kodun bazı bölümlerini tamamen yeniden yazmayı düşünmek faydalı olabilir. Ancak önce testler yazmalı ve yeterli bir süre ayırmalısınız. Aksi halde, ilk paragrafta konuştuğumuz türden sonuçlar elde edebilirsiniz. 168 | 169 | **✅ Refaktör sırasında yeni işlevsellik oluşturulmamalıdır.** 170 | 171 | Refaktörü, yeni özelliklerin doğrudan geliştirilmesiyle karıştırmayın. Bu süreçleri mümkünse en azından bireysel taahhütler içinde ayırmaya çalışın. 172 | 173 | **✅ Refaktör sonrasında mevcut tüm testlerin geçmesi gerekir.** 174 | 175 | Refactoring sonrasında testlerin bozulabileceği iki durum söz konusu olabilir: 176 | 177 | - Yeniden düzenleme sırasında bir hata yapmış olabilirsiniz. Bu hiç akıllıca değil: devam etmeli ve bir şekilde hatayı düzeltmelisiniz. 178 | - Testleriniz düşük düzeyde (low-level) olabilir. Örneğin, sınıfların private yöntemlerini test etmeyi denemiş olabilir ve testler başarısızlıkla sonuçlanmış olabilir. 179 | 180 | Bu durumda, sorun testlerdedir. Bu durumda iki seçeneğiniz var: Testleri kendiniz yeniden düzenleyebilir veya tamamen yeni bir dizi üst düzey yani kapsamlı test yazabilirsiniz. Bu tür bir durumdan kaçınmanın harika bir yolu BDD (Behavior-driven Development) prensibine dayalı testler yazmaktır. 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /code-smells/dispensables.md: -------------------------------------------------------------------------------- 1 | # Vazgeçilebilir (Dispensables) 2 | 3 | Kodunuz da vazgeçilebilir yapılar olabilir. Bu yapılar, yokluğu kod daha temiz, daha verimli ve anlaşılması daha kolay hale gelir. 4 | 5 | ## 1️⃣ Yorumlar (Comments) 6 | 7 | **🤢 Belirti ve Semptomlar** 8 | 9 | Bir yöntem veya sınıf açıklayıcı yorumlarla dolu olduğunda soru işaretleri oluşmalıdır. 10 | 11 | ![](https://refactoring.guru/images/refactoring/content/smells/comments-01-2x.png) 12 | 13 | **🤒 Sorunun Nedenleri** 14 | 15 | Geliştiriciler, genellikle en iyi niyetle, kodunun sezgisel veya açık olmadığını fark ettiğinde yorumları kodların eklerler. Bu gibi durumlarda yorumlar, iyileştirilebilecek şüpheli kod kokusunu maskeleyen bir deodorant gibidir. 16 | 17 | *En iyi yorum, bir yöntem veya sınıf için iyi bir adlandırmadır.* 18 | 19 | Bir kod parçasının yorum olmadan anlaşılamayacağını düşünüyorsanız kod yapısını yorumlara gerek duyulmayacak şekilde değiştirmeyi deneyin. Daha temiz bir kod yapısına aktarılmak, yorum ile açıklamaktan daha sürdürülebilirdir. 20 | 21 | **💊 Tedavi** 22 | 23 | - Bir yorum karmaşık bir ifadeyi açıklamak amacıyla kullanılıyorsa, ifade **Extract Variable** tekniği kullanılarak anlaşılır alt ifadelere bölmelisiniz. 24 | 25 | - Bir yorum bir kod bölümünü açıklıyorsa, bu bölüm **Extract Method** tekniğini kullanılarak ayrı bir metoda dönüştürülebilir. Yeni metodun adı, büyük olasılıkla yorum metninden alınabilir. Böylelikle yorum satırına ihtiyaç duymayan, yeterince açıklayıcı bir yöntem adıyla sorunun üstesinden gelmiş olursunuz. 26 | 27 | - Bir metod zaten çıkarılmışsa (extracted), ancak metodu ne yaptığını açıklamak için hala yorumlar gerekiyorsa, metoda açıklayıcı bir ad verin. Bunun için **Rename Method** tekniğini kullanın. 28 | 29 | - Sistem çalışması için gerekli bir durum hakkında kuralları belirtmeniz gerekiyorsa, **Introduce Assertion** tekniğini kullanın. 30 | 31 | **💰 Hesaplaşma** 32 | 33 | Kod daha sezgisel ve anlaşılır hale gelir. 34 | 35 | ![](https://refactoring.guru/images/refactoring/content/smells/comments-02-2x.png) 36 | 37 | **🤫 Ne Zaman Yok Sayılmalı?** 38 | 39 | Yorumlar bazen yararlı olabilir: 40 | 41 | - Bir şeyin neden belirli bir şekilde uygulandığını açıklarken. 42 | 43 | - Karmaşık algoritmaları açıklarken (tabi ki algoritmayı basitleştirmeye yönelik diğer tüm yöntemler denendiğinde ve yetersiz kaldığında). 44 | 45 | ## 2️⃣ Tekrarlı/Kopya Kod (Duplicate Code) 46 | 47 | **🤢 Belirti ve Semptomlar** 48 | 49 | İki kod parçası neredeyse aynı göründüğü durumlarda kafanızda soru işaretleri oluşmalıdır. 50 | 51 | ![](https://refactoring.guru/images/refactoring/content/smells/duplicate-code-01-2x.png) 52 | 53 | **🤒 Sorunun Nedenleri** 54 | 55 | Tekrarlı kod genellikle birden fazla geliştiricinin aynı programın farklı bölümleri üzerinde aynı anda çalıştığında meydana gelir. Farklı görevler üzerinde çalıştıkları için, meslektaşlarının kendi ihtiyaçları doğrultusunda yeniden kullanılabilecek benzer bir kod yazdığından habersiz olabilirler. 56 | 57 | Kodun belirli bölümleri farklı görünse de aslında aynı işi yaptığında, hemen fark edilemeyecek duplication da söz konusudur. Bu tür tekrarları bulmak ve düzeltmek zor olabilir. 58 | 59 | Bazen tekrarlama bilerek yapılmış olabilir. Son teslim tarihlerine yetişmek için acele ederken ve mevcut kod iş için neredeyse doğru olduğunda, acemi programcılar ilgili kodu kopyalayıp yapıştırmanın cazibesine karşı koyamayabilirler. Ve bazı durumlarda programcı dağınıklığı gideremeyecek kadar tembeldir. Bu durumlarda kod iyice kirli hale gelir ve bir aksiyon alınmadığında, iş içinden çıkılmaz bir hal alabilir. 60 | 61 | 62 | **💊 Tedavi** 63 | 64 | - Aynı kod, aynı sınıfta iki veya daha fazla yöntemde bulunursa: 65 | **Extract Method** tekniğini kullanın ve her iki yere de yeni yöntem için çağrılar yapın. 66 | 67 | 68 | ![](https://refactoring.guru/images/refactoring/content/smells/duplicate-code-02-2x.png) 69 | 70 | - Eğer aynı kod, aynı seviyedeki iki alt sınıfta bulunuyorsa: 71 | - Her iki sınıf için de **Extract Method** tekniğini kullanın, ardından üst sınıfa çıkardığınız metotta kullanılan alanlar için **Pull Up Field** tekniğini kullanın. 72 | - Yineleme kodu bir yapıcı (constructor) içindeyse, **Pull Up Constructor Body** tekniğini kullanın. 73 | - Yineleme kodu benzer ancak tamamen aynı değilse, **Form Template Method** tekniğini kullanın. 74 | - İki metodun aynı şeyi yaptığı ancak farklı algoritmalar kullandığı durumlarda, en iyi algoritmayı seçin ve **Substitute Algorithm** tekniğini uygulayın. 75 | 76 | - Eğer aynı kod farklı iki sınıfta bulunuyorsa: 77 | - Eğer sınıflar bir hiyerarşinin bir parçası değilse, bu sınıflar için tüm önceki işlevselliği koruyan tek bir üst sınıf oluşturmak için **Extract Superclass** tekniğii kullanın. 78 | - Eğer bir üst sınıf oluşturmak zor veya imkansızsa, bir sınıfta **Extract Class** tekniğini kullanın. Sonrasında yeni bileşeni diğer sınıfta kullanın. 79 | 80 | - Eğer çok sayıda koşullu ifadeler bulunuyorsa ve aynı amaca hizmet ediyorsa (sadece koşullarında farklılık gösteriyor), bu operatörleri **Consolidate Conditional Expression** tekniğini kullanarak tek bir koşula birleştirin. Bu işlemi yaparken, koşulu anlaşılır bir adı olan ayrı bir metoda yerleştirmek için **Extract Method** tekniğini kullanın. 81 | 82 | - Eğer koşullu bir ifadenin tüm dallarında aynı kod gerçekleştiriliyorsa: **Consolidate Duplicate Conditional Fragments** tekniği kullanarak, aynı kodu koşul ağacının dışına yerleştirin. 83 | 84 | **💰 Hesaplaşma** 85 | 86 | - Yinelenen kodu birleştirmek, kodunuzun yapısını basitleştirir ve kısaltır. 87 | 88 | - Basitleştirme + kısalık = basitleştirilmesi daha kolay ve desteklenme maliyeti az olan kod. 89 | 90 | ![](https://refactoring.guru/images/refactoring/content/smells/duplicate-code-03-2x.png) 91 | 92 | **🤫 Ne Zaman Yok Sayılmalı?** 93 | 94 | Çok nadir durumlarda, iki özdeş kod parçasını birleştirmek, kodu daha az sezgisel ve anlaşılır hale getirebilir. Bu tarz durumlarda yok sayılabilir. 95 | 96 | ## 3️⃣ Tembel Sınıf (Lazy Class) 97 | 98 | **🤢 Belirti ve Semptomlar** 99 | 100 | Sınıfları anlamak ve sürdürmek her zaman zamana ve maliyete sebep olacaktır. Dolayısıyla bir sınıf dikkatinizi çekecek kadar yeterli yerde kullanılmıyorsa göstermiyorsa silinmelidir. 101 | 102 | ![](https://refactoring.guru/images/refactoring/content/smells/lazy-class-01-2x.png) 103 | 104 | **🤒 Sorunun Nedenleri** 105 | 106 | Belki bir sınıf, eski bir süreçte tamamen işlevsel olacak şekilde tasarlanmıştı. Ancak bazı refactoring süreçlerinden sonra gülünç derecede küçük hale geldi. 107 | 108 | Veya belki de gelecekte hiç yapılmayacak geliştirme çalışmalarını desteklemek için tasarlandı. Yani henüz olmayan özelllikler için önceden hazırlandı. 109 | 110 | **💊 Tedavi** 111 | 112 | - Neredeyse kullanışsız olan bileşenlere **Inline Class** tekniği uygulanmalıdır. 113 | 114 | - Az fonksiyona sahip alt sınıflar için **Collapse Hierarchy** yöntemini deneyin. 115 | 116 | ![](https://refactoring.guru/images/refactoring/content/smells/lazy-class-02-2x.png) 117 | 118 | **💰 Hesaplaşma** 119 | 120 | - Kod boyutu azaltır. 121 | - Daha kolay bakım sunar. 122 | 123 | **🤫 Ne Zaman Yok Sayılmalı?** 124 | 125 | Bazen gelecekteki gelişime yönelik niyetleri belirlemek için bir Tembel Sınıf (Lazy Class) oluşturulur. Bu durumda, kodunuzda açıklık ve basitlik arasında bir denge kurmaya çalışmalısınız. 126 | 127 | 128 | ## 4️⃣ Veri Sınıfı (Data Class) 129 | 130 | **🤢 Belirti ve Semptomlar** 131 | 132 | Bir veri sınıfı (data class), yalnızca alanları ve bunlara erişim için kaba yöntemleri (getters ve setters) içeren bir sınıfı ifade eder. Bunlar yalnızca diğer sınıflar tarafından kullanılan veriler için kullanılan conteynerlerdir. Bu sınıflar herhangi bir ek işlevsellik içermez ve sahip oldukları veriler üzerinde bağımsız olarak çalışamazlar. Böyle bir durumla karşılaştığınızda soru işaretleri oluşmalıdır. 133 | 134 | ![](https://refactoring.guru/images/refactoring/content/smells/data-class-01-2x.png) 135 | 136 | **🤒 Sorunun Nedenleri** 137 | 138 | Yeni oluşturulan bir sınıfın yalnızca birkaç ortak alan (ve hatta belki bir avuç getter/setter) içermesi normal bir şeydir. Ancak nesnelerin gerçek gücü, verileri üzerinde davranış türlerini veya işlemleri içerebilmeleridir. 139 | 140 | **💊 Tedavi** 141 | 142 | - Bir sınıf public alanlar içeriyorsa, bu alanları doğrudan erişimden gizlemek ve erişimi sadece getter ve setter'lar aracılığıyla yapılmasını sağlamak için **Encapsulate Field** tekniğini kullanın. 143 | 144 | - Verilerin saklandığı koleksiyonlar (örneğin diziler) için **Encapsulate Collection** tekniğini kullanın. 145 | 146 | - Sınıfı kullanan istemci kodunu gözden geçirin. Burada, işlevselliğin veri sınıfında daha iyi yer alabileceği durumları bulabilirsiniz. Eğer durum böyleyse, bu işlevselliği veri sınıfına göç ettirmek için **Move Method** ve **Extract Method** tekniklerini kullanın. 147 | 148 | - Sınıf, düşünce ile oluşturulmuş metodlarla doldurulduktan sonra, sınıf verisine aşırı geniş erişim sağlayan eski veri erişimi metodlarından kurtulmak isteyebilirsiniz. Bu durumda, **Remove Setting Method** ve **Hide Method** yöntemleri yardımcı olabilir. 149 | 150 | 151 | ![](https://refactoring.guru/images/refactoring/content/smells/data-class-02-2x.png) 152 | 153 | **💰 Hesaplaşma** 154 | 155 | - Kodun anlaşılmasını ve organizasyonunu geliştirir. Belirli veriler üzerindeki işlemler artık kod boyunca gelişigüzel bir şekilde yerine tek bir yerde toplanır. Böylelikle bir standarta sahip olursunuz. 156 | - İstemci kodunun kopyalarını tespit etmenize yardımcı olur. 157 | 158 | ## 5️⃣ Ölü Kod (Dead Code) 159 | 160 | **🤢 Belirti ve Semptomlar** 161 | 162 | Bir değişken, parametre, alan, yöntem veya sınıf artık kullanılmamaktadır. Bu durum genellikle eski olduğu için ortaya çıkar. Böyle bir durumda soru işaretleri oluşmalıdır. 163 | 164 | ![](https://refactoring.guru/images/refactoring/content/smells/dead-code-01-2x.png) 165 | 166 | **🤒 Sorunun Nedenleri** 167 | 168 | Yazılımın gereksinimleri değiştiğinde ya da düzeltmeler yapıldığında kimsenin eski kodu temizlemeye vakti olmaz. 169 | 170 | Bu tür kod, dallardan birine ulaşılamadığında (hata veya başka koşullar nedeniyle) karmaşık koşul ifadelerinde de bulunabilir. 171 | 172 | **💊 Tedavi** 173 | 174 | - Kullanılmayan kodları ve gereksiz dosyaları silin. 175 | 176 | - Gereksiz bir sınıf durumunda, bir alt sınıf veya üst sınıf kullanılıyorsa **Inline Class** veya **Collapse Hierarchy** teknikleri uygulanabilir. 177 | 178 | - Gereksiz parametreleri kaldırmak için **Remove Parameter** yöntemini kullanın. 179 | 180 | 181 | ![](https://refactoring.guru/images/refactoring/content/smells/dead-code-02-2x.png) 182 | 183 | **💰 Hesaplaşma** 184 | 185 | - Kod boyutu azalır. 186 | - Daha kolay destek sağlanır. 187 | 188 | 189 | ## 6️⃣ Spekülatif Genellik (Speculative Generality) 190 | 191 | **🤢 Belirti ve Semptomlar** 192 | 193 | Kullanılmayan bir sınıf, yöntem, alan veya parametre var ise soru işaretleriniz oluşmalıdır. 194 | 195 | ![](https://refactoring.guru/images/refactoring/content/smells/speculative-generality-01-2x.png) 196 | 197 | 198 | **🤒 Sorunun Nedenleri** 199 | 200 | Bazen kod, hiçbir zaman uygulamaya konmayan, gelecekte beklenen özellikleri desteklemek için "her ihtimale karşı" diye düşünülerek oluşturulur. Sonuç olarak bu düşünce, kodun anlaşılması ve desteklenmesi zorlaştıracaktır. 201 | 202 | **💊 Tedavi** 203 | 204 | - Kullanılmayan soyut (abstract) sınıfları kaldırmak için **Collapse Hierarchy** yöntemini deneyin. 205 | 206 | - Başka bir sınıfa işlevsellik aktarmanın gereksiz olduğu durumları **Inline Class** tekniği ile ortadan kaldırabilirsiniz. 207 | 208 | - Kullanılmayan metodlar mı? Onlardan kurtulmak için **Inline Method** tekniğini kullanın. 209 | 210 | - Kullanılmayan parametrelere sahip metodlar, **Remove Parameter** tekniğinin yardımıyla incelenmelidir. 211 | 212 | - Kullanılmayan alanlar basitçe silinebilir. 213 | 214 | 215 | ![](https://refactoring.guru/images/refactoring/content/smells/speculative-generality-02-2x.png) 216 | 217 | **💰 Hesaplaşma** 218 | 219 | - Kod boyutu azalır. 220 | - Daha kolay destek. 221 | 222 | **🤫 Ne Zaman Yok Sayılmalı?** 223 | 224 | Bir framework üzerinde çalışıyorsanız, framework kullanıcıları tarafından ihtiyaç duyulduğu sürece, çerçevenin kendisinde kullanılmayan bir işlevsellik yaratmak son derece mantıklıdır. 225 | 226 | Öğeleri silmeden önce birim testlerde kullanılmadıklarından emin olun. Bu, testlerin bir sınıftan belirli dahili bilgileri almanın veya testle ilgili spesifik eylemleri gerçekleştirmenin bir yoluna ihtiyaç duyması durumunda gerçekleşir. 227 | 228 | -------------------------------------------------------------------------------- /code-smells/bloaters.md: -------------------------------------------------------------------------------- 1 | # Bloaters (Şişkinlik) 2 | 3 | Bloaters, üzerinde çalışılması zor olacak kadar devasa boyutlara ulaşmış kodlar, yöntemler ve sınıfları tanımlar. Genellikle bu kokular hemen ortaya çıkmaz, proje veya program geliştikçe zamanla birikir. Ayrıca kimsenin bu sorunun önüne geçmek için çaba göstermediğinde bu koku iyice kendini belli eder. 4 | 5 | ## 1️⃣ Uzun Metot (Long Method) 6 | 7 | **🤢 Belirti ve Semptomlar** 8 | 9 | Bir yöntem çok fazla kod satırı içeriyorsa bir sorun vardır. Genellikle on satırdan uzun herhangi bir yöntem ortaya çıktıysa bu yöntem ile ilgili soru işaretleriniz oluşmalıdır. 10 | 11 | ![](https://refactoring.guru/images/refactoring/content/smells/long-method-01-2x.png) 12 | 13 | 14 | **🤒 Sorunun Nedenleri** 15 | 16 | Geliştirme sürecinde bir yönteme her zaman bir şeyler eklenir. Durumun tam aksi olarak ise kolay kolat hiçbir şey çıkarılmaz. Kod yazmak okumaktan daha kolaydır. Bundan dolayı bu koku, yöntem kontrol edilemez büyük boyutlu bir canavara dönüşene kadar fark edilmeden kalır. 17 | 18 | Genellikle yeni bir yöntem oluşturmak, mevcut bir yönteme ekleme yapmaktan daha zordur: "Ama bu sadece birkaç satır kod, sırf bunun için bütün bir yöntem yaratmanın bir anlamı yok, var olana ekleyelim gitsin!" Bu düşünce, başka bir satırın eklendiği ve ardından yine birkaç satır eklendiği anlamına gelir. Aynı veya farklı geliştirici birer satır daha ekledikçe yöntem, bir spagetti kodu karmaşasına evrilir. 19 | 20 | **💊 Tedavi** 21 | 22 | Genel bir kural olarak durum şudur: Bir yöntemin içindeki bir alana yorum yapma ihtiyacı hissediyorsanız, bu kodu alıp yeni bir yönteme koymalısınız. Çünkü açıklama veya yorum gerektiriyorsa, o yöntem kendisine ait olmayan bir alan içeriyordur. Tek bir satır bile ayrı bir yönteme bölünebilir ve bölünmelidir de! Bununla beraber yöntemin açıklayıcı ve uygun bir adı varsa, kimsenin ne yaptığını görmek için yöntemin gövdesine bakmasına gerek kalmayacaktır. 23 | 24 | ![](https://refactoring.guru/images/refactoring/content/smells/long-method-02-2x.png) 25 | 26 | - Bir metodun gövdesinin uzunluğunu azaltmak için **Extract Method** tekniği kullanın. 27 | 28 | - Yerel değişkenler ve parametreler bir metodu ayrı bir metoda çıkarmayı engelliyorsa, **Replace Temp with Query**, **Introduce Parameter Object** veya **Preserve Whole Object** tekniklerinden uygun olanı/olanları kullanın. 29 | 30 | - Eğer önceki yöntemlerin hiçbiri işe yaramazsa, tüm metodu **Replace Method with Method Object** tekniği kullanarak ayrı bir nesneye taşımaya çalışın. 31 | 32 | - Koşullu operatörler ve döngülerin bulunması, kodun ayrı bir metoda taşınabileceğine dair birer ipucudur. Koşullular için **Decompose Conditional** tekniği kullanabilirsiniz. Döngüler engelliyorsa, **Extract Method** tekniğini deneyin. 33 | 34 | **💰 Hesaplaşma** 35 | 36 | - Tüm nesne yönelimli (OOP) kod türleri arasında, kısa metotlara sahip sınıflar her zaman en uzun ömürlü olanlardır. Bir metot veya fonksiyon ne kadar uzunsa, onu anlamak ve sürdürülebilir kılmak o kadar zor olur. 37 | 38 | - Ayrıca, uzun metotlar istenmeyen kopya yani duplicate kodlar için mükemmel saklanma alanları sunar. Bundan sakınmalıyız. 39 | 40 | **📈 Performans/Verim** 41 | 42 | Birçok kaynakta iddia edildiği gibi, metot sayısındaki artış performansa zarar verir mi? Hemen hemen tüm durumlar göz önüne alındığında etki o kadar önemsizdir ki endişelenmeye bile değmez. 43 | 44 | Ayrıca, bu yöntemle net ve anlaşılır bir kod elde ettiğinizden dolayı, gerektiğinde gerçek performans kazanımları elde etmek için kodu yeniden yapılandırmanın gerçekten etkili yollarını bulma olasılığınız daha yüksektir. 45 | 46 | 47 | ## 2️⃣ Large Class (Büyük Sınıf) 48 | 49 | **🤢 Belirti ve Semptomlar** 50 | 51 | Bir sınıf birçok alan (field), yöntem ve kod satırı içerdiğinde soru işaretleriniz oluşmalıdır. 52 | 53 | ![](https://refactoring.guru/images/refactoring/content/smells/large-class-01-2x.png) 54 | 55 | **🤒 Sorunun Nedenleri** 56 | 57 | Sınıflar genellikle küçük yapılar olarak başlar. Ancak program büyüdükçe büyüdükçe büyür ve zamanla şişerler. 58 | 59 | Uzun yöntemler case'inde de olduğu gibi, programcılar genellikle mevcut bir sınıfa yeni bir özellik eklemeyi, o özellik için yeni bir sınıf oluşturmaya tercih ederler. 60 | 61 | ![](https://refactoring.guru/images/refactoring/content/smells/large-class-02.png) 62 | 63 | **💊 Tedavi** 64 | 65 | Bir sınıf çok fazla metot içeriyorsa, o sınıfı farklı sınıflara ayırmayı düşünün: 66 | 67 | - **Extract Class** tekniği, büyük sınıfın davranışının bir kısmının ayrı bir bileşene/sınıfa dönüştürülebilmesi durumunda yardımcı olur. 68 | - **Extract Subclass** tekniği, üst sınıfın davranışının bir kısmının farklı şekillerde alt sınıfta uygulanabilmesine veya nadir durumlarda kullanılmasına yardımcı olur. 69 | - **Extract Interface** tekniği, istemcinin kullanabileceği işlem ve davranışların bir listesinin gerekli olması durumunda yardımcı olur. 70 | - Projenin grafiksel arayüzden büyük bir sınıf sorumluysa, bazı verilerini ve davranışlarını ayrı bir etki alanı nesnesine (domain object) taşımayı deneyebilirsiniz. Bunu yaparken bazı verilerin kopyalarını iki yerde saklamak ve verilerin tutarlı olmasını sağlamak gerekebilir. **Duplicate Observed Data** tekniği bunu yapmanın bir yolunu sunar. 71 | 72 | ![](https://refactoring.guru/images/refactoring/content/smells/large-class-03-2x.png) 73 | 74 | **💰 Hesaplaşma** 75 | 76 | - Bu sınıfların yeniden düzenlenmesi yani refactor edilmesi, geliştiricilerin bir sınıf için çok sayıda özelliği hatırlama ihtiyacını ortadan kaldırır. Bu da geliştirme sürecine pozitif etki olarak yansıyacaktır. 77 | 78 | - Çoğu durumda, büyük sınıfları parçalara ayırmak kod ve işlevlerin tekrarlanmasının yani duplicate olmasının önüne geçer. 79 | 80 | ## 3️⃣ Primitive Obsession (İlkel Takıntı) 81 | 82 | **🤢 Belirti ve Semptomlar** 83 | 84 | Aşağıdaki listelenmiş durumlarda soru işaretleriniz oluşmalıdır: 85 | 86 | - Basit görevler için küçük nesneler yerine ilkel öğelerin (primitives) kullanılması (para birimi, aralıklar, telefon numaraları için özel dizeler vb.) 87 | - Değişkenler için sabitlerin kullanılması (yönetici haklarına sahip kullanıcılara atıfta bulunmak için `USER_ADMIN_ROLE = 1` sabiti gibi.) 88 | - Veri dizilerinde (data array) kullanılmak üzere field adları olarak dize (string) sabitlerinin kullanılması. 89 | 90 | ![](https://refactoring.guru/images/refactoring/content/smells/primitive-obsession-01-2x.png) 91 | 92 | **🤒 Sorunun Nedenleri** 93 | 94 | Repoda bulunan çoğu diğer koku gibi, ilkel (primitive) obsessions zayıf anlarda ortaya çıkar. Bir programcı "Sadece bazı verileri depolamak için bir alan!" diye düşünebilir. Bir ilkel alan oluşturmak, tamamen yeni bir sınıf yapmaktan çok daha kolaydır. Öyle değil mi? Ve öyle de olur. Sonra başka bir alan gerektiğinde yine aynı şekilde bir primitive değer daha eklenmiş olur. Böylelikel zamanla sınıf büyük ve kullanışsız hale evrilecektir. 95 | 96 | İlkel veriler sıklıkla türleri (type) simule etmek için kullanılır. Yani ayrı bir veri türü yerine, bir varlık için izin verilen değerler listesini oluşturan bir dizi sayı veya dizeye (string) sahip olursunuz. Anlaşılması kolay isimler daha sonra bu belirli sayılara ve dizelere sabitler aracılığıyla verilir, bu yüzden geniş bir alana yayılırlar. 97 | 98 | İlkel kullanımının kötü bir örneği, alan taklidi (field simulation) yapmaktır. Sınıf, çeşitli veri ve dize sabitlerini içeren büyük bir diziyi içerir. Bu verilere erişmek için sınıfta belirtilenler/tanımlanan dize sabitleri dizi indisleri olarak kullanılır. 99 | 100 | **💊 Tedavi** 101 | 102 | - Çok çeşitli ilkel (primitive) alanlarınız varsa, bunlardan bazılarını mantıksal olarak kendi sınıflarında gruplandırmak daha sağlıklı olabilir. Daha da iyisi, bu verilerle ilişkili davranışları da ayrı bir sınıfa taşıyabilirsiniz. Bu görev için **Replace Data Value with Object** tekniğine bir göz atabilirsinz. 103 | 104 | ![](https://refactoring.guru/images/refactoring/content/smells/primitive-obsession-02-2x.png) 105 | 106 | 107 | - İlkel alanların değerleri metot parametrelerinde kullanılıyorsa, **Introduce Parameter Object** veya **Preserve Whole Object** tekniklerini kullanın. 108 | 109 | - Karmaşık veriler değişkenlerde kodlandığında, **Replace Type Code with Class**, **Replace Type Code with Subclasses** veya **Replace Type Code with State/Strategy** kullanın. 110 | 111 | - Değişkenler arasında diziler varsa, **Replace Array with Object** kullanın. 112 | 113 | **💰 Hesaplaşma** 114 | 115 | - İlkel veriler yerine, nesnelerin tercih edilmesi sayesinde kod daha esnek hale gelir. 116 | - Kodun daha iyi anlaşılabilir ve düzenli hale gelir. Belirli veriler üzerindeki operasyonlar, dağınık olmaktansa aynı yerde toplanıt. Böylelikle bu sabitlerin neden dizide oldukları hakkında daha fazla tahmin yapmaya gerek olmayacaktır, her şey oldukça net hale gelir. 117 | - Kopya (duplicate) kodun daha kolay bulunması. 118 | 119 | ## 4️⃣ Long Parameter List (Uzun Parametre Listesi) 120 | 121 | **🤢 Belirti ve Semptomlar** 122 | 123 | Bir yöntem için üç veya dörtten fazla parametre bulunması durumunda soru işaretleri oluşmalıdır. 124 | 125 | ![](https://refactoring.guru/images/refactoring/content/smells/long-parameter-list-01-2x.png) 126 | 127 | **🤒 Sorunun Nedenleri** 128 | 129 | Birkaç algoritma türü tek bir yöntemde birleştirildiğinde uzun bir parametre listesi ortaya çıkabilir. Hangi algoritmanın nasıl çalıştırılacağını kontrol etmek için uzun bir liste ile karşı karşıya gelebilirsiniz. 130 | 131 | Uzun parametre listeleri sorunu, sınıfları birbirinden daha bağımsız hale getirirken bir yan etki olarak da oluşabilir. Örneğin, bir yöntemde ihtiyaç duyulan belirli nesneleri oluşturmaya yönelik kodunuz, yöntemden yöntemi çağırmaya yönelik bir koda taşıdınız. Aynı zamanda oluşturulan nesneler yönteme parametre olarak aktarıldı. Böylece orijinal sınıf artık nesneler arasındaki ilişkileri bilmez ve bağımlılıklar azalır. Ancak bu nesnelerden birkaçı oluşturulursa, her biri kendi parametresine ihtiyaç duyacaktır. Bu da daha uzun bir parametre listesi anlamına gelir. Oldukça beyin yakıcı bir hal aldı değil mi! 132 | 133 | Uzadıkça çelişkili hale gelen ve kullanımı zorlaşan bu tür listeleri anlamak zordur. Uzun bir parametre listesi yerine, bir yöntem kendi nesnesinin verilerini kullanabilir. Geçerli nesne gerekli tüm verileri içermiyorsa, yöntem parametresi olarak (gerekli verileri alacak olan) başka bir nesne daha iletilebilir. 134 | 135 | **💊 Tedavi** 136 | 137 | - Parametrelere hangi değerlerin aktarıldığını kontrol edin. Eğer bazı argümanlar sadece başka bir nesnenin metot çağrılarının sonuçları ise, **Replace Parameter with Method Call** tekniğini kullanın. Bu nesne, kendi sınıfının alanına yerleştirilebilir veya bir metot parametresi olarak aktarılabilir. 138 | 139 | - Başka bir nesneden alınan bir veri grubunu parametre olarak geçirmek yerine, **Preserve Whole Object** tekniğini kullanarak nesnenin kendisini yönteme geçirin. 140 | 141 | - Diğer yandan, bu parametreler farklı kaynaklardan geliyorsa, **Introduce Parameter Object** tekniği kullanarak bunları tek bir parametre nesnesi olarak geçirebilirsiniz. 142 | 143 | ![](https://refactoring.guru/images/refactoring/content/smells/long-parameter-list-02-2x.png) 144 | 145 | **💰 Hesaplaşma** 146 | 147 | - Daha okunabilir, daha kısa kod sunar. 148 | - Refactoring, daha önce fark edilmeyen yinelenen kodu ortaya çıkarabilir böylelikle daha temiz bir kod base'e ulaşırsınız. 149 | 150 | **🤫 Ne Zaman Yok Sayılmalı?** 151 | 152 | Sınıflar arasında istenmeyen bağımlılığa neden olacaksa parametrelerden kurtulmayın. 153 | 154 | ## 5️⃣ Data Clumps (Veri Kümeleri) 155 | 156 | **🤢 Belirti ve Semptomlar** 157 | 158 | Bazen kodun farklı bölümleri bir veritabanına bağlanma parametreleri gibi aynı değişken gruplarını içerebilir. Bu kümelerin kendi sınıflarına dönüştürülmesi gerekmektedir. 159 | 160 | ![](https://refactoring.guru/images/refactoring/content/smells/data-clumps-01-2x.png) 161 | 162 | **🤒 Sorunun Nedenleri** 163 | 164 | Genellikle bu veri grupları zayıf program yapısından veya kopyala yapıştır geliştirmelerden kaynaklanmaktadır. 165 | 166 | Bazı verilerin veri kümesi (data clump) olup olmadığından emin olmak istiyorsanız veri değerlerinden birini silin ve diğer değerlerin hâlâ anlamlı olup olmadığına bakın. Durum böyle değilse, bu değişken grubunun bir nesnede birleştirilmesi gerektiğine dair iyi bir işaret sunar. 167 | 168 | **💊 Tedavi** 169 | 170 | - Tekrar eden veri, bir sınıfın alanlarını (field) oluşturuyorsa, **Extract Class** tekniğini kullanarak bu alanları kendi sınıflarına taşıyın. 171 | 172 | - Aynı veri yığınları metod parametrelerinde geçiyorsa, **Introduce Parameter Object** tekniğini kullanarak bunları bir sınıf olarak ayırın. 173 | 174 | - Yalnızca bireysel alanlar değil genel olarak verilerin bazıları diğer metotlara geçiriliyorsa, , tüm veri nesnesini metoda geçirmeyi düşünün. **Preserve Whole Object** tekniği bu konuda yardımcı olacaktır. 175 | 176 | - Bu alanların kullandığı kodlara bakın. Bu kodu bir veri sınıfına taşımak iyi bir fikir olabilir. 177 | 178 | ![](https://refactoring.guru/images/refactoring/content/smells/data-clumps-02-2x.png) 179 | 180 | **💰 Hesaplaşma** 181 | 182 | - Kodun anlaşılmasını ve organizasyonunu geliştirir. Belirli veriler üzerindeki işlemler artık kod boyunca gelişigüzel bir şekilde yerine tek bir yerde toplanır. Böylelikle gerektiğinde düzenlemeler daha kolay yapılacaktır. 183 | 184 | - Kod boyutunu azaltır. Daha az kod, daha az koku demektir! 185 | 186 | ![](https://refactoring.guru/images/refactoring/content/smells/data-clumps-03-2x.png) 187 | 188 | 189 | **🤫 Ne Zaman Yok Sayılmalı?** 190 | 191 | Bir nesnenin yalnızca değerlerini (ilkel türler) iletmek yerine, bir yöntemin parametrelerinde tamamını geçirmek, iki sınıf arasında istenmeyen bir bağımlılık yaratabilir. 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /refactoring-techniques/moving-features-between-objects.md: -------------------------------------------------------------------------------- 1 | # Özellikleri Nesneler Arasında Taşıma (Moving Features between Objects) 2 | 3 | İşlevselliği farklı sınıflar arasında ideal olmayan bir şekilde dağıtmış olsanız bile hala umut var. 4 | 5 | Bu yeniden düzenleme teknikleri, işlevselliğin sınıflar arasında güvenli bir şekilde nasıl taşınacağını, yeni sınıfların nasıl oluşturulacağını ve uygulama ayrıntılarının genel erişimden nasıl gizleneceğini gösterir. 6 | 7 | ## Move Method 8 | 9 | ### 🙁 Problem 10 | 11 | Bir yöntem başka bir sınıfta kendi sınıfından daha fazla kullanması sorun oluşturabilir. 12 | 13 |
14 | 15 | ![](https://refactoring.guru/images/refactoring/diagrams/Move%20Method%20-%20Before.png) 16 |
17 | 18 | ### 😊 Çözüm 19 | 20 | Yöntemi en çok kullanan sınıfta, yeni bir yöntem oluşturun. Ardından kodu eski yöntemden oluşturduğunuz yönteme taşıyın. Orijinal yöntemin kodunu diğer sınıftaki yeni yönteme referans olacak şekilde güncelleyin veya tamamen kaldırın. 21 | 22 |
23 | 24 | ![](https://refactoring.guru/images/refactoring/diagrams/Move%20Method%20-%20After.png) 25 |
26 | 27 | ### 🤔 Neden Refactoring Uygulanmalı? 28 | 29 | - Bir yöntemi, yöntem tarafından kullanılan verilerin çoğunu içeren bir sınıfa taşıyabilirsiniz. Bu, sınıfları kendi içinde daha tutarlı hale getirir. 30 | 31 | - Yöntemi çağıran sınıfın, bulunduğu sınıfa bağımlılığını azaltmak veya ortadan kaldırmak için bir yöntemi taşıyabilirsiniz. Çağıran sınıf zaten yöntemi taşımayı planladığınız sınıfa bağımlıysa bu yararlı olabilir. Bu yöntem, sınıflar arasındaki bağımlılığı azaltır. 32 | 33 | ### 🤯 Nasıl Refactor Edilir? 34 | 35 | 1. Kendi sınıfında eski yöntemin kullandığı tüm özellikleri taşıdığını doğrulayın. Bunları taşımak da iyi bir fikir olabilir. Kural olarak, eğer bir özellik yalnızca söz konusu yöntem tarafından kullanılıyorsa, özelliği mutlaka yöntemle birlikte taşımalısınız. Özellik başka yöntemler tarafından da kullanılıyorsa bu yöntemleri de taşımalısınız. Bazen çok sayıda yöntemi taşımak, farklı sınıflarla aralarında ilişkiler kurmaktan çok daha kolaydır. 36 | 37 | Yöntemin üst sınıflarda ve alt sınıflarda bildirilmediğinden yani kullanılmadığından emin olun. Bu durumda, donör sınıflar arasında bölünmüş bir yöntemin değişen işlevselliğini sağlamak için ya taşımaktan kaçınmanız ya da alıcı sınıfta bir tür çok biçimlilik (polymorphism) uygulamanız gerekecektir. 38 | 39 | 2. Alıcı sınıfında yeni yöntemi tanımlayın. Yeni sınıfta metoda daha uygun olan yeni bir isim vermeyi de göz önünde bulundurabilirsiniz. 40 | 41 | 3. Alıcı sınıfına nasıl referans vereceğinize karar verin. Uygun bir nesneyi döndüren bir alanınız veya yönteminiz zaten olabilir, ancak yoksa alıcı sınıfın nesnesini depolamak için yeni bir yöntem veya alan oluşturmanız gerekecektir. 42 | 43 | Artık alıcı nesneye ve onun sınıfındaki yeni bir yönteme referans vermenin bir yoluna sahipsiniz. Tüm bunları elinizin altında tutarak eski yöntemi yeni yöntemin referansına dönüştürebilirsiniz. 44 | 45 | 4. Bir göz atın: eski yöntemi tamamen silebilir misiniz? Eğer öyleyse, eski yöntemin kullanıldığı her yere yeni yönteme bir referans oluşturun. 46 | 47 | ## Move Field 48 | 49 | ### 🙁 Problem 50 | 51 | Bir alan (field) kendi sınıfından ziyade başka bir sınıfta daha fazla kullanılıyorsa sorun oluşturabilir. 52 | 53 |
54 | 55 | ![](https://refactoring.guru/images/refactoring/diagrams/Move%20Field%20-%20Before.png) 56 |
57 | 58 | ### 😊 Çözüm 59 | 60 | Yeni bir sınıfta bir alan (field) oluşturun ve eski alanın tüm kullanımlarını yeni oluşturulan field'a yönlendirin. 61 | 62 |
63 | 64 | ![](https://refactoring.guru/images/refactoring/diagrams/Move%20Field%20-%20After.png) 65 |
66 | 67 | ### 🤔 Neden Refactoring Uygulanmalı? 68 | 69 | Genellikle alanlar (fields), **Extract Class** tekniğinin bir parçası olarak taşınır. Alanı hangi sınıfta bırakacağınıza karar vermek zor olabilir. Temel kuralımız şu: Alanı, onu kullanan yöntemlerle aynı yere veya bu yöntemlerin çoğunun bulunduğu yere konumlandırmak daha sağlıklı olacaktır. 70 | 71 | Bu kural, alanın yanlış yere yerleştirildiği diğer durumlarda kurtarıcınız olacaktır. 72 | 73 | ### 🤯 Nasıl Refactor Edilir? 74 | 75 | 1. Eğer alan public ise, alanı private yapıp public erişim yöntemleri sağlarsanız (bunun için **Encapsulate Field** tekniğini kullanabilirsiniz) refactoring çok daha kolay olacaktır. 76 | 77 | 2. Alıcı sınıfında erişim yöntemleriyle aynı yeni bir alanı oluşturun. 78 | 79 | 3. Alıcı sınıfına nasıl erişeceğinize karar verin. Uygun nesneyi döndüren bir alanınız veya yönteminiz zaten olabilir; değilse, alıcı sınıfın nesnesini depolamak için yeni bir yöntem veya alan oluşturmanız gerekecektir. 80 | 81 | 4. Eski alana yapılan tüm referansları, alıcı sınıfındaki yöntemlere yapılan uygun çağrılarla değiştirin. Alan private değilse üst sınıfta ve alt sınıflarda bu konuyla ilgilenin. 82 | 83 | 5. Orijinal sınıftaki alanı silin. 84 | 85 | ## Extract Class 86 | 87 | ### 🙁 Problem 88 | 89 | Bir sınıf iki sınıfın işini aynı anda yapmaya çalıştığında sorun ortaya çıkabilir. 90 | 91 |
92 | 93 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Class%20-%20Before.png) 94 |
95 | 96 | ### 😊 Çözüm 97 | 98 | Yeni bir sınıf oluşturun ve ilgili işlevsellikten sorumlu alanları ve yöntemleri yeni oluşturduğunuz bu sınıfa taşıyın. 99 | 100 |
101 | 102 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Class%20-%20After.png) 103 |
104 | 105 | ### 🤔 Neden Refactoring Uygulanmalı? 106 | 107 | Sınıflar her zaman net ve anlaşılması kolay başlar. Diğer sınıfların çalışmalarına karışmadan işlerini yaparlar ve kendi işleriyle ilgilenirler. Ancak program genişledikçe, birer birer yöntemler ve alanlar (fields) eklenir... ve sonunda bazı sınıflar, her zamankinden daha fazla sorumluluk yerine getirir. Hatta bazen birkaç sınıfın işini tek bir sınıfın sorumluluğuna bırakmış olabiliriz. 108 | 109 | ### ✅ Avantajları 110 | 111 | - Bu refactoring yöntemiyle, Tek Sorumluluk İlkesine (Single Responsibility Principle) bağlılığın korunmasına yardımcı olacaktır. Sınıflarınız kodları daha açık ve anlaşılır hale gelecektir. 112 | 113 | - Tek sorumluluk sınıfları daha güvenilirdir ve değişikliklere karşı daha dayanıklıdır. Örneğin on farklı şeyden sorumlu bir sınıfınız olduğunu varsayalım. Bu sınıfı bir şeyi daha iyi hale getirmek için değiştirdiğinizde, diğer dokuz konuda onu bozma riskiyle karşı karşıya kalırsınız. 114 | 115 | ### 🚫 Dezavantajları 116 | 117 | Bu refactoring tekniğini kullanırken aşırıya kaçarsanız **Inline Class** yöntemine başvurmak zorunda kalabilirsiniz. 118 | 119 | ### 🤯 Nasıl Refactor Edilir? 120 | 121 | Başlamadan önce sınıfın sorumluluklarını tam olarak nasıl bölmek istediğinize karar verin. 122 | 123 | 1. İlgili işlevselliği içerecek yeni bir sınıf oluşturun. 124 | 125 | 2. Eski sınıf ile yeni sınıf arasında bir ilişki oluşturun. İdeal durumda bu ilişki tek yönlüdür. Bu tek yönlü ilişki, ikinci sınıfın herhangi bir sorun olmadan yeniden kullanılmasına olanak tanır. Ancak iki yönlü bir ilişkinin gerekli olduğunu düşünüyorsanız bu da elbette her zaman kurulabilir. Sizi engelleyen bir kural veya durum yoktur. 126 | 127 | 3. Yeni sınıfa taşımaya karar verdiğiniz her alan ve yöntem için **Move Field** ve **Move Method** tekniklerini kullanın. Yöntemler için, hata yapma riskini azaltmak amacıyla private olanlarla başlayın. En sonunda hata-düzeltme zincirinden kaçınmak için, her seferinde biraz yer değiştirmeye çalışın ve her taşımadan sonra sonuçları test edin. 128 | 129 | Taşıma işlemini tamamladıktan sonra ortaya çıkan sınıfları bir kez daha kontrol edin. Sorumlulukları değişen eski bir sınıf, daha fazla netlik sağlamak amacıyla yeniden adlandırılabilir. Varsa, iki yönlü sınıf ilişkilerinden kurtulup kurtulamayacağınızı görmek için tekrar kontrol edin. 130 | 131 | 4. Ayrıca yeni sınıfa dışarıdan erişilebilirliği de düşünün. Sınıfı private hale getirerek, eski sınıfın alanları aracılığıyla yöneterek, sınıfı tamamen istemciden gizleyebilirsiniz. Alternatif olarak, istemcinin değerleri doğrudan değiştirmesine izin vererek bunu herkese açık (public) hale getirebilirsiniz. Buradaki kararınız, yeni sınıftaki değerlerde beklenmeyen doğrudan değişiklikler yapıldığında eski sınıfın davranışı açısından ne kadar güvenli olduğuna bağlıdır. 132 | 133 | 134 | ## Inline Class 135 | 136 | ### 🙁 Problem 137 | 138 | Bir sınıf neredeyse hiçbir şey yapmaz ve hiçbir şeyden sorumlu değildir. Yani neredeyse görevi olmayan kullanılmayan bir sınıf vardır. Bu projeniz için sorun olabilir. 139 | 140 |
141 | 142 | ![](https://refactoring.guru/images/refactoring/diagrams/Inline%20Class%20-%20Before.png) 143 |
144 | 145 | ### 😊 Çözüm 146 | 147 | Tüm özellikleri sınıftan diğer bir sınıfa taşıyın. 148 | 149 |
150 | 151 | ![](https://refactoring.guru/images/refactoring/diagrams/Inline%20Class%20-%20After.png) 152 |
153 | 154 | ### 🤔 Neden Refactoring Uygulanmalı? 155 | 156 | Çoğu zaman bu tekniğe, bir sınıfın özellikleri diğer sınıflara aktarıldıktan ve o sınıfa yapacak çok az şey bırakıldıktan sonra ihtiyaç duyulur. 157 | 158 | ### ✅ Avantajları 159 | 160 | Gereksiz sınıfları ortadan kaldırmak, bilgisayardaki işletim belleğini ve kafanızdaki bant genişliğini serbest bırakır. 161 | 162 | ### 🤯 Nasıl Refactor Edilir? 163 | 164 | 1. Alıcı sınıfında, verici sınıfında (neredeyse iş yapmayan sınıf) bulunan ortak alanları ve yöntemleri oluşturun. Yöntemler, verici sınıfının eşdeğer yöntemlerine atıfta bulunmalıdır. 165 | 166 | 2. Verici sınıfına yapılan tüm referansları, alıcı sınıfın alanlarına ve yöntemlerine yapılan referanslarla değiştirin. 167 | 168 | 3. Şimdi programı test edin ve herhangi bir hata eklenmediğinden emin olun. Testler her şeyin yolunda gittiğini gösteriyorsa, tüm işlevleri orijinal sınıftan alıcı sınıfına tamamen aktarmak için **Move Method** ve **Move Field** tekniklerini kullanmaya başlayın. Orijinal sınıf tamamen boşalana kadar bunu yapmaya devam edin. 169 | 170 | 4. Orijinal sınıfı silin. 171 | 172 | 173 | ## Hide Delegate 174 | 175 | ### 🙁 Problem 176 | 177 | İstemci, A nesnesinin bir alanından veya yönteminden B nesnesini alır. İstemci daha sonra B nesnesinin yöntemini çağırır. 178 | 179 |
180 | 181 | ![](https://refactoring.guru/images/refactoring/diagrams/Hide%20Delegate%20-%20Before.png) 182 |
183 | 184 | ### 😊 Çözüm 185 | 186 | A sınıfında, çağrıyı B nesnesine devreden yeni bir yöntem oluşturun. Artık istemci B sınıfı hakkında bilgi sahibi değil veya buna bağlı değil. 187 | 188 |
189 | 190 | ![](https://refactoring.guru/images/refactoring/diagrams/Hide%20Delegate%20-%20After.png) 191 |
192 | 193 | ### 🤔 Neden Refactoring Uygulanmalı? 194 | 195 | 196 | Başlangıç ​​olarak terminolojiye bakalım: 197 | 198 | - Sunucu (server), istemcinin doğrudan erişime sahip olduğu nesnedir. 199 | 200 | - Temsilci (delegate), istemcinin ihtiyaç duyduğu işlevselliği içeren son nesnedir. 201 | 202 | Bir istemci başka bir nesneden bir nesne talep ettiğinde, ardından ikinci nesne başka bir nesne talep ettiğinde ve bu şekilde devam ettiğinde bir çağrı zinciri ortaya çıkar. Bu çağrı dizileri, istemcinin sınıf yapısı boyunca gezinmesini gerektirir. Bu karşılıklı ilişkilerdeki herhangi bir değişiklik, istemci tarafında da değişiklik yapılmasını gerektirecektir. 203 | 204 | ### ✅ Avantajları 205 | 206 | Temsilciyi (delegation), istemciden gizleyin. İstemci, kodunun nesneler arasındaki ilişkileri hakkında ne kadar az bilgiye ihtiyacı olursa, programınızda değişiklik yapmak o kadar kolay olacaktır. 207 | 208 | ### 🚫 Dezavantajları 209 | 210 | Aşırı sayıda temsilci (delegation) yöntemi oluşturmanız gerekiyorsa, sunucu sınıfı gereksiz bir aracı olma riskiyle karşı karşıya kalır ve bu da **Middle Man** fazlalığına yol açar. 211 | 212 | ### 🤯 Nasıl Refactor Edilir? 213 | 214 | 1. İstemci tarafından çağrılan temsilci sınıfının her bir yöntemi için; sunucu sınıfında, çağrıyı temsilci sınıfına devreden bir yöntem oluşturun. 215 | 216 | 2. İstemci kodunu, sunucu sınıfının yöntemlerini çağıracak şekilde değiştirin. 217 | 218 | 3. Eğer değişiklikleriniz istemcinin temsilci sınıfına ihtiyaç duymasını engelliyorsa, sunucu sınıfından temsilci sınıfına erişim yöntemini kaldırabilirsiniz (başlangıçta temsilci sınıfını almak için kullanılan yöntem). 219 | 220 | ## Remove Middle Man 221 | 222 | ### 🙁 Problem 223 | 224 | Bir sınıfın, diğer nesnelere yetki veren çok fazla yöntemi olması sorun olabilir. 225 | 226 |
227 | 228 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Middle%20Man%20-%20Before.png) 229 |
230 | 231 | ### 😊 Çözüm 232 | 233 | Bu yöntemleri silin ve istemciyi doğrudan son yöntemleri çağırmaya zorlayın. 234 | 235 |
236 | 237 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Middle%20Man%20-%20After.png) 238 |
239 | 240 | ### 🤔 Neden Refactoring Uygulanmalı? 241 | 242 | Bu tekniği açıklamak için **Hide Delegate** tekniğini terimlerini kullanacağız: 243 | 244 | - Sunucu (server), istemcinin doğrudan erişime sahip olduğu nesnedir. 245 | 246 | - Temsilci (delegate), istemcinin ihtiyaç duyduğu işlevselliği içeren son nesnedir. 247 | 248 | İki tür sorun vardır: 249 | 250 | 1. Sunucu sınıfı hiçbir şey yapmaz ve yalnızca gereksiz karmaşıklık yaratır. Bu durumda bu sınıfa ihtiyaç olup olmadığı üzerine düşünmek gerekir. 251 | 2. Temsilciye (delegate) her yeni özellik eklendiğinde, sunucu sınıfında bunun için bir yetki verme (delegating) yöntemi oluşturmanız gerekir. Çok fazla değişiklik yapılırsa bu oldukça yorucu olacaktır. 252 | 253 | ### 🤯 Nasıl Refactor Edilir? 254 | 255 | 1. Sunucu sınıfı nesnesinden temsilci sınıfı nesnesine erişmek için bir alıcı (getter) oluşturun. 256 | 257 | 2. Sunucu sınıfındaki yetki verme yöntemlerine yapılan çağrıları, temsilci sınıfındaki yöntemlere yönelik doğrudan çağrılarla değiştirin. 258 | 259 | 260 | ## Introduce Foreign Method 261 | 262 | ### 🙁 Problem 263 | 264 | Yardımcı program sınıfı ihtiyacınız olan yöntemi içermez ve yöntemi sınıfa ekleyemezseniz bu projeniz için sorun olabilir. 265 | 266 | ```java 267 | class Report { 268 | // ... 269 | void sendReport() { 270 | Date nextDay = new Date(previousEnd.getYear(), 271 | previousEnd.getMonth(), previousEnd.getDate() + 1); 272 | // ... 273 | } 274 | } 275 | ``` 276 | 277 | ### 😊 Çözüm 278 | 279 | Yöntemi bir istemci sınıfına ekleyin ve yardımcı program sınıfının bir nesnesini argüman olarak ona iletin. 280 | 281 | ```java 282 | class Report { 283 | // ... 284 | void sendReport() { 285 | Date newStart = nextDay(previousEnd); 286 | // ... 287 | } 288 | private static Date nextDay(Date arg) { 289 | return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1); 290 | } 291 | } 292 | ``` 293 | 294 | ### 🤔 Neden Refactoring Uygulanmalı? 295 | 296 | Belirli bir sınıfın verilerini ve yöntemlerini kullanan bir kodunuz var. Kodun sınıftaki yeni bir yöntemin içinde daha iyi konumlanacağını ve çalışacağını fark ediyorsunuz. Ancak yöntemi sınıfa ekleyemezsiniz, çünkü örneğin sınıf bir üçüncü taraf kütüphanede bulunuyor. 297 | 298 | Yönteme taşımak istediğiniz kod programınızın farklı yerlerinde birkaç kez tekrarlandığında, bu yeniden düzenleme işleminin büyük bir getirisi olacaktır. 299 | 300 | Utility sınıfının bir nesnesini yeni yöntemin parametrelerine geçirdiğinizden, tüm alanlarına erişebilirsiniz. Yöntemin içinde, yöntem yardımcı program sınıfının bir parçasıymış gibi istediğiniz hemen hemen her şeyi yapabilirsiniz. 301 | 302 | ### ✅ Avantajları 303 | 304 | Kod tekrarını ortadan kaldırır. Kodunuz birkaç yerde tekrarlanırsa, bu kod parçalarını bir yöntem çağrısıyla değiştirebilirsiniz. Bu, yabancı yöntemin optimal olmayan bir yerde bulunduğu düşünülse bile tekrarlı koddan daha iyidir. 305 | 306 | ### 🚫 Dezavantajları 307 | 308 | Bir istemci sınıfında bir yardımcı sınıf yöntemine sahip olmanın nedenleri, sizden sonra kodu sürdüren kişi için her zaman temiz kod olmayacaktır. Yöntem diğer sınıflarda da kullanılabiliyorsa, yardımcı sınıf için bir sarmalayıcı oluşturup yöntemi oraya yerleştirerek fayda sağlayabilirsiniz. Bu, bu tür birkaç faydalı yöntem olduğunda da faydalıdır. **Introduce Local Extension** tekniği bu konuda yardımcı olabilir. 309 | 310 | ### 🤯 Nasıl Refactor Edilir? 311 | 312 | 1. İstemci sınıfında yeni bir yöntem oluşturun. 313 | 314 | 2. Oluşturulan bu yöntemde, yardımcı program sınıfının nesnesinin iletileceği bir parametre oluşturun. Bu nesne client sınıfından alınabiliyorsa böyle bir parametre oluşturmanıza gerek yoktur. 315 | 316 | 3. İlgili kod parçalarını bu yönteme çıkarın (Extract) ve bunları yöntem çağrılarıyla değiştirin. 317 | 318 | 4. Daha sonra mümkün olması durumunda, bu yöntemin bir yardımcı program sınıfına yerleştirilmesi tavsiyesiyle birlikte, yöntemin yorumlarına Yabancı yöntem etiketini bıraktığınızdan emin olun. Bu, gelecekte yazılımın bakımını yapacak kişiler için bu yöntemin neden bu özel sınıfta yer aldığını anlamayı kolaylaştıracaktır. 319 | 320 | ## Introduce Local Extension 321 | 322 | ### 🙁 Problem 323 | 324 | Yardımcı program sınıfı ihtiyacınız olan yöntemi içermez ve yöntemi sınıfa ekleyemezseniz bu projeniz için sorun olabilir. 325 | 326 |
327 | 328 | ![](https://refactoring.guru/images/refactoring/diagrams/Introduce%20Local%20Extension%20-%20Before.png) 329 |
330 | 331 | ### 😊 Çözüm 332 | 333 | Yöntemleri içeren yeni bir sınıf oluşturun. Sonrasında bu sınıfı yardımcı program sınıfının alt öğesi veya sarmalayıcısı yapın. 334 | 335 |
336 | 337 | ![](https://refactoring.guru/images/refactoring/diagrams/Introduce%20Local%20Extension%20-%20After.png) 338 |
339 | 340 | ### 🤔 Neden Refactoring Uygulanmalı? 341 | 342 | Kullandığınız sınıf ihtiyacınız olan yöntemlere sahip olmayabilir. Daha da kötüsü, bu yöntemleri ekleyemezsiniz (çünkü sınıflar örneğin üçüncü taraf bir kütüphanededir). İki çıkış yolu var: 343 | 344 | 1. İlgili sınıftan, yöntemleri içeren ve diğer her şeyi ana sınıftan miras alan bir alt sınıf oluşturun. Bu yol daha kolaydır ancak bazen yardımcı program sınıfının kendisi tarafından engellenir (`final` anahtar kelimesi nedeniyle). 345 | 2. Tüm yeni yöntemleri içeren bir sarmalayıcı (wrapper) sınıf oluşturun ve başka bir yerde ilgili nesneye yardımcı program sınıfından yetki verin. Bu yöntem daha fazla iş gerektirir çünkü yalnızca sarmalayıcı ve yardımcı program nesnesi arasındaki ilişkiyi sürdürmek için koda değil, aynı zamanda yardımcı program sınıfının genel arayüzünü taklit etmek için çok sayıda basit yetki verme yöntemine de ihtiyacınız vardır. 346 | 347 | ### ✅ Avantajları 348 | 349 | Ek yöntemleri ayrı bir uzantı sınıfına (sarmalayıcı veya alt sınıf) taşıyarak, istemci sınıflarını uymayan kodlarla doldurmaktan kaçınırsınız. Program bileşenleri daha tutarlıdır ve daha fazla yeniden kullanılabilir. 350 | 351 | ### 🤯 Nasıl Refactor Edilir? 352 | 353 | 1. Yeni bir uzantı sınıfı oluşturun: 354 | - Seçenek A: Sınıfı yardımcı program sınıfının bir çocuğu (child-class) yapın. 355 | - Seçenek B: Eğer bir sarmalayıcı yapmaya karar verdiyseniz, içinde delegasyonun yapılacağı yardımcı program sınıfı nesnesini depolamak için bir alan oluşturun. Bu seçeneği kullanırken, yardımcı program sınıfının genel yöntemlerini tekrarlayan ve yardımcı program nesnesinin yöntemlerine basit temsilci atama içeren yöntemler de oluşturmanız gerekecektir. 356 | 357 | 2. Yardımcı sınıfının yapıcısının parametrelerini kullanan bir yapıcı oluşturun. 358 | 359 | 3. Ayrıca parametrelerinde yalnızca orijinal sınıfın nesnesini alan alternatif bir dönüştürme yapıcısı (constructor) oluşturun. Bu, orijinal sınıfın nesnelerinin yerine uzantının yerleştirilmesine yardımcı olacaktır. 360 | 361 | 4. Sınıfta yeni, genişletilmiş yöntemler oluşturun. Yabancı yöntemleri diğer sınıflardan bu sınıfa taşıyın veya yabancı yöntemlerin işlevleri uzantıda zaten mevcutsa silin. 362 | 363 | 5. Yardımcı program sınıfının kullanımını, işlevselliğinin gerekli olduğu yerlerde yeni uzantı sınıfıyla değiştirin. 364 | 365 | -------------------------------------------------------------------------------- /refactoring-techniques/simplifying-conditional-expressions.md: -------------------------------------------------------------------------------- 1 | # Koşullu İfadeleri Basitleştirme (Simplifying Conditional Expressions) 2 | 3 | Koşullu ifadelerin mantıkları projeniz/programınız büyüdükçe giderek daha karmaşık hale gelir. Bu durumla mücadele edebileceğimiz oldukça fazla refactoring tekniği bulunmaktadır. 4 | 5 | ## Decompose Conditional 6 | 7 | ### 🙁 Problem 8 | 9 | Karmaşık bir koşulunuz var (`if-then`/`else` veya `switch`) bu durumda projedeki diğer geliştiriciler bu koşullu ifadeyi anlamak için zaman kaybedecektir. 10 | 11 | ```java 12 | if (date.before(SUMMER_START) || date.after(SUMMER_END)) { 13 | charge = quantity * winterRate + winterServiceCharge; 14 | } 15 | else { 16 | charge = quantity * summerRate; 17 | } 18 | ``` 19 | 20 | ### 😊 Çözüm 21 | 22 | Koşulun karmaşık kısımlarını ayrı yöntemlere ayırabilirsiniz. Bu okunurluğu arttıracaktır. 23 | 24 | ```java 25 | if (isSummer(date)) { 26 | charge = summerCharge(quantity); 27 | } 28 | else { 29 | charge = winterCharge(quantity); 30 | } 31 | ``` 32 | 33 | ### 🤔 Neden Refactoring Uygulanmalı? 34 | 35 | Bir kod parçası ne kadar uzun olursa anlaşılması da o kadar zor olur. Kodunuz, koşullarla doldurulduğunda anlaşılması daha da gü. hale gelir: 36 | 37 | - `then` bloğundaki kodun ne yaptığını bulmakla meşgulken ilgili koşulun ne olduğunu unutabilirsiniz. Ki uzun koşulları ifadelerde bu çok olağan bir durumdur. 38 | 39 | - `else` kısnını ayrıştırmakla meşgulken, kodun `then` kısmının ne yaptığını unutursunuz. 40 | 41 | ### ✅ Avantajları 42 | 43 | - Koşullu kodu açıkça adlandırılmış yöntemlere çıkararak, kodda daha sonra değişiklik veya bakımını yapacak olan kişinin (örneğin, iki ay sonraki siz) hayatını kolaylaştırırsınız. 44 | 45 | - Bu refactoring tekniği aynı zamanda koşullardaki kısa ifadeler için de geçerlidir. `isSalaryDay()` işlevi, tarihleri ​​karşılaştırmaya yönelik koddan çok daha güzel ve daha açıklayıcıdır. 46 | 47 | ### 🤯 Nasıl Refactor Edilir? 48 | 49 | 1. Koşulu, **Extract Method.** tekniği aracılığıyla ayrı bir yönteme çıkarın. 50 | 51 | 2. `then` ve `else` blokları için işlemi tekrarlayın. 52 | 53 | ## Consolidate Conditional Expression 54 | 55 | ### 🙁 Problem 56 | 57 | Aynı sonuca veya eyleme yol açan birden fazla koşulunuz olduğu durumlarda bazı sorunla karşılaşabilirsiniz. Sonuçta koşullu ifadeniz yanlış koşulda takılabilir. 58 | 59 | ```java 60 | double disabilityAmount() { 61 | if (seniority < 2) { 62 | return 0; 63 | } 64 | if (monthsDisabled > 12) { 65 | return 0; 66 | } 67 | if (isPartTime) { 68 | return 0; 69 | } 70 | // Compute the disability amount. 71 | // ... 72 | } 73 | ``` 74 | 75 | ### 😊 Çözüm 76 | 77 | Tüm bu koşul cümlelerini tek bir ifadede birleştirin. 78 | 79 | ```java 80 | double disabilityAmount() { 81 | if (isNotEligibleForDisability()) { 82 | return 0; 83 | } 84 | // Compute the disability amount. 85 | // ... 86 | } 87 | ``` 88 | 89 | ### 🤔 Neden Refactoring Uygulanmalı? 90 | 91 | Kodunuz aynı eylemleri gerçekleştiren birçok alternatif operatör içerir. Operatörlerin neden bölündüğü belli bile olmayacaktır. Anlaması ise oldukça güçleşecektir. 92 | 93 | Birleştirmenin temel amacı, daha fazla netlik sağlamak için koşulu ayrı bir yönteme çıkarmaktır. 94 | 95 | ### ✅ Avantajları 96 | 97 | - Yinelenen kontrol akış kodunu, ortadan kaldırır. Böylelikle daha net bir kod oluşur. Aynı amaca sahip yani aynı değeri döndüren birden fazla koşulu birleştirmek, tek bir eyleme yol açan yalnızca tek bir karmaşık kontrol yaptığınızı göstermenize yardımcı olur. 98 | 99 | - Tüm operatörleri birleştirerek artık bu karmaşık ifadeyi, koşulun amacını açıklayan bir isimle yeni bir yöntemde izole edebilirsiniz. Böylelikle diğer geliştiriciler yöntemin adına bakarak bu koşulun ne yaptığını anlayabilir. 100 | 101 | ### 🤯 Nasıl Refactor Edilir? 102 | 103 | Refactoring yapmadan önce, yalnızca değerleri döndürmek yerine, koşullu ifadelerin herhangi bir yan etkisi (side effects) olmadığından veya herhangi bir değeri/değişkeni değiştirmediğinden emin olun. Bir koşulun sonuçlarına göre bir değişkende bir değişiklik olduğu gibi, operatörün içinde yürütülen kodda yan etkiler gizleniyor olabilir. Tüm bunlara refactoring sırasında dikkat etmelisiniz. 104 | 105 | 1. Koşullu ifadeleri `and` ve `or` kullanarak tek bir ifadede birleştirin. Konsolidasyon sırasında genel bir kural olarak: 106 | - İç içe geçmiş koşullar `and` kullanılarak birleştirilir. 107 | - Ardışık koşul cümleleri `or` ile birleştirilir. 108 | 2. Operatör koşullarında **Extract Methods** tekniği uygulayın ve yönteme, ifadenin amacını yansıtan bir ad verin. 109 | 110 | ## Consolidate Duplicate Conditional Fragments 111 | 112 | ### 🙁 Problem 113 | 114 | Bir koşullunun tüm dallarında aynı kod bulunabilir, bu durum kodu okuyan kişinin koşullu ifadenin amacını anlamasını zorlaştırır. 115 | 116 | ```java 117 | if (isSpecialDeal()) { 118 | total = price * 0.95; 119 | send(); 120 | } 121 | else { 122 | total = price * 0.98; 123 | send(); 124 | } 125 | ``` 126 | 127 | ### 😊 Çözüm 128 | 129 | Kodu koşulun dışına taşıyın. 130 | 131 | ```java 132 | if (isSpecialDeal()) { 133 | total = price * 0.95; 134 | } 135 | else { 136 | total = price * 0.98; 137 | } 138 | send(); 139 | ``` 140 | 141 | ### 🤔 Neden Refactoring Uygulanmalı? 142 | 143 | Bir koşulun tüm dallarında yinelenen kod bulunur; bu, genellikle koşulun dalları içindeki kodun evriminin bir sonucudur. Takım gelişimi buna katkıda bulunan bir faktör olabilir. 144 | 145 | ### ✅ Avantajları 146 | 147 | Kod tekrarını azaltır. 148 | 149 | ### 🤯 Nasıl Refactor Edilir? 150 | 151 | 1. Duplicate edilmiş kod koşullu ifadelerin başındaysa, kodu koşullu dallanmadan önceki bir yere taşıyın. 152 | 153 | 2. Eğer kod dalların sonunda çalıştırılıyorsa, onu koşuldan dışarı çıkarın. Sonrasında koşullu ifadelerin sonra yerleştirin. 154 | 155 | 3. Yinelenen kod dalların içinde rastgele yerleştirilmişse, sonraki kodun sonucunu değiştirip değiştirmediğine bağlı olarak ilk önce kodu dalın başına veya sonuna taşımayı deneyin. 156 | 157 | 4. Uygunsa ve duplicate edilmiş kod bir satırdan uzunsa, **Extract Methods** tekniği kullanmayı deneyin. Böylelikle kod daha temiz hale gelir. 158 | 159 | 160 | ## Remove Control Flag 161 | 162 | ### 🙁 Problem 163 | 164 | Birden çok boolean ifadesi için kontrol bayrağı görevi gören bir boolean değişkeniniz varsa bu durum kodun okunmasını zorlaştırabilir. 165 | 166 | ### 😊 Çözüm 167 | 168 | Değişken yerine `break`, `continue` ve `return` anahtar kelimelerini kullanın. Böylelikle koşullu ifadeye bakan herkes aynı durumu hızlıca anlayabilir. 169 | 170 | ### 🤔 Neden Refactoring Uygulanmalı? 171 | 172 | Modern programlama dillerinde, döngülerdeki ve diğer karmaşık yapılardaki kontrol akışını değiştirmek için özel operatörlerimiz olduğundan, bu tarz kullanımlar kodunuzu daha temiz gösterecektir. Ekstra bir bayrak eklemek, kodu karmaşık kılar. 173 | 174 | - `break`: Döngüyü durdurur 175 | - `continue`: Geçerli döngünün yürütülmesini durdurur ve bir sonraki yinelemede döngü koşullarını kontrol etmeye gider 176 | - `return`: Tüm fonksiyonun yürütülmesini durdurur ve operatörde verilmişse sonucunu döndürür. 177 | 178 | ### ✅ Avantajları 179 | 180 | Kontrol bayrağı kodu genellikle kontrol akışı operatörleriyle yazılan koddan çok daha hantaldır. 181 | 182 | ### 🤯 Nasıl Refactor Edilir? 183 | 184 | 1. Döngüden veya geçerli yinelemeden çıkışa neden olan kontrol bayrağına değer atamasını bulun. 185 | 186 | 2. Eğer bu bir döngüden çıkışsa, bunu `break` ile değiştirin; Bu bir yinelemeden çıkışsa `continue` veya bu değeri işlevden döndürmeniz gerekiyorsa `return` değerlerini kullanın. 187 | 188 | 3. Kontrol bayrağıyla ilişkili kalan kodu ve kontrolleri kaldırın. 189 | 190 | 191 | ## Replace Nested Conditional with Guard Clauses 192 | 193 | ### 🙁 Problem 194 | 195 | Bir grup iç içe geçmiş koşul cümleniz var ve kod yürütmenin normal akışını belirlemek zor olması kod içerisinde karmaşıklık oluşturur. Sonradan projeye dahil olan bir kişi belkide aynı amaca hizmet edeceğini anlayamayacağı için kod tekrarına sebep olabilir. 196 | 197 | ```java 198 | public double getPayAmount() { 199 | double result; 200 | if (isDead){ 201 | result = deadAmount(); 202 | } 203 | else { 204 | if (isSeparated){ 205 | result = separatedAmount(); 206 | } 207 | else { 208 | if (isRetired){ 209 | result = retiredAmount(); 210 | } 211 | else{ 212 | result = normalPayAmount(); 213 | } 214 | } 215 | } 216 | return result; 217 | } 218 | ``` 219 | 220 | ### 😊 Çözüm 221 | 222 | Tüm özel kontrolleri ve uç durumları (edge cases) ayrı maddelere ayırın ve bunları ana kontrollerin önüne yerleştirin. İdeal olarak, birbiri ardına gelen düz bir koşul listesine sahip olmalısınız. 223 | 224 | ```java 225 | public double getPayAmount() { 226 | if (isDead){ 227 | return deadAmount(); 228 | } 229 | if (isSeparated){ 230 | return separatedAmount(); 231 | } 232 | if (isRetired){ 233 | return retiredAmount(); 234 | } 235 | return normalPayAmount(); 236 | } 237 | ``` 238 | 239 | ### 🤔 Neden Refactoring Uygulanmalı? 240 | 241 | Her bir iç içelik düzeyinin girintileri, acı ve keder yönünü sağa doğru işaret eden bir ok oluşturur: 242 | 243 | ```java 244 | if () { 245 | if () { 246 | do { 247 | if () { 248 | if () { 249 | if () { 250 | ... 251 | } 252 | } 253 | ... 254 | } 255 | ... 256 | } 257 | while (); 258 | ... 259 | } 260 | else { 261 | ... 262 | } 263 | } 264 | ``` 265 | 266 | Kod yürütmenin normal akışı hemen belli olmadığından, her koşulun ne yaptığını ve nasıl yaptığını anlamak zordur. Bu koşullar, her bir koşulun, genel yapıyı optimize etmeye yönelik herhangi bir düşünce olmaksızın geçici bir önlem olarak eklendiği, karışık bir evrimi gösterir. 267 | 268 | Durumu basitleştirmek için özel durumları, yürütmeyi hemen sonlandıran ve koruma hükümleri doğruysa boş değer döndüren ayrı koşullara ayırın. Aslında buradaki göreviniz yapıyı düz (flat) hale getirmektir. Böylelikle koşullu ifade daha anlaşılabilir olur. 269 | 270 | ### 🤯 Nasıl Refactor Edilir? 271 | 272 | Kodu yan etkilerden (side effects) kurtarmaya çalışın; **Separate Query from Modifier** tekniği bu amaç için yararlı olabilir. Bu çözüm aşağıda açıklanan reshuffling için gerekli olacaktır. 273 | 274 | 1. Bir hatanın çağrılmasına veya yöntemden bir değerin anında döndürülmesine yol açan tüm koruma cümlelerini ayırın. Bu koşulları yöntemin başına yerleştirin. Böylelikle kod tüm koşulları takip etmeden erkenden işlemini sonlandırabilir. 275 | 276 | 2. Yeniden düzenleme tamamlandıktan ve tüm testler başarıyla tamamlandıktan sonra, aynı istisnalara veya döndürülen değerlere yol açan koruma cümleleri için **Consolidate Conditional Expression** tekniğini kullanıp kullanamayacağınıza bakın. 277 | 278 | 279 | ## Replace Conditional with Polymorphism 280 | 281 | ### 🙁 Problem 282 | 283 | Nesne türüne veya özelliklerine bağlı olarak çeşitli eylemleri gerçekleştiren bir koşulunuz olduğunu varsayalım. Koşullu ifade zamanla uzadıkça uzayabilir, bu durum da anlaşılmasını güçlendirir. 284 | 285 | ```java 286 | class Bird { 287 | // ... 288 | double getSpeed() { 289 | switch (type) { 290 | case EUROPEAN: 291 | return getBaseSpeed(); 292 | case AFRICAN: 293 | return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; 294 | case NORWEGIAN_BLUE: 295 | return (isNailed) ? 0 : getBaseSpeed(voltage); 296 | } 297 | throw new RuntimeException("Should be unreachable"); 298 | } 299 | } 300 | ``` 301 | 302 | ### 😊 Çözüm 303 | 304 | Koşulun dallarıyla eşleşen alt sınıflar oluşturun. Bunlarda, paylaşılan bir yöntem oluşturun ve kodu, koşulun karşılık gelen dalından ona taşıyın. Daha sonra koşullu ifadeyi, ilgili yöntem çağrısıyla değiştirin. Sonuç olarak, nesne sınıfına bağlı olarak polimorfizm yoluyla uygun uygulamaya ulaşılacaktır. 305 | 306 | ```java 307 | abstract class Bird { 308 | // ... 309 | abstract double getSpeed(); 310 | } 311 | 312 | class European extends Bird { 313 | double getSpeed() { 314 | return getBaseSpeed(); 315 | } 316 | } 317 | class African extends Bird { 318 | double getSpeed() { 319 | return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; 320 | } 321 | } 322 | class NorwegianBlue extends Bird { 323 | double getSpeed() { 324 | return (isNailed) ? 0 : getBaseSpeed(voltage); 325 | } 326 | } 327 | 328 | // Somewhere in client code 329 | speed = bird.getSpeed(); 330 | ``` 331 | 332 | ### 🤔 Neden Refactoring Uygulanmalı? 333 | 334 | Bu refactoring tekniği, kodunuz aşağıda listelenenlere göre değişen çeşitli görevleri gerçekleştiren, operatörler içeriyorsa yardımcı olabilir: 335 | 336 | - Uyguladığı nesnenin veya arayüzün sınıfı 337 | - Bir nesnenin alanının değeri 338 | - Bir nesnenin yöntemlerinden birinin çağrılmasının sonucu 339 | 340 | Yeni bir nesne özelliği veya türü ortaya çıkarsa, tüm benzer koşullardaki kodu aramanız ve eklemeniz gerekecektir. Dolayısıyla, bir nesnenin tüm yöntemlerine dağılmış birden fazla koşulu varsa, bu tekniğin faydası katlanarak artar. 341 | 342 | ### ✅ Avantajları 343 | 344 | - Bu teknik, Söyle-Sorma (Tell-Don’t-Ask) ilkesine bağlıdır: Bir nesneye durumu hakkında soru sormak ve ardından buna dayalı eylemler gerçekleştirmek yerine, nesneye ne yapması gerektiğini basitçe söylemek ve nasıl yapılacağına kendisinin karar vermesine izin vermek çok daha kolaydır. 345 | 346 | - Yinelenen kodu kaldırır. Neredeyse aynı olan birçok koşuldan kurtulursunuz. Daha temiz bir kod source elde edilir. 347 | 348 | - Yeni bir yürütme varyantı eklemeniz gerekiyorsa tek yapmanız gereken mevcut koda dokunmadan yeni bir alt sınıf eklemektir (Açık/Kapalı Prensibi). 349 | 350 | 351 | ### 🤯 Nasıl Refactor Edilir? 352 | 353 | **Refactoring'e Hazırlık** 354 | 355 | Bu refactoring tekniği için alternatif davranışları içerecek hazır bir sınıf hiyerarşisine sahip olmalısınız. Eğer böyle bir hiyerarşiniz yoksa bir tane oluşturun. Diğer teknikler bunun gerçekleşmesine yardımcı olacaktır: 356 | 357 | - **Replace Type Code with Subclasses:** Belirli bir nesne özelliğinin tüm değerleri için alt sınıflar oluşturulacaktır. Bu yaklaşım basittir ancak nesnenin diğer özellikleri için alt sınıflar oluşturamayacağınız için daha az esnektir. 358 | 359 | - **Replace Type Code with State/Strategy:** Belirli bir nesne özelliği için bir sınıf ayrılacak ve özelliğin her değeri için ondan alt sınıflar oluşturulacaktır. Geçerli sınıf, bu türdeki nesnelere referanslar içerecek ve yürütmeyi onlara devredecektir. 360 | 361 | Aşağıdaki adımlar, hiyerarşiyi zaten oluşturduğunuzu varsayarak listelenmiştir. 362 | 363 | ** Refactoring Adımları** 364 | 365 | 1. Koşul başka eylemleri de gerçekleştiren bir yöntemdeyse, **Extract Methods** tekniğini uygulayın. 366 | 367 | 2. Her hiyerarşi alt sınıfı için, koşulluyu içeren yöntemi yeniden tanımlayın ve karşılık gelen koşullu dalın kodunu bu konuma kopyalayın. 368 | 369 | 3. Bu dalı koşuldan silin. 370 | 371 | 4. Koşullu boşalıncaya kadar değiştirmeyi tekrarlayın. Daha sonra koşulluyu silin ve yöntemin özetini bildirin. 372 | 373 | 374 | ## Introduce Null Object 375 | 376 | ### 🙁 Problem 377 | 378 | Bazı yöntemler gerçek nesneler yerine `null` değerini döndürdüğünden, kodunuzda `null` için birçok kontrol bulunur. Bu kontroller bir süre sonra tekrarlı koda ve karmaşıklığa neden olacaktır. 379 | 380 | ```java 381 | if (customer == null) { 382 | plan = BillingPlan.basic(); 383 | } 384 | else { 385 | plan = customer.getPlan(); 386 | } 387 | ``` 388 | 389 | ### 😊 Çözüm 390 | 391 | `null` yerine, varsayılan davranışı sergileyen null bir nesne döndürün. 392 | 393 | ```java 394 | class NullCustomer extends Customer { 395 | boolean isNull() { 396 | return true; 397 | } 398 | Plan getPlan() { 399 | return new NullPlan(); 400 | } 401 | // Some other NULL functionality. 402 | } 403 | 404 | // Replace null values with Null-object. 405 | customer = (order.customer != null) ? 406 | order.customer : new NullCustomer(); 407 | 408 | // Use Null-object as if it's normal subclass. 409 | plan = customer.getPlan(); 410 | ``` 411 | 412 | ### 🤔 Neden Refactoring Uygulanmalı? 413 | 414 | Düzinelerce `null` kontrolü, kodunuzu daha uzun ve daha çirkin hale getirir. 415 | 416 | ### 🚫 Dezavantajları 417 | 418 | - Koşullu ifadelerden kurtulmanın bedeli yeni bir sınıf daha yaratmaktır. Ama bu sınıfı oluşturmaya duruma göre deyecektir. 419 | 420 | ### 🤯 Nasıl Refactor Edilir? 421 | 422 | 1. Söz konusu sınıftan `null` nesne rolünü üstlenecek bir alt sınıf oluşturun. 423 | 424 | 2. Her iki sınıfta da, boş bir nesne için `true` değerini ve gerçek bir sınıf için `false` değerini döndüren `isNull()` yöntemini oluşturun. 425 | 426 | 3. Kodun gerçek bir nesne yerine `null` değerini döndürebileceği tüm yerleri bulun. Kodu, boş bir nesne döndürecek şekilde değiştirin. 427 | 428 | 4. Gerçek sınıfın değişkenlerinin `null` ile karşılaştırıldığı tüm yerleri bulun. Bu kontrolleri `isNull()` çağrısıyla değiştirin. 429 | 430 | - Bir değer `null` değerine eşit olmadığında orijinal sınıfın yöntemleri bu koşullar altında çalıştırılıyorsa, bu yöntemleri null sınıfında yeniden tanımlayın ve koşulun `else` kısmındaki kodu buraya ekleyin. Daha sonra tüm koşulu silebilirsiniz ve farklı davranışlar polimorfizm yoluyla uygulanacaktır. 431 | - Eğer işler o kadar basit değilse ve yöntemler yeniden tanımlanamıyorsa, boş bir değer durumunda gerçekleştirilmesi gereken işlemleri, `null` nesnenin yeni yöntemlerine basitçe ayıklayıp çıkaramayacağınıza bakın. Varsayılan olarak işlemler olarak `else`'deki eski kod yerine bu yöntemleri çağırın. 432 | 433 | ## Introduce Assertion 434 | 435 | ### 🙁 Problem 436 | 437 | Kodun bir kısmının doğru çalışması için belirli koşulların veya değerlerin doğru olması gerekir. Bu olağan bir durumdur, ama kodu daha temiz hale getirebilecekken neden bu şekilde ilerleyesiniz ki? 438 | 439 | ```java 440 | double getExpenseLimit() { 441 | // Should have either expense limit or 442 | // a primary project. 443 | return (expenseLimit != NULL_EXPENSE) ? 444 | expenseLimit : 445 | primaryProject.getMemberExpenseLimit(); 446 | } 447 | ``` 448 | ### 😊 Çözüm 449 | 450 | Bu varsayımları belirli assertion kontrolleriyle değiştirin. 451 | 452 | ```java 453 | double getExpenseLimit() { 454 | Assert.isTrue(expenseLimit != NULL_EXPENSE || primaryProject != null); 455 | 456 | return (expenseLimit != NULL_EXPENSE) ? 457 | expenseLimit: 458 | primaryProject.getMemberExpenseLimit(); 459 | } 460 | ``` 461 | 462 | ### 🤔 Neden Refactoring Uygulanmalı? 463 | 464 | Kodun bir kısmının, örneğin bir nesnenin mevcut durumu veya bir parametrenin veya yerel değişkenin değeri hakkında bir şeyler varsaydığını varsayalım. Genellikle bu varsayım, bir hata durumu dışında her zaman geçerli olacaktır. 465 | 466 | İlgili assertionları ekleyerek bu varsayımları açık hale getirin. Yöntem parametrelerindeki tür ipuçlarında olduğu gibi, bu assertionlar kodunuz için canlı belgeler görevi görebilir. Böylelikle bu kısımda çalışacak başka bir geliştirici olduğunda anlama sırasında vakit kaybetmeyecektir. 467 | 468 | Kodunuzun nerede assertionlara ihtiyaç duyduğunu görmek için bir kılavuz olarak, belirli bir yöntemin çalışacağı koşulları açıklayan yorumları kontrol edin. 469 | 470 | ### ✅ Avantajları 471 | 472 | Bir varsayım doğru değilse ve bu nedenle kod yanlış sonuç veriyorsa, büyük sonuçlara yol açabilir. Bu durumda, veri bozulmasına yol açmadan yürütmeyi durdurmak daha iyidir. Bu aynı zamanda programın testini gerçekleştirmenin yollarını tasarlarken gerekli testi yazmayı ihmal ettiğiniz anlamına da gelir. 473 | 474 | ### 🚫 Dezavantajları 475 | 476 | - Bazen bir hata, basit bir assertiondan daha uygundur. İstisnanın gerekli sınıfını seçebilir ve geri kalan kodun bunu doğru şekilde işlemesini sağlayabilirsiniz. 477 | 478 | - Bir istisna ne zaman basit bir assertiondan daha iyidir? İstisna, kullanıcının veya sistemin eylemlerinden kaynaklanabiliyorsa ve bu durmu istisnayla (exception) halledebilirsiniz. Öte yandan, sıradan isimsiz ve işlenmemiş istisnalar temel olarak basit assertionlara eşdeğerdir; onları ele almazsınız ve bunlar yalnızca hiçbir zaman meydana gelmemesi gereken bir program hatasının sonucu olarak ortaya çıkar. 479 | 480 | ### 🤯 Nasıl Refactor Edilir? 481 | 482 | 1. Bir koşulun varsayıldığını gördüğünüzde emin olmak için bu koşula bir assertion ekleyin. 483 | 484 | 2. İddiayı eklemek programın davranışını değiştirmemelidir. 485 | 486 | 3. Kodunuzdaki her şey için assertionlar kullanarak aşırıya kaçmayın. Yalnızca kodun doğru çalışması için gerekli olan koşulları kontrol edin. Belirli bir assertion yanlış olsa bile kodunuz normal şekilde çalışıyorsa, assertionu güvenle kaldırabilirsiniz. 487 | 488 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 📝 Refactoring Rehberi 2 | 3 | Bu repo, yazılım geliştiriciler için refactoring konusunda bir rehber niteliği taşımaktadır. Temiz kodun ne olduğundan, teknik borçtan, ne zaman ve nasıl refactoring yapılacağına kadar geniş bir yelpazede bilgi içermektedir. Ayrıca, kod kokuları olarak bilinen ve kod kalitesini düşüren sorunlara ve bu sorunların nasıl giderilebileceğine dair pratik tekniklere odaklanmaktadır. 4 | 5 | ## 🛠️ Refactoring Nedir? 6 | 7 | Refactoring, mevcut bir kod tabanını değiştirerek onu daha temiz, daha okunabilir ve daha bakımı kolay hale getirme sürecidir. Refactoring'in amacı, kodun işlevselliğini değiştirmeden, ancak daha iyi tasarlanmış, daha modüler ve daha kaliteli bir şekilde olmasını sağlamaktır. Bu süreç, kod kokularını gidermeyi, tekrar eden kodu azaltmayı, karmaşıklığı azaltmayı ve kodun genel kalitesini artırmayı hedefler. Refactoring, yazılım geliştirme sürecinde sürekli bir iyileştirme ve optimizasyon çabası olarak görülmelidir. 8 | 9 | ## 📚 İçindekiler 10 | 11 | - 📒 **Giriş** 12 | - 📖 [Clean Code (Temiz Kod)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/introduction.md#temiz-kod-clean-code) 13 | - 📖 [Technical Debt (Teknik Borç)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/introduction.md#teknik-bor%C3%A7-technical-debt) 14 | - 📖 [Ne Zaman Refactoring Yapılmalı?](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/introduction.md#ne-zaman-refactoring-yap%C4%B1lmal%C4%B1) 15 | - 📖 [Refactoring Nasıl Yapılır?](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/intro📌duction.md#refactoring-nas%C4%B1l-yap%C4%B1l%C4%B1r) 16 | 17 | - 📒 **Kod Kokuları (Code Smells)** 18 | - 📖 [Bloaters (Şişkinlik)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#bloaters-%C5%9Fi%C5%9Fkinlik) 19 | - 📌 [Long Method (Uzun Metot)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#1%EF%B8%8F%E2%83%A3-uzun-metot-long-method) 20 | - 📌 [Large Class (Büyük Sınıf)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#2%EF%B8%8F%E2%83%A3-large-class-b%C3%BCy%C3%BCk-s%C4%B1n%C4%B1f) 21 | - 📌 [Primitive Obsession (İlkel Takıntı)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#3%EF%B8%8F%E2%83%A3-primitive-obsession-i%CC%87lkel-tak%C4%B1nt%C4%B1) 22 | - 📌 [Long Parameter List (Uzun Parametre Listesi)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#4%EF%B8%8F%E2%83%A3-long-parameter-list-uzun-parametre-listesi) 23 | - 📌 [Data Clumps (Veri Kümeleri)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/bloaters.md#5%EF%B8%8F%E2%83%A3-data-clumps-veri-k%C3%BCmeleri) 24 | 25 | - 📖 [Object-Orientation Abusers (Nesne Yönelimini Kötüye Kullanma)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/object-orientation-abusers.md#object-orientation-abusers-nesne-y%C3%B6nelimini-k%C3%B6t%C3%BCye-kullanma) 26 | - 📌 [Switch Statements](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/object-orientation-abusers.md#1%EF%B8%8F%E2%83%A3-switch-statements) 27 | - 📌 [Temporary Field (Geçici Alan)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/object-orientation-abusers.md#2%EF%B8%8F%E2%83%A3-temporary-field-ge%C3%A7ici-alan) 28 | - 📌 [Refused Bequest (Reddedilen Miras)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/object-orientation-abusers.md#3%EF%B8%8F%E2%83%A3-refused-bequest-reddedilen-miras) 29 | - 📌 [Alternative Classes with Different Interfaces (Farklı Arayüzlerle Alternatif Sınıflar)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/object-orientation-abusers.md#4%EF%B8%8F%E2%83%A3-alternative-classes-with-different-interfaces-farkl%C4%B1-aray%C3%BCzlerle-alternatif-s%C4%B1n%C4%B1flar) 30 | 31 | - 📖 [Change Preventers (Önleyicileri Değiştirme)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/change-preventers.md#change-preventers-%C3%B6nleyicileri-de%C4%9Fi%C5%9Ftirme) 32 | - 📌 [Divergent Change (Iraksak Değişim)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/change-preventers.md#1%EF%B8%8F%E2%83%A3-iraksak-de%C4%9Fi%C5%9Fim-divergent-change) 33 | - 📌 [Shotgun Surgery](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/change-preventers.md#2%EF%B8%8F%E2%83%A3-shotgun-surgery) 34 | - 📌 [Parallel Inheritance Hierarchies](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/change-preventers.md#3%EF%B8%8F%E2%83%A3-parallel-inheritance-hierarchies) 35 | 36 | - 📖 [Dispensables (Vazgeçilebilir Olanlar)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#vazge%C3%A7ilebilir-dispensables) 37 | - 📌 [Comments (Yorumlar)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#1%EF%B8%8F%E2%83%A3-yorumlar-comments) 38 | - 📌 [Duplicate Code (Tekrarlı/Kopya Kod)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#2%EF%B8%8F%E2%83%A3-tekrarl%C4%B1kopya-kod-duplicate-code) 39 | - 📌 [Lazy Class (Tembel Sınıf)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#3%EF%B8%8F%E2%83%A3-tembel-s%C4%B1n%C4%B1f-lazy-class) 40 | - 📌 [Data Class (Veri Sınıfı)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#4%EF%B8%8F%E2%83%A3-veri-s%C4%B1n%C4%B1f%C4%B1-data-class) 41 | - 📌 [Dead Code (Ölü Kod)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#5%EF%B8%8F%E2%83%A3-%C3%B6l%C3%BC-kod-dead-code) 42 | - 📌 [Speculative Generality (Spekülatif Genellik)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/dispensables.md#6%EF%B8%8F%E2%83%A3-spek%C3%BClatif-genellik-speculative-generality) 43 | 44 | - 📖 [Couplers (Bağlayıcılar)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/couplers.md#ba%C4%9Flay%C4%B1c%C4%B1lar-couplers) 45 | - 📌 [Feature Envy (Özellik Kıskançlığı)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/couplers.md#1%EF%B8%8F%E2%83%A3-%C3%B6zellik-k%C4%B1skan%C3%A7l%C4%B1%C4%9F%C4%B1-feature-envy) 46 | - 📌 [Inappropriate Intimacy (Uygunsuz Yakınlık)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/couplers.md#2%EF%B8%8F%E2%83%A3-uygunsuz-yak%C4%B1nl%C4%B1k-inappropriate-intimacy) 47 | - 📌 [Message Chains (Mesaj Zincirleri)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/couplers.md#3%EF%B8%8F%E2%83%A3-mesaj-zincirleri-message-chains) 48 | - 📌 [Middle Man (Orta Adam)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/couplers.md#4%EF%B8%8F%E2%83%A3-orta-adan-middle-man) 49 | 50 | - 📖 [Other Smells (Diğer Kokular)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/other-smells.md#di%C4%9Fer-kokular-other-smells) 51 | - 📌 [Incomplete Library Class (Tamamlanmamış Kütüphane Sınıfı)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/code-smells/other-smells.md#1%EF%B8%8F%E2%83%A3-tamamlanmam%C4%B1%C5%9F-k%C3%BCt%C3%BCphane-s%C4%B1n%C4%B1f%C4%B1-incomplete-library-class) 52 | 53 | - 📒 **Refactoring Techniques (Refactoring Teknikleri)** 54 | 55 | - 📖 [Composing Methods (Oluşturma Yöntemleri)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#olu%C5%9Fturma-y%C3%B6ntemleri-composing-methods) 56 | - 📌 [Extract Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#extract-method) 57 | - 📌 [Inline Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#inline-method) 58 | - 📌 [Extract Variable](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#extract-variable) 59 | - 📌 [Inline Temp](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#inline-temp) 60 | - 📌 [Replace Temp with Query](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#replace-temp-with-query) 61 | - 📌 [Split Temporary Variable](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#split-temporary-variable) 62 | - 📌 [Remove Assignments to Parameters](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#remove-assignments-to-parameters) 63 | - 📌 [Replace Method with Method Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#replace-method-with-method-object) 64 | - 📌 [Substitute Algorithm](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/composing-methods.md#substitute-algorithm) 65 | 66 | - 📖 [Moving Features between Objects (Özellikleri Nesneler Arasında Taşıma)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#%C3%B6zellikleri-nesneler-aras%C4%B1nda-ta%C5%9F%C4%B1ma-moving-features-between-objects) 67 | - 📌 [Move Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#move-method) 68 | - 📌 [Move Field](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#move-field) 69 | - 📌 [Extract Class](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#extract-class) 70 | - 📌 [Inline Class](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#inline-class) 71 | - 📌 [Hide Delegate](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#hide-delegate) 72 | - 📌 [Remove Middle Man](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#remove-middle-man) 73 | - 📌 [Introduce Foreign Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#introduce-foreign-method) 74 | - 📌 [Introduce Local Extension](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/moving-features-between-objects.md#introduce-local-extension) 75 | 76 | - 📖 [Organizing Data (Verileri Düzenleme)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#verileri-d%C3%BCzenleme-organizing-data) 77 | - 📌 [Self Encapsulate Field](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#self-encapsulate-field) 78 | - 📌 [Replace Data Value with Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-data-value-with-object) 79 | - 📌 [Change Value to Reference](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#change-value-to-reference) 80 | - 📌 [Change Reference to Value](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#change-reference-to-value) 81 | - 📌 [Replace Array with Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-array-with-object) 82 | - 📌 [Duplicate Observed Data](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#duplicate-observed-data) 83 | - 📌 [Change Unidirectional Association to Bidirectional](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#change-unidirectional-association-to-bidirectional) 84 | - 📌 [Change Bidirectional Association to Unidirectional](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#change-bidirectional-association-to-unidirectional) 85 | - 📌 [Replace Magic Number with Symbolic Constant](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-magic-number-with-symbolic-constant) 86 | - 📌 [Encapsulate Field](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#encapsulate-field) 87 | - 📌 [Encapsulate Collection](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#encapsulate-collection) 88 | - 📌 [Replace Type Code with Class](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-type-code-with-class) 89 | - 📌 [Replace Type Code with Subclasses](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-type-code-with-subclasses) 90 | - 📌 [Replace Type Code with State/Strategy](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-type-code-with-statestrategy) 91 | - 📌 [Replace Subclass with Fields](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/organizing-data.md#replace-subclass-with-fields) 92 | 93 | - 📖 [Simplifying Conditional Expressions (Koşullu İfadeleri Basitleştirme)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#ko%C5%9Fullu-i%CC%87fadeleri-basitle%C5%9Ftirme-simplifying-conditional-expressions) 94 | - 📌 [Decompose Conditional](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#decompose-conditional) 95 | - 📌 [Consolidate Conditional Expression](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#consolidate-conditional-expression) 96 | - 📌 [Consolidate Duplicate Conditional Fragments](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#consolidate-duplicate-conditional-fragments) 97 | - 📌 [Remove Control Flag](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#remove-control-flag) 98 | - 📌 [Replace Nested Conditional with Guard Clauses](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#replace-nested-conditional-with-guard-clauses) 99 | - 📌 [Replace Conditional with Polymorphism](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#replace-conditional-with-polymorphism) 100 | - 📌 [Introduce Null Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#introduce-null-object) 101 | - 📌 [Introduce Assertion](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-conditional-expressions.md#introduce-assertion) 102 | 103 | - 📖 [Simplifying Method Calls (Yöntem Çağrılarını Basitleştirme)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#y%C3%B6ntem-%C3%A7a%C4%9Fr%C4%B1lar%C4%B1n%C4%B1-basitle%C5%9Ftirme-simplifying-method-calls) 104 | - 📌 [Rename Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#rename-method) 105 | - 📌 [Add Parameter](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#add-parameter) 106 | - 📌 [Remove Parameter](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#remove-parameter) 107 | - 📌 [Separate Query from Modifier](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#separate-query-from-modifier) 108 | - 📌 [Parameterize Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#parameterize-method) 109 | - 📌 [Replace Parameter with Explicit Methods](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#replace-parameter-with-explicit-methods) 110 | - 📌 [Preserve Whole Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#preserve-whole-object) 111 | - 📌 [Replace Parameter with Method Call](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#replace-parameter-with-method-call) 112 | - 📌 [Introduce Parameter Object](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#introduce-parameter-object) 113 | - 📌 [Remove Setting Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#remove-setting-method) 114 | - 📌 [Hide Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#hide-method) 115 | - 📌 [Replace Constructor with Factory Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#replace-constructor-with-factory-method) 116 | - 📌 [Replace Error Code with Exception](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#replace-error-code-with-exception) 117 | - 📌 [Replace Exception with Test](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/simplifying-method-calls.md#replace-exception-with-test) 118 | - 📖 [Dealing with Generalization (Genellemeyle Başa Çıkmak)](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#genellemeyle-ba%C5%9Fa-%C3%A7%C4%B1kmak-dealing-with-generalization) 119 | - 📌 [Pull Up Field](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#pull-up-field) 120 | - 📌 [Pull Up Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#pull-up-method) 121 | - 📌 [Pull Up Constructor Body](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#pull-up-constructor-body) 122 | - 📌 [Push Down Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#push-down-method) 123 | - 📌 [Push Down Field](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#push-down-field) 124 | - 📌 [Extract Subclass](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#extract-subclass) 125 | - 📌 [Extract Superclass](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#extract-superclass) 126 | - 📌 [Extract Interface](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#extract-interface) 127 | - 📌 [Collapse Hierarchy](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#collapse-hierarchy) 128 | - 📌 [Form Template Method](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#form-template-method) 129 | - 📌 [Replace Inheritance with Delegation](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#replace-inheritance-with-delegation) 130 | - 📌 [Replace Delegation with Inheritance](https://github.com/fatihes1/refactoring-turkce-kaynak/blob/main/refactoring-techniques/dealing-with-generalization.md#replace-delegation-with-inheritance) 131 | 132 | 133 | ## 🤝 Katkıda Bulunma 134 | 135 | Dökümanı oluştururken bazı yerlerde terimlerin Türkçe karşılıklarını bulmakta çok güçlük çektim. Haliyle bazı başlıklar yeteri kadar açıklayıcı ve net olmamış olabilir. Bu konularda ve elbette Türkçe çevirilere katkıda bulunmak isterseniz, lütfen aşağıdaki adımları izleyin: 136 | 137 | 1. Bu depoyu fork'layın. 138 | 2. İlgili dosyayı düzenleyin veya yeni bir bilgi ekleyin. 139 | 3. Yanlış çeviri veya ekleme yapmak istediğin yerleri özgürce düzenleyebilirsiniz! 140 | 4. Değişikliklerinizi görmem ve onaylayabilmem adına lütfen bir pull request oluşturun. 141 | 142 | Katkı contribution'larını ve önerileri memnuniyetle karşılayacağımdan emin olabilirsiniz 🤗 ! 143 | 144 | ## 📜 Lisans 145 | 146 | Bu çeviriler Refactoring Guru'nun orijinal içeriği temel alınarak oluşturulmuştur. Elbette kendimce yorumlamaya ve açıklamaya çalıştığım bir o kadar alan bulunuyor. Bununla beraber, orijinal içeriğin lisansı geçerli olacaktır. Lütfen orijinal içeriğin lisans koşullarına uyun. 147 | 148 | Orijinal İngilizce kaynağa [buradan](https://refactoring.guru/refactoring) erişebilirsiniz. 149 | -------------------------------------------------------------------------------- /refactoring-techniques/composing-methods.md: -------------------------------------------------------------------------------- 1 | # Oluşturma Yöntemleri (Composing Methods) 2 | 3 | Refactoring'in büyük bir kısmı yöntemlerin doğru şekilde oluşturulmasına ayrılmıştır. Çoğu durumda, aşırı uzun yöntemler tüm kötülüklerin anası olarak düşünülebilir. Bu yöntemlerin içindeki kod değişkenleri, yürütme mantığını gizler ve yöntemin anlaşılmasını son derece zorlaştırır, hatta değiştirilmesini daha da zorlaştırır. 4 | 5 | Bu gruptaki refactoring teknikleri yöntemlerin kullanımını kolaylaştırır, kod tekrarını ortadan kaldırır. Böylelikle gelecekteki iyileştirmelerin önünü açar. 6 | 7 | ## Extract Method 8 | 9 | ### 🙁 Problem 10 | 11 | Birlikte gruplandırılabilecek bir kod parçanız var. Ancak bu kısımların ayrı ayrı kullanılması sorun olabilir. 12 | 13 | ```java 14 | void printOwing() { 15 | printBanner(); 16 | 17 | // Print details. 18 | System.out.println("name: " + name); 19 | System.out.println("amount: " + getOutstanding()); 20 | } 21 | ``` 22 | 23 | ### 😊 Çözüm 24 | 25 | Bu kodu ayrı bir yeni metoda (veya işleve) taşıyın ve eski kodu, method çağrısıyla değiştirin. 26 | 27 | ```java 28 | void printOwing() { 29 | printBanner(); 30 | printDetails(getOutstanding()); 31 | } 32 | 33 | void printDetails(double outstanding) { 34 | System.out.println("name: " + name); 35 | System.out.println("amount: " + outstanding); 36 | } 37 | ``` 38 | 39 | ### 🤔 Neden Refactoring Uygulanmalı? 40 | 41 | Bir yöntemde ne kadar çok satır bulunursa, yöntemin ne yaptığını anlamak o kadar zor olur. Bu refactoring'in temel nedeni budur. 42 | 43 | Kodunuzdaki pürüzlü kısımları ortadan kaldırmanın yanı sıra, yöntemlerin çıkarılması yani extract edilmesi aynı zamanda diğer birçok refactoring yaklaşımının da bir adımıdır. 44 | 45 | ### ✅ Avantajları 46 | 47 | - Elbette daha okunabilir kod! Yeni metoda, metodun amacını açıklayan bir isim vermek önemlidir: `createOrder()`, `renderCustomerInfo()`, vb. 48 | 49 | - Daha az kod tekrarı. Genellikle bir metodun içinde bulunan kod, programınızın diğer yerlerinde tekrar kullanılabilir. Bu nedenle, duplicate edilmiş kodları, yeni metodunuza yapılan çağrılarla değiştirebilirsiniz. 50 | 51 | - Bağımsız kod parçalarını izole eder. Böylelikle hataların daha az ortaya çıkmasını sağlar (örneğin yanlış değişkenin değiştirilmesi gibi). 52 | 53 | 54 | ### 🤯 Nasıl Refactor Edilir? 55 | 56 | 1. Yeni bir metod oluşturun ve amacını net bir şekilde yansıtan bir şekilde adlandırın. 57 | 58 | 2. İlgili kod parçasını yeni metodunuza kopyalayın. Parçayı eski yerinden silin ve yerine yeni oluşturmuş olduğunuz metodun çağrısını koyun. 59 | 60 | Bu kod parçasında kullanılan tüm değişkenleri bulun. Eğer değişkenler parçanın içinde tanımlanmışsa ve dışında kullanılmıyorsa, onları değiştirmeyin. Bu değişkenler, yeni metod için yerel değişkenler olacaklardır. 61 | 62 | 3. Eğer değişkenler, çıkaracağınız (extract) kodun öncesinde tanımlanmışsa, bu değişkenleri yeni metodunuzun parametrelerine geçirmeniz gerekecek, böylece önceki değerlerini kullanabilirsiniz. Bu değişkenlerden kurtulmak için **Replace Temp with Query** yöntemini kullanmak bazen daha kolay olabilir. 63 | 64 | 4. Eğer çıkarılan (extract) kodun içinde bir yerel değişkenin bir şekilde değiştiğini görüyorsanız, bu değişen değerin ileride ana metodunuzda gerekebileceği anlamına gelebilir. İki kere kontrol edin! Eğer gerçekten değişebiliyorsa, bu değişkenin değerini ana metoda döndürerek her şeyin önceki halindeki gibi çalışmasını sürdürmesini sağlayın. 65 | 66 | ## Inline Method 67 | 68 | ### 🙁 Problem 69 | 70 | Bir yöntemin gövdesi yöntemin kendisinden daha çok önem arz ettiği durumlar sorun olabilir. 71 | ```java 72 | class PizzaDelivery { 73 | // ... 74 | int getRating() { 75 | return moreThanFiveLateDeliveries() ? 2 : 1; 76 | } 77 | boolean moreThanFiveLateDeliveries() { 78 | return numberOfLateDeliveries > 5; 79 | } 80 | } 81 | ``` 82 | 83 | ### 😊 Çözüm 84 | 85 | Yönteme yapılan çağrıları yöntemin içeriğiyle değiştirin ve yöntemin kendisini silin. 86 | 87 | ```java 88 | class PizzaDelivery { 89 | // ... 90 | int getRating() { 91 | return numberOfLateDeliveries > 5 ? 2 : 1; 92 | } 93 | } 94 | ``` 95 | 96 | ### 🤔 Neden Refactoring Uygulanmalı? 97 | 98 | Bu sorunda bir yöntem basitçe başka bir yönteme yetki vermektedir. Bu delegasyonun kendi başına bir sorunu yoktur. Ancak bu tür birçok yöntem olduğunda, bunlar çözülmesi zor, kafa karıştırıcı bir karmaşa haline gelir. Koda bakan başka bir geliştirici yöntemi anlamakta vakit kaybedecektir. 99 | 100 | Çoğunlukla yöntemler başlangıçta çok kısa değildir, bununla beraber programda değişiklikler yapıldıkça bu hale gelirler. Bu nedenle, kullanım süresi dolmuş yöntemlerden kurtulmaktan çekinmeyin. 101 | 102 | ### ✅ Avantajları 103 | 104 | Gereksiz yöntemlerin sayısını en aza indirerek kodu daha anlaşılır hale getirirsiniz. 105 | 106 | ### 🤯 Nasıl Refactor Edilir? 107 | 108 | 1. Yöntemin alt sınıflarda yeniden tanımlanmadığından emin olun. Yöntem yeniden tanımlanmışsa bu teknikten kaçınmak daha sağlıklıdır. 109 | 110 | 2. Yönteme yapılan tüm çağrıları bulun. Bu çağrıları yöntemin içeriğiyle değiştirin. 111 | 112 | 3. Son olarak yöntemi silin. 113 | 114 | ## Extract Variable 115 | 116 | ### 🙁 Problem 117 | 118 | Anlaşılması zor bir ifadenizin olması sorun olabilir. 119 | 120 | ```java 121 | void renderBanner() { 122 | if ((platform.toUpperCase().indexOf("MAC") > -1) && 123 | (browser.toUpperCase().indexOf("IE") > -1) && 124 | wasInitialized() && resize > 0 ) 125 | { 126 | // do something 127 | } 128 | } 129 | ``` 130 | 131 | ### 😊 Çözüm 132 | 133 | İfadenin sonucunu veya parçalarını kendi kendini açıklayan ayrı değişkenlere ayrırın/parçalayın. 134 | 135 | ```java 136 | void renderBanner() { 137 | final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1; 138 | final boolean isIE = browser.toUpperCase().indexOf("IE") > -1; 139 | final boolean wasResized = resize > 0; 140 | 141 | if (isMacOs && isIE && wasInitialized() && wasResized) { 142 | // do something 143 | } 144 | } 145 | ``` 146 | 147 | ### 🤔 Neden Refactoring Uygulanmalı? 148 | 149 | Değişkenleri çıkarmanın (extract) temel nedeni, karmaşık bir ifadeyi ara kısımlarına bölerek daha anlaşılır hale getirmektir. 150 | 151 | Bunlar şunlar olabilir: 152 | - C tabanlı dillerde `if()` operatörünün durumu veya `? :` operatörünün bir kısmı 153 | - Ara sonuçları olmayan uzun bir aritmetik ifade 154 | - Uzun çok parçalı satırlar 155 | 156 | Çıkarılan (extract) ifadenin kodunuzun başka yerlerinde kullanıldığını görürseniz, bir değişkenin çıkarılması, **Extract Method** tekniğini gerçekleştirmenin ilk adımı olabilir. 157 | 158 | ### ✅ Avantajları 159 | 160 | Daha okunabilir kod! Çıkarılan yani ayrılan değişkenlere, değişkenin amacını net bir şekilde açıklayan iyi isimler vermeye çalışın. `customerTaxValue`, `cityUnemploymentRate`, `clientSalutationString` vb. gibi adları tercih edin. 161 | 162 | ### 🚫 Dezavantajları 163 | 164 | - Kodunuzda daha fazla değişken mevcut olur. Ancak bu, kodunuzu okuma kolaylığı ile dengelenir. 165 | - Koşullu ifadeleri refactor ederken, derleyicinin büyük olasılıkla, elde edilen değeri oluşturmak için gereken hesaplama miktarını en aza indirecek şekilde onu optimize edeceğini unutmayın. Diyelim ki şu ifadeye sahipsiniz `if (a() || b()) .... ` Eğer `a` yöntemi `true` değerini döndürürse program `b` yöntemini çağırmaz çünkü sonuçtaki değer, hangi değer döndürülürse döndürülsün yine de `true` olacaktır. Bu durum `b` değeri ne olursa olsun bu şekilde olacaktır. 166 | 167 | Bununla birlikte, bu ifadenin bazı kısımlarını değişkenlere ayırırsanız, her iki yöntem de her zaman çağrılacaktır; bu da, özellikle bu yöntemler ağır işler yapıyorsa, programın performansına zarar verebilir. 😟 168 | 169 | ### 🤯 Nasıl Refactor Edilir? 170 | 171 | 1. İlgili ifadenin önüne yeni bir satır ekleyin ve orada yeni bir değişken tanımlayın. Karmaşık ifadenin bir kısmını bu değişkene atayın. 172 | 173 | 2. İfadenin bu bölümünü yeni değişkenle değiştirin. 174 | 175 | 3. İfadenin tüm karmaşık kısımları için işlemi tekrarlayın. 176 | 177 | 178 | ## Inline Temp 179 | 180 | ### 🙁 Problem 181 | 182 | Basit bir ifadenin sonucunun atandığı geçici bir değişkeniniz var. Ayrı bir değişkende tutmak ne kadar mantıklı? 183 | 184 | ```java 185 | boolean hasDiscount(Order order) { 186 | double basePrice = order.basePrice(); 187 | return basePrice > 1000; 188 | } 189 | ``` 190 | 191 | ### 😊 Çözüm 192 | 193 | Değişkene atamak yerine döndürülecek ifadeyi direkt kullanın. 194 | 195 | ```java 196 | boolean hasDiscount(Order order) { 197 | return order.basePrice() > 1000; 198 | } 199 | ``` 200 | 201 | ### 🤔 Neden Refactoring Uygulanmalı? 202 | 203 | Satır içi yerel (inline temps) değişkenler neredeyse her zaman **Replace Temp with Query** tekniğinin bir parçası olarak veya **Extract Method** yönteminin önünü açmak için kullanılır. 204 | 205 | ### ✅ Avantajları 206 | 207 | Bu yeniden düzenleme tekniği kendi başına neredeyse hiçbir fayda sağlamaz. Ancak değişkene bir yöntemin sonucu atanırsa, gereksiz değişkenden kurtularak programın okunabilirliğini marjinal olarak artırabilirsiniz. 208 | 209 | ### 🚫 Dezavantajları 210 | 211 | Bazen görünüşte işe yaramayan geçici değişkenler, birkaç kez yeniden kullanılan pahalı bir işlemin sonucunu önbelleğe almak için kullanılır. Bu nedenle, bu yeniden düzenleme tekniğini kullanmadan önce basitliğin performansa mal olmayacağından emin olun. 212 | 213 | ### 🤯 Nasıl Refactor Edilir? 214 | 215 | 1. Değişkeni kullanan tüm yerleri bulun. Değişken yerine kendisine atanmış olan ifadeyi kullanın. 216 | 217 | 2. Değişkenin tanımlama satırını silin. 218 | 219 | 220 | ## Replace Temp with Query 221 | 222 | ### 🙁 Problem 223 | 224 | Bir ifadenin sonucunu daha sonra kodunuzda kullanmak üzere yerel bir değişkene yerleştirmeniz bazen sorun olabilir. 225 | 226 | ```java 227 | double calculateTotal() { 228 | double basePrice = quantity * itemPrice; 229 | if (basePrice > 1000) { 230 | return basePrice * 0.95; 231 | } 232 | else { 233 | return basePrice * 0.98; 234 | } 235 | } 236 | ``` 237 | 238 | ### 😊 Çözüm 239 | 240 | İfadenin tamamını ayrı bir yönteme taşıyın ve sonucu ondan döndürün. Değişken kullanmak yerine yöntemi sorgulayın. Gerekirse yeni yöntemi diğer yöntemlere dahil edin. 241 | 242 | ```java 243 | double calculateTotal() { 244 | if (basePrice() > 1000) { 245 | return basePrice() * 0.95; 246 | } 247 | else { 248 | return basePrice() * 0.98; 249 | } 250 | } 251 | double basePrice() { 252 | return quantity * itemPrice; 253 | } 254 | ``` 255 | 256 | ### 🤔 Neden Refactoring Uygulanmalı? 257 | 258 | Bu refactor, Extract Method tekniğinin çok uzun bir yöntemin bir kısmı için uygulanmasına zemin hazırlayabilir. 259 | 260 | Method içerisinde kullanılan ifade bazen diğer yöntemlerde de bulunabilir, bu da ortak bir yöntem oluşturmayı düşünmenin nedenlerinden biridir. 261 | 262 | ### ✅ Avantajları 263 | 264 | - Kod okunabilirliği. `GetTax()` yönteminin amacını anlamak, `orderPrice() * 0.2` satırından çok daha kolaydır. 265 | 266 | - Değiştirilen satırın birden fazla yöntemde kullanılması durumunda birçok yerde değişikliğe gidilmek yerine method içerisindeki bir değişiklik her yeri etkileyecektir. 267 | 268 | ### 🤓 Bilinmesinde Yarar Var 269 | 270 | **Performans** 271 | 272 | Bu refactor yaklaşımın performansta bir düşüşe neden olup olmayacağı sorusunu gündeme getirebilir. Dürüst cevap şudur: evet performansta düşüş olacaktır. Çünkü ortaya çıkan kod yeni bir yöntemin çağrılmasıyla kullanılabilir. Ancak günümüzün hızlı CPU'ları ve güçlü derleyicileri sayesinde yük neredeyse her zaman minimum düzeyde olacaktır. Buna karşılık, okunabilir kod ve refactor yaklaşımı sayesinde bu yöntemi program kodunun başka yerlerinde yeniden kullanma yeteneği dikkat çekici faydalardır. 273 | 274 | Bununla birlikte, geçici değişkeniniz gerçekten zaman alan bir ifadenin sonucunu önbelleğe almak için kullanılıyorsa, ifadeyi yeni bir yönteme çıkardıktan sonra bu refactoring'i durdurmak isteyebilirsiniz. 275 | 276 | ### 🤯 Nasıl Refactor Edilir? 277 | 278 | 1. Yöntem içinde, değişkene yalnızca bir kez değer atandığından emin olun. Eğer aksi bir durum varsa, değişkenin yalnızca ifadenizin sonucunu depolamak için kullanılacağından emin olmak için **Split Temporary Variable** tekniğini kullanın. 279 | 280 | 2. İlgili ifadeyi yeni bir yönteme yerleştirmek için **Extract Method** tekniğini kullanın. Bu yöntemin yalnızca bir değer döndürdüğünden ve nesnenin durumunu değiştirmediğinden emin olun. Yöntem nesnenin durumunu etkiliyorsa veya değiştiriyorsa **Separate Query from Modifier** yöntemini göz önünde bulundurun/deneyin. 281 | 282 | 3. Değişkenin bulunduğu yerleri, yeni oluşturduğunuz yönteminizi çağırmaya yönelik kod satırı ile değiştirin. 283 | 284 | ## Split Temporary Variable 285 | 286 | ### 🙁 Problem 287 | 288 | Bir yöntemin içinde çeşitli ara değerleri depolamak için kullanılan bir yerel değişkeninizin olması sorun olabilir. Döngü değişkenlerini bu sınıfa dahil etmiyoruz 😅 289 | 290 | ```java 291 | double temp = 2 * (height + width); 292 | System.out.println(temp); 293 | temp = height * width; 294 | System.out.println(temp); 295 | ``` 296 | 297 | ### 😊 Çözüm 298 | 299 | Farklı değerler için farklı değişkenler kullanın. Her değişken yalnızca belirli bir şeyden sorumlu olmalıdır. 300 | 301 | ```java 302 | final double perimeter = 2 * (height + width); 303 | System.out.println(perimeter); 304 | final double area = height * width; 305 | System.out.println(area); 306 | ``` 307 | 308 | ### 🤔 Neden Refactoring Uygulanmalı? 309 | 310 | Bir fonksiyonun içinde barındırdığı değişkenlerin sayısını göz ardı ediyorsanız ve bu değişkenleri kendisi ile ilgisiz çeşitli amaçlarla yeniden kullandığınız bir seneryo var diyelim. Size kötü bir haberim var; değişkenleri içeren kodda değişiklik yapmanız gerektiğinde sorunlarla karşılaşacağınızdan emin olabilirsiniz. Doğru değerlerin kullanıldığından emin olmak için her değişken kullanımını yeniden kontrol etmeniz gerekecektir. Bu da size vakit kaybettirecektir. 311 | 312 | ### ✅ Avantajları 313 | 314 | - Program kodunun her bileşeni sadece tek bir şeyden sorumlu olmalıdır. Bu yöntem, kodun bakımını çok daha kolay hale getirir. Çünkü tahmin edilemez etkilerden korkmadan herhangi bir kod satırını kolayca değiştirebilirsiniz. 315 | 316 | - Kod daha okunabilir hale gelir. Eğer bir değişken uzun zaman önce aceleyle oluşturulduysa, muhtemelen hiçbir şey açıklamayan bir isme sahiptir: `k`, `a2`, `value`, vb. Ancak yeni değişkenleri anlaşılır ve kendiliğinden açıklayıcı bir şekilde adlandırarak bu durumu düzeltebilirsiniz. Örneğin; `customerTaxValue`, `cityUnemploymentRate`, `clientSalutationString`gibi. 317 | 318 | - Bu refaktörleme tekniği, daha sonra **Extract Method** tekniğini kullanmayı planlıyorsanız faydalıdır. 319 | 320 | 321 | ### 🤯 Nasıl Refactor Edilir? 322 | 323 | 1. Kodda değişkene değer ataması yapılan ilk yeri bulun. Burada değişkeni, atanan değere karşılık gelen uygun bir isimle yeniden adlandırmalısınız. 324 | 325 | 2. Değişkenin bu değerinin kullanıldığı yerlerde eski adı yerine yeni adını kullanın. 326 | 327 | 3. Bu işlemi değişkene farklı bir değerin atandığı yerler için gerektiği kadar tekrarlayın. 328 | 329 | 330 | ## Remove Assignments to Parameters 331 | 332 | ### 🙁 Problem 333 | 334 | Metodun gövdesindeki bir parametreye değer atamanız sorun oluşturabilir. 335 | 336 | ```java 337 | int discount(int inputVal, int quantity) { 338 | if (quantity > 50) { 339 | inputVal -= 2; 340 | } 341 | // ... 342 | } 343 | ``` 344 | 345 | ### 😊 Çözüm 346 | 347 | Parametre yerine yerel bir değişken kullanın. 348 | 349 | ```java 350 | int discount(int inputVal, int quantity) { 351 | int result = inputVal; 352 | if (quantity > 50) { 353 | result -= 2; 354 | } 355 | // ... 356 | } 357 | ``` 358 | 359 | ### 🤔 Neden Refactoring Uygulanmalı? 360 | 361 | Bu yeniden düzenlemenin nedenleri **Split Temporary Variable** tekniği ile aynıdır. Ancak bu case'de yerel bir değişkenle değil bir parametreyle ilgileniyoruz. 362 | 363 | Öncelikle referans yoluyla bir parametre iletilirse, yöntem içerisinde parametre değeri değiştirildikten sonra bu değer, yöntemin çağrılmasını talep eden argümana iletilir. Çoğu zaman bu kazara meydana gelir ve talihsiz sonuçlara yol açar. Programlama dilinizde parametreler genellikle değere göre (referansa göre değil) aktarılsa bile, bu garip kodlamayla buna alışkın olmayanların kafalarında soru işaretleri oluşturabilir. 364 | 365 | İkincisi, tek bir parametreye farklı değerlerin birden çok kez ataması, belirli bir zamanda parametrede hangi verilerin bulunması gerektiğini bilmenizi zorlaştırır. Parametreniz ve içeriği belgelenmişse, ancak gerçek değer yöntem içinde beklenenden farklı olursa problem daha da kötüleşir. 366 | 367 | ### ✅ Avantajları 368 | 369 | - Programın her öğesi yalnızca bir şeyden sorumlu olmalıdır. Bu, herhangi bir yan etki olmadan kodu güvenli bir şekilde değiştirebileceğiniz için kod bakımını ileriye dönük olarak çok daha kolay hale getirir. 370 | 371 | - Bu yeniden düzenleme, tekrarlayan kodun ayrı yöntemlere çıkarılmasına (extract) yardımcı olur. 372 | 373 | ### 🤯 Nasıl Refactor Edilir? 374 | 375 | 1. Yerel bir değişken oluşturun ve parametrenizin başlangıç ​​değerini atayın. 376 | 377 | 2. Bu satırı izleyen tüm yöntem kodlarında parametreyi yeni yerel değişkeninizle değiştirin. 378 | 379 | ## Replace Method with Method Object 380 | 381 | ### 🙁 Problem 382 | 383 | Yerel değişkenlerin çok iç içe geçtiği ve **Extract Methods** tekniğini uygulayamayacağınız uzun bir yönteminizin olması sorun olabilir. 384 | 385 | ```java 386 | class Order { 387 | // ... 388 | public double price() { 389 | double primaryBasePrice; 390 | double secondaryBasePrice; 391 | double tertiaryBasePrice; 392 | // Perform long computation. 393 | } 394 | } 395 | ``` 396 | ### 😊 Çözüm 397 | 398 | Yerel değişkenlerin sınıfın alanları (field) haline gelmesi için yöntemi ayrı bir sınıfa dönüştürün. Daha sonra yöntemi aynı sınıf içindeki birkaç yönteme bölebilirsiniz. 399 | 400 | ```java 401 | class Order { 402 | // ... 403 | public double price() { 404 | return new PriceCalculator(this).compute(); 405 | } 406 | } 407 | 408 | class PriceCalculator { 409 | private double primaryBasePrice; 410 | private double secondaryBasePrice; 411 | private double tertiaryBasePrice; 412 | 413 | public PriceCalculator(Order order) { 414 | // Copy relevant information from the 415 | // order object. 416 | } 417 | 418 | public double compute() { 419 | // Perform long computation. 420 | } 421 | } 422 | ``` 423 | 424 | ### 🤔 Neden Refactoring Uygulanmalı? 425 | 426 | Bir yöntem çok uzun olabilir ve birbirinden izole edilmesi zor olan yerel değişkenlerin bir birine bağımlılıkları nedeniyle onu ayıramazsınız. 427 | 428 | İlk adım, yöntemin tamamını ayrı bir sınıfa taşımak ve yerel değişkenlerini sınıfın alanlarına (fields) dönüştürmektir. 429 | 430 | İlk olarak, bu, sorunun sınıf düzeyinde izole edilmesine olanak tanır. İkincisi, büyük ve hantal bir yöntemin, orijinal sınıfın amacına zaten uymayan daha küçük yöntemlere bölünmesinin önünü açar. 431 | 432 | ### ✅ Avantajları 433 | 434 | Uzun bir yöntemi kendi sınıfında izole etmek, yöntemin boyutunun şişmesini durdurmaya olanak tanır. Bu aynı zamanda, orijinal sınıfı faydasız yöntemlerle kirletmeden, sınıf içinde alt yöntemlere bölünmesine de olanak tanır. 435 | 436 | ### 🚫 Dezavantajları 437 | 438 | Programın genel karmaşıklığını artıran başka bir sınıf eklenir. 439 | 440 | ### 🤯 Nasıl Refactor Edilir? 441 | 442 | 1. Yeni bir sınıf oluşturun. Yeniden düzenlediğiniz yöntemin amacına göre sınıfı adlandırın. 443 | 444 | 2. Yeni sınıfta, yöntemin daha önce bulunduğu sınıfın bir örneğine referansı depolamak için private bir alan (fields) oluşturun. Bu tanımlamayla birlikte gerekirse orijinal sınıftan gerekli bazı verileri almak için kullanılabilir. 445 | 446 | 3. Yöntemin her yerel değişkeni için ayrı bir private alan oluşturun. 447 | 448 | 4. Yöntemin tüm yerel değişkenlerinin değerlerini parametre olarak kabul eden ve ayrıca karşılık gelen private alanları başlatan bir kurucu (constructor) oluşturun. 449 | 450 | 5. Ana yöntemi tanımlayın ve yerel değişkenleri private alanlarla değiştirerek orijinal yöntemin kodunu ona kopyalayın. 451 | 452 | 6. Bir yöntem nesnesi oluşturup ana yöntemini çağırarak, orijinal sınıftaki orijinal yöntemin gövdesini değiştirin. 453 | 454 | ## Substitute Algorithm 455 | 456 | ### 🙁 Problem 457 | 458 | Mevcut bir algoritmayı yenisiyle değiştirmek mi istiyorsunuz. Bu süreçte sorunlarla karşılaşabilirsiniz. 459 | 460 | ```java 461 | String foundPerson(String[] people){ 462 | for (int i = 0; i < people.length; i++) { 463 | if (people[i].equals("Don")){ 464 | return "Don"; 465 | } 466 | if (people[i].equals("John")){ 467 | return "John"; 468 | } 469 | if (people[i].equals("Kent")){ 470 | return "Kent"; 471 | } 472 | } 473 | return ""; 474 | } 475 | ``` 476 | 477 | ### 😊 Çözüm 478 | 479 | Algoritmayı barındıran yöntemin gövdesini yeni bir algoritmayla değiştirin. 480 | 481 | ```java 482 | String foundPerson(String[] people){ 483 | List candidates = 484 | Arrays.asList(new String[] {"Don", "John", "Kent"}); 485 | for (int i=0; i < people.length; i++) { 486 | if (candidates.contains(people[i])) { 487 | return people[i]; 488 | } 489 | } 490 | return ""; 491 | } 492 | ``` 493 | 494 | ### 🤔 Neden Refactoring Uygulanmalı? 495 | 496 | - Kademeli refactoring, bir programı iyileştirmenin tek yöntemi değildir. Bazen bir yöntem sorunlarla o kadar karmaşık hale gelir ki, yöntemi yıkıp yeni bir başlangıç ​​yapmak daha kolay olur. Belki de çok daha basit ve daha etkili bir algoritma bulmuşsunuzdur. Bu durumda eski algoritmayı yenisiyle değiştirmeniz yeterlidir. 497 | 498 | - Zaman geçtikçe algoritmanız iyi bilinen bir kütüphaneye veya framework'e dahil edilebilir. Bununla beraber, bakımı kolaylaştırmak için bağımsız uygulamanızdan kurtulmak isteyebilirsiniz. 499 | 500 | - Programınızın gereksinimleri o kadar yoğun şekilde değişebilir ki, mevcut algoritmanız bu görev için yeterli kalmayabilir. 501 | 502 | ### 🤯 Nasıl Refactor Edilir? 503 | 504 | 1. Mevcut algoritmayı mümkün olduğunca basitleştirdiğinizden emin olun. Önemsiz kodu, **Extract Methods** tekniğini kullanarak başka yöntemlere taşıyın veya oluşturun. Algoritmanızda ne kadar az dinamik parça olursa, değiştirilmesi o kadar kolay olur. 505 | 506 | 2. Yeni algoritmanızı yeni bir yöntemle oluşturun. Eski algoritmayı yenisiyle değiştirin ve programı test etmeye başlayın. 507 | 508 | 3. Sonuçlar eşleşmiyorsa eski uygulamaya dönün ve sonuçları karşılaştırın. Farklılığın nedenlerini tanımlayın. Bunun nedeni genellikle eski algoritmadaki bir hata olsa da, yeni algoritmada çalışmayan bir şeyden kaynaklanma olasılığı daha yüksektir. 509 | 510 | 4. Tüm testler başarıyla tamamlandığında eski algoritmayı tamamen silin! 511 | 512 | 513 | 514 | 515 | -------------------------------------------------------------------------------- /refactoring-techniques/dealing-with-generalization.md: -------------------------------------------------------------------------------- 1 | # Genellemeyle Başa Çıkmak (Dealing with Generalization) 2 | 3 | Bu teknikler, öncelikle işlevselliği sınıf devralma hiyerarşisi boyunca taşımakla ilişkilidir. Ayrıca, yeni sınıflar ve arayüzler oluşturmayı içerirler. Bununla birlikte, soyutlamayı temsilci seçme yöntemiyle değiştirmek de mümkündür. Bu durumda, soyutlamadan türetilen sınıflar temsilcileri seçebilir. Özetle, soyutlama, hem yeni sınıflar ve arayüzler oluşturmayı hem de temsilci seçme yöntemiyle değişiklik yapmayı içeren bir dizi yeniden düzenleme tekniği sunar. 4 | 5 | ## Pull Up Field 6 | 7 | ### 🙁 Problem 8 | 9 | İki farklı sınıf aynı field'a sahipse ortada bir kod tekrarı bulunmaktadır. 10 | 11 |
12 | 13 | ![](https://refactoring.guru/images/refactoring/diagrams/Pull%20Up%20Field%20-%20Before.png) 14 |
15 | 16 | ### 😊 Çözüm 17 | 18 | Tekrar olan field'ı, alt sınıflardan kaldırın ve üst sınıfa taşıyın. Böylelikle kod tekrarının önüne geçmiş olursunuz. 19 | 20 |
21 | 22 | ![](https://refactoring.guru/images/refactoring/diagrams/Pull%20Up%20Field%20-%20After.png) 23 |
24 | 25 | ### 🤔 Neden Refactoring Uygulanmalı? 26 | 27 | Proje boyunca alt sınıflar ayrı ayrı büyüyüp geliştir. Bu durum aynı amaca hizmet eden field'ların ve yöntemlerin ortaya çıkmasına neden olabilir. 28 | 29 | ### ✅ Avantajları 30 | 31 | Alt sınıflardaki fieldların tekrarlanmasını ortadan kaldırır. 32 | 33 | Varsa, yinelenen yöntemlerin daha sonraki adımlarda, alt sınıflardan bir üst sınıfa taşınmasını kolaylaştırır. 34 | 35 | ### 🤯 Nasıl Refactor Edilir? 36 | 37 | 1. Alt sınıflarda buluanan field'ların aynı aynı amaca hizmet ettiğinden emin olun. 38 | 39 | 2. Fieldlar farklı adlara sahipse, onlara aynı adı verin. Daha sonra, bu field'lara yapılan tüm referansları mevcut kodla değiştirin. 40 | 41 | 3. Üst sınıfta aynı ada sahip bir field oluşturun. Field'lar private ise üst sınıf alanın korunması gerektiğini unutmayın. 42 | 43 | 4. Field'ları alt sınıflardan kaldırın. 44 | 45 | 5. Yeni field erişim yöntemlerinin arkasına gizlemek amacıyla, **Self Encapsulate Field** tekniğini kullanmayı düşünebilirsiniz. 46 | 47 | ## Pull Up Method 48 | 49 | ### 🙁 Problem 50 | 51 | İki farklı alt sınıfın benzer işleri gerçekleştiren yöntemleri olması kod tekrarına sebep olacaktır. 52 | 53 |
54 | 55 | ![](https://refactoring.guru/images/refactoring/diagrams/Pull%20Up%20Method%20-%20Before.png) 56 | 57 |
58 | 59 | ### 😊 Çözüm 60 | 61 | Yöntemleri ortaklaştırın ve ardından bu yöntemleri, üst sınıfa taşıyın. 62 | 63 |
64 | 65 | ![](https://refactoring.guru/images/refactoring/diagrams/Pull%20Up%20Method%20-%20After.png) 66 | 67 |
68 | 69 | ### 🤔 Neden Refactoring Uygulanmalı? 70 | 71 | Proje boyunca alt sınıflar ayrı ayrı büyüyüp geliştir. Bu durum aynı amaca hizmet eden field'ların ve yöntemlerin ortaya çıkmasına neden olabilir. 72 | 73 | 74 | ### ✅ Avantajları 75 | 76 | - Tekrarlı kodlardan kurtulur. Bir yöntemde değişiklik yapmanız gerektiği durumda, yöntemin tüm kopyalarını alt sınıflarda aramak zorunda kalmaktansa, bu değişiklikleri tek bir yerde yapmak daha iyidir. 77 | 78 | - Bu yeniden düzenleme tekniği, bir alt sınıfın bir üst sınıf yöntemini yeniden tanımlaması ancak temelde aynı işi gerçekleştirmesi durumunda da kullanılabilir. 79 | 80 | 81 | ### 🤯 Nasıl Refactor Edilir? 82 | 83 | 1. Üst sınıflardaki benzer yöntemleri araştırın. Aynı değillerse birbirleriyle eşleşecek şekilde biçimlendirin. 84 | 85 | 2. Yöntemler farklı bir parametre kümesi kullanıyorsa, parametreleri üst sınıfta görmek istediğiniz formda olacak şekilde yerleştirin. 86 | 87 | 3. Yöntemi üst sınıfa kopyalayın. Burada yöntem kodunun yalnızca alt sınıflarda bulunan ve dolayısıyla üst sınıfta bulunmayan alanları ve yöntemleri kullandığını görebilirsiniz. Bunu çözmek için aşağıda listelen yöntemlerden birini deneyebilirsiniz: 88 | 89 | - Field'lar için: alt sınıflarda alıcılar ve ayarlayıcılar (getter & setter) oluşturmak için **Pull Up Field** veya **Self-Encapsulate Field ** tekniğini kullanın; daha sonra bu alıcıları (getter) soyut (abstract) olarak üst sınıfta tanımlayın. 90 | 91 | - Yöntemler için:**Pull Up Method** tekniğini kullanın veya üst sınıfta onlar için soyut yöntemler tanımlayın (sınıfınızın daha önce soyut değilse soyut hale geleceğini unutmayın). 92 | 93 | 4. Yöntemleri alt sınıflardan kaldırın. 94 | 95 | 5. Yöntemin çağrıldığı konumları kontrol edin. Bazı yerlerde bir alt sınıfın kullanımını üst sınıfla değiştirmeniz gerekebilir. 96 | 97 | 98 | ## Pull Up Constructor Body 99 | 100 | ### 🙁 Problem 101 | 102 | Alt sınıflarınızda neredeyse aynı koda sahip kurucular (constructors) bulunuyorsa bu kod tekrarına sebep olacaktır. 103 | 104 | ```java 105 | class Manager extends Employee { 106 | public Manager(String name, String id, int grade) { 107 | this.name = name; 108 | this.id = id; 109 | this.grade = grade; 110 | } 111 | // ... 112 | } 113 | ``` 114 | 115 | ### 😊 Çözüm 116 | 117 | Bir üst sınıf yapıcısı (constructor) oluşturun. Daha sonra alt sınıflarda aynı olan kodu üst sınıftaki constructor'a taşıyın. Alt sınıfların yapıcılarında (constructors) üst sınıf yapıcısını (`super()`) çağırın. 118 | 119 | ```java 120 | class Manager extends Employee { 121 | public Manager(String name, String id, int grade) { 122 | super(name, id); 123 | this.grade = grade; 124 | } 125 | // ... 126 | } 127 | ``` 128 | 129 | ### 🤔 Neden Refactoring Uygulanmalı? 130 | 131 | Bu refactoring tekniğinin **Pull Up Method** tekniğinden farkı nedir? 132 | 133 | 1. Java'da, alt sınıflar bir kurucuyu (constructor) miras alamaz, bu nedenle alt sınıf kurucusuna **Pull Up Method** uygulayamaz. Üst sınıftaki tüm kurucu (constructor) kodunu kaldırdıktan sonra onu silemezsiniz. Üst sınıfta bir kurucu yaratmanın yanı sıra, üst sınıf kurucuya basit yetki verme ile alt sınıflarda da kurucuların olması gerekir. 134 | 135 | 2. C++ ve Java'da (eğer üst sınıf yapıcısını (constructor) açıkça çağırmadıysanız), üst sınıf yapıcısı otomatik olarak alt sınıf yapıcısından önce çağrılır, bu da ortak kodun yalnızca alt sınıf yapıcılarının başlangıcından itibaren taşınmasını gerekli kılar.. 136 | 137 | 3. Çoğu programlama dilinde, bir alt sınıf yapıcısı, üst sınıfın parametrelerinden farklı olarak kendi parametre listesine sahip olabilir. Bu nedenle, yalnızca gerçekten ihtiyaç duyduğu parametrelerle birlikte bir üst sınıf kurucu constructor oluşturmalısınız. 138 | 139 | 140 | ### 🤯 Nasıl Refactor Edilir? 141 | 142 | 1. Bir üst sınıfta bir kurucu (constructor) oluşturun. 143 | 144 | 2. Her alt sınıfın yapıcısının başlangıcındaki ortak kodu üst sınıf yapıcısına taşıyın. Bunu yapmadan önce mümkün olduğu kadar çok ortak kodu yapıcının başlangıcına taşımaya çalışın. 145 | 146 | 3. Üst sınıf yapıcısının yapılan çağrıyı alt sınıf yapıcılarının ilk satırına yerleştirin. 147 | 148 | 149 | ## Push Down Method 150 | 151 | ### 🙁 Problem 152 | 153 | Bir method yalnızca bir (veya birkaç) alt sınıf tarafından kullanılan bir üst sınıfta mı uygulanmış? Bu yöntemi kullanmayacak olan alt sınıfların, bu yöntemi miras olarak alması ne kadar mantıklı? 154 | 155 |
156 | 157 | ![](https://refactoring.guru/images/refactoring/diagrams/Push%20Down%20Method%20-%20Before.png) 158 | 159 |
160 | 161 | ### 😊 Çözüm 162 | 163 | Bu yöntemi, üst sınıftan yönteme ihtiyacı olan alt sınıflara taşıyın. 164 | 165 |
166 | 167 | ![](https://refactoring.guru/images/refactoring/diagrams/Push%20Down%20Method%20-%20After.png) 168 | 169 |
170 | 171 | ### 🤔 Neden Refactoring Uygulanmalı? 172 | 173 | İlk başta belirli bir yöntemin tüm alt sınıflar için evrensel olması amaçlanmış olabilir. Ancal gerçekte yalnızca bir veya birkaç alt sınıfta kullanılabilir. Bu durum, özellikle planlanan yapıların hayata geçmemesi durumunda ortaya çıkabilir. 174 | 175 | Bu tür durumlar, bir sınıf hiyerarşisinden işlevselliğin kısmen kaldırılmasından sonra da yalnızca bir alt sınıfta kullanılan bir yöntem bırakılması durumunda ortaya çıkabilir. 176 | 177 | Bir yöntemin birden fazla alt sınıf için gerekli olduğunu, ancak tüm alt sınıflar gerekli olmadığını görürseniz, bir ara alt sınıf oluşturup yöntemi bu alt sınıfa taşımak yararlı olabilir. Böylelikle, bir yöntemin tüm alt sınıflara iletilmesinden kaynaklanacak kod çoğaltmasının önlenmesine olanak tanıyacaktır. 178 | 179 | ### ✅ Avantajları 180 | 181 | Sınıf tutarlılığını artırır. Bir yöntem görmeyi beklediğiniz yerde bulunacaktır. 182 | 183 | 184 | ### 🤯 Nasıl Refactor Edilir? 185 | 186 | 1. Yöntemi bir alt sınıfta tanımlayın ve yöntemin gövde kodunu üst sınıftan kopyalayın. 187 | 188 | 2. Yöntemi üst sınıftan kaldırın. 189 | 190 | 3. Yöntemin kullanıldığı tüm yerleri bulun ve yeni tanımlanan alt sınıftan çağrıldığından emin olun. 191 | 192 | 193 | ## Push Down Field 194 | 195 | ### 🙁 Problem 196 | 197 | Bir parent sınıfta bulunan field yalnızca birkaç alt sınıfta mı kullanılıyor? Böyle bir durumda **Push Down Method** daki gibi gereksiz miras durumu söz konusu olacaktır. 198 | 199 |
200 | 201 | ![](https://refactoring.guru/images/refactoring/diagrams/Push%20Down%20Field%20-%20Before.png) 202 | 203 |
204 | 205 | ### 😊 Çözüm 206 | 207 | Field'ı sadece ihtiyacı olan alt sınıflara taşıyın. 208 | 209 |
210 | 211 | ![](https://refactoring.guru/images/refactoring/diagrams/Push%20Down%20Field%20-%20After.png) 212 | 213 |
214 | 215 | ### 🤔 Neden Refactoring Uygulanmalı? 216 | 217 | İlk başta belirli bir field'ın tüm alt sınıflar için evrensel olması amaçlanmış olabilir. Ancal gerçekte yalnızca bir veya birkaç alt sınıfta kullanılabilir. Bu durum, özellikle planlanan yapıların hayata geçmemesi durumunda ortaya çıkabilir. 218 | 219 | Bu tür durumlar, bir sınıf hiyerarşisinden işlevselliğin kısmen kaldırılmasından sonra da yalnızca bir alt sınıfta kullanılan bir field bırakılması durumunda ortaya çıkabilir. 220 | 221 | Bir field birden fazla alt sınıf için gerekli olduğunu, ancak tüm alt sınıflar gerekli olmadığını görürseniz, bir ara alt sınıf oluşturup field'ı bu alt sınıfa taşımak yararlı olabilir. Böylelikle, bir field'ın tüm alt sınıflara iletilmesinden kaynaklanacak kod çoğaltmasının önlenmesine olanak tanıyacaktır. 222 | 223 | ### ✅ Avantajları 224 | 225 | - Dahili sınıf tutarlılığını artırır. Field gerçekten bulunması gereken yerde tanımlı olur. 226 | 227 | - Aynı anda birkaç alt sınıfa geçerken field'ları birbirinden bağımsız olarak geliştirebilirsiniz. Bu, kod çoğaltmasına neden olur, bu nedenle field'ları yalnızca gerçekten farklı şekillerde kullanmayı düşündüğünüzde aşağı doğru iletin. 228 | 229 | ### 🤯 Nasıl Refactor Edilir? 230 | 231 | 1. Gerekli tüm alt sınıflarda bir field tanımlayın. 232 | 233 | 2. Field'ı üst sınıftan kaldırın. 234 | 235 | ## Extract Subclass 236 | 237 | ### 🙁 Problem 238 | 239 | Bir ana sınıfın yalnızca belirli durumlarda kullanılan methodları ve field'ları varsa kod karmaşıklaşır. 240 | 241 |
242 | 243 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Subclass%20-%20Before.png) 244 | 245 |
246 | 247 | ### 😊 Çözüm 248 | 249 | Bir alt sınıf oluşturun ve bu yöntem ve field'ları sadece bu alt sınfıta kullanın. 250 | 251 |
252 | 253 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Subclass%20-%20After.png) 254 | 255 |
256 | 257 | ### 🤔 Neden Refactoring Uygulanmalı? 258 | 259 | Ana sınıfınız, sınıf için belirli bir nadir kullanım durumunu uygulamaya yönelik yöntemlere ve field'lara sahip olabilir. Nadir de olsa, bundan sınıf sorumludur ve ilişkili tüm field'ları ve yöntemleri tamamen ayrı bir sınıfa taşımak yanlış olacaktır. Ancak bunlar bir alt sınıfa taşınabilirler ve biz de bu refactoring tekniğinin yardımıyla bunu yapacağız. 260 | 261 | ### ✅ Avantajları 262 | 263 | - Hızlı ve kolay bir şekilde alt sınıf oluşturur. 264 | 265 | - Ana sınıfınız halihazırda birden fazla özel durum uyguluyorsa, birkaç ayrı alt sınıf oluşturabilirsiniz. 266 | 267 | ### 🚫 Dezavantajları 268 | 269 | Görünen basitliğine rağmen, birkaç farklı sınıf hiyerarşisini ayırmanız gerekiyorsa, Miras çıkmaza yol açabilir. Örneğin, köpeklerin boyutuna ve kürküne bağlı olarak farklı davranışlara sahip Köpekler (`Dogs`) sınıfınız varsa, iki hiyerarşiyi ortaya çıkarabilirsiniz: 270 | 271 | - boyuta göre: Büyük (`Large`), Orta (`Medium`) ve Küçük (`Small`) 272 | 273 | - kürkle: Pürüzsüz (`Smooth`) ve Shaggy (`Shaggy`) 274 | 275 | Ve her şey iyi görünebilir, ancak hem büyük (`Large`) hem de Pürüzsüz (`Smooth`) bir köpek yaratmanız gerektiğinde sorunların ortaya çıkması dışında, yalnızca bir sınıftan bir nesne oluşturabildiğiniz için. Bununla birlikte, Devralmak yerine Oluştur'u (Compose instead of Inherit) tekniğini kullanarak bu sorunu önleyebilirsiniz (**Strategy** tasarım desenine bakın). Başka bir deyişle, Köpek (`Dog`) sınıfının beden ve kürk olmak üzere iki bileşen alanı olacaktır. Bu alanlara gerekli sınıflardan bileşen nesneleri ekleyeceksiniz. Böylece `LargeSize` ve `ShaggyFur` özelliklerine sahip bir Köpek (`Dog`) üretebilirsiniz. 276 | 277 | 278 | ### 🤯 Nasıl Refactor Edilir? 279 | 280 | 1. İlgilendiğiniz sınıftan yeni bir alt sınıf oluşturun. 281 | 282 | 2. Bir alt sınıftan nesneler oluşturmak için ek verilere ihtiyacınız varsa, bir kurucu (constructor) oluşturun ve kurucuya gerekli parametreleri ekleyin. Kurucunun ana uygulamasını çağırmaası gerektiğini unutmayın. 283 | 284 | 3. Ana sınıfın yapıcısına (constructor) yapılan tüm çağrıları bulun. Bir alt sınıfın işlevselliği gerekli olduğunda ana kurucuyu alt sınıf kurucuyla değiştirin. 285 | 286 | 4. Gerekli yöntemleri ve alanları ana sınıftan alt sınıfa taşıyın. Bunu **Push Down Method** ve **Push Down Method** teknikleri aracılığıyla yapın. Önce yöntemleri taşıyarak başlamak daha kolaydır. Bu şekilde alanlar tüm süreç boyunca erişilebilir kalır. 287 | 288 | 5. Alt sınıf hazır olduktan sonra, işlevsellik seçimini kontrol eden tüm eski field'ları bulun. Field'ları kullanıldığı tüm operatörleri değiştirmek için polimorfizmi kullanarak bu alanları silin. Basit bir örnek: Araba (`Car`) sınıfında, `isElectricCar` alanınız vardı ve buna bağlı olarak, `refuel()` yönteminde araca ya gaz dolduruluyor ya da elektrik yükleniyor. Yeniden düzenleme sonrasında `isElectricCar` alanı kaldırılır ve `Car` ve `ElectricCar` sınıfları, `refuel()` yönteminin kendi uygulamalarına (implementation) sahip olur. 289 | 290 | 291 | ## Extract Superclass 292 | 293 | ### 🙁 Problem 294 | 295 | Ortak field ve yöntemleri sahip olan iki farklı sınıfınız var. Madem ortak değerlere sahip, neden farklı iki sınıf ki? 296 | 297 |
298 | 299 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Superclass%20-%20Before.png) 300 | 301 |
302 | 303 | ### 😊 Çözüm 304 | 305 | Bu iki sınıfın alt sınıf olacağı, bir üst sınıf oluşturun ve tüm aynı field ve yöntemleri bu parent sınıfa taşıyın. 306 | 307 |
308 | 309 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Superclass%20-%20After.png) 310 | 311 |
312 | 313 | ### 🤔 Neden Refactoring Uygulanmalı? 314 | 315 | Bu tür kod tekrarı, iki sınıf benzer görevleri aynı şekilde gerçekleştirdiğinde veya benzer görevleri farklı şekillerde gerçekleştirdiğinde ortaya çıkar. Nesneler bu tür durumları kalıtım yoluyla basitleştirmek için yerleşik bir mekanizma sunar. Ancak çoğu zaman bu benzerlik, sınıflar oluşturulana kadar fark edilmeden kalır ve daha sonra bir miras yapısının oluşturulmasını gerekli kılar. 316 | 317 | ### ✅ Avantajları 318 | 319 | Kod tekilleştirme. Ortak alanlar ve yöntemler artık yalnızca tek bir yerde bulunur. 320 | 321 | ### 🖐🏼 Ne Zaman Kullanılmamalı? 322 | 323 | Bu tekniği halihazırda bir üst sınıfa sahip olan sınıflara uygulayamazsınız. 324 | 325 | ### 🤯 Nasıl Refactor Edilir? 326 | 327 | 1. Soyut (abstract) bir üst sınıf oluşturun. 328 | 329 | 2. Ortak işlevselliği bir üst sınıfa taşımak için **Pull Up Field**, **Pull Up Method** ve **Pull Up Constructor Body** tekniklerini kullanın. Field'lar ile başlayın, çünkü ortak alanlara ek olarak ortak yöntemlerde kullanılan alanları da taşımanız gerekecektir. 330 | 331 | 3. İstemci kodunda, alt sınıfların kullanımının yeni sınıfınızla değiştirilebileceği yerleri arayın. 332 | 333 | 334 | ## Extract Interface 335 | 336 | ### 🙁 Problem 337 | 338 | Birden fazla istemci bir sınıf arayüzünün (interface) aynı bölümünü kullanıyor. Bununla beraber iki sınıftaki arayüzün bir kısmı aynı olabilir. Bu bir tür kod tekrarı değil mi? 339 | 340 |
341 | 342 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Interface%20-%20Before.png) 343 | 344 |
345 | 346 | ### 😊 Çözüm 347 | 348 | Bu sınıflardaki özdeş kısmı kendi arayüzüne taşıyın. 349 | 350 |
351 | 352 | ![](https://refactoring.guru/images/refactoring/diagrams/Extract%20Interface%20-%20After.png) 353 | 354 |
355 | 356 | ### 🤔 Neden Refactoring Uygulanmalı? 357 | 358 | 1. Sınıflar farklı durumlarda özel işlevler uyguladığında arayüzler çok uygundur. Hangi rolü kullanacağını açıkça belirtmek için **Extract Interface** kullanın. 359 | 360 | 2. Bir sınıfın sunucusunda gerçekleştirdiği işlemleri tanımlamanız gerektiğinde başka bir uygun durum ortaya çıkar. Sonunda birden fazla türdeki sunucuların kullanımına izin verilmesi planlanıyorsa tüm sunucuların arayüzü uygulaması gerekir. 361 | 362 | ### 🤓 Bilinmesinde Yarar Var 363 | 364 | **Extract Superclass** ve **Extract Interface** teknikleri arasında belirli bir benzerlik vardır. 365 | 366 | Bir arayüzün çıkarılması, yalnızca ortak arayüzlerin yalıtılmasına olanak tanır. Başka bir deyişle, eğer sınıflar **Duplicate Code** içeriyorsa, arayüzün çıkarılması yani extract edilmesi tekilleştirmenize yardımcı olmayacaktır. 367 | 368 | Yine de, tekrarlı kodu içeren davranışı ayrı bir bileşene taşımak ve tüm işi ona devretmek için **Extract Class** tekniğini uygulanarak bu sorun biraz da olsa azaltılabilir. Ortak davranışın boyutu büyükse, her zaman **Extract Superclass** tekniğini kullanabilirsiniz. Bu elbette daha da kolay olacaktır. Ancak bu yolu seçerseniz yalnızca bir parent sınıfı kullanabileceğinizi unutmayın. 369 | 370 | ### 🤯 Nasıl Refactor Edilir? 371 | 372 | 1. Boş bir arayüz (interface) oluşturun. 373 | 374 | 2. Arayüzdeki ortak işlemleri tanımlayın. 375 | 376 | 3. Arayüzü uygulayan olarak gerekli sınıfları oluşturun. 377 | 378 | 4. Yeni arayüzü kullanmak için istemci kodundaki tür tanımlamalarını (type declarations) değiştirin. 379 | 380 | 381 | ## Collapse Hierarchy 382 | 383 | ### 🙁 Problem 384 | 385 | Bir alt sınıfın neredeyse üst sınıfıyla aynı olduğu bir sınıf hiyerarşiniz var. O halde alt sınıf neden var? 386 | 387 |
388 | 389 | ![](https://refactoring.guru/images/refactoring/diagrams/Collapse%20Hierarchy%20-%20Before.png) 390 | 391 |
392 | 393 | ### 😊 Çözüm 394 | 395 | Alt sınıf ve üst sınıfı birleştirin. 396 | 397 |
398 | 399 | ![](https://refactoring.guru/images/refactoring/diagrams/Collapse%20Hierarchy%20-%20After.png) 400 | 401 |
402 | 403 | ### 🤔 Neden Refactoring Uygulanmalı? 404 | 405 | Programınız zamanla büyür ve alt sınıf ile üst sınıf neredeyse aynı hale gelebilir. Bir alt sınıftan bir özellik kaldırılabilir, bir yöntem üst sınıfa taşınabilir... ve artık iki benzer sınıfınız olmuş olur. Bu ne kadar gereklidir kş? 406 | 407 | ### ✅ Avantajları 408 | 409 | - Program karmaşıklığı azalır. Daha az sınıf, aklınızda tutmanız gereken daha az şey ve gelecekteki kod değişiklikleri sırasında endişelenecek daha az bozulabilir dinmik parça anlamına gelir. 410 | 411 | - Yöntemler bir sınıfta erken tanımlandığında kodunuzda gezinmek ve kodu anlamak daha kolaydır. Belirli bir yöntemi bulmak için tüm hiyerarşiyi taramanıza gerek kalmaz. 412 | 413 | ### 🖐🏼 Ne Zaman Kullanılmamalı? 414 | 415 | - Refactoring ettiğiniz sınıf hiyerarşisinde birden fazla alt sınıf mı var? Eğer öyleyse, refactoring sürecini tamamlandıktan sonra geri kalan alt sınıflar, hiyerarşinin çöktüğü sınıfın mirasçıları haline gelmelidir. 416 | 417 | - Ancak bunun Liskov ikame ilkesinin ihlaline yol açabileceğini unutmayın. Örneğin, programınız şehir içi ulaşım ağlarını taklit ediyorsa ve Taşıma (`Transport`) üst sınıfını yanlışlıkla Araba (`Car`) alt sınıfına daraltırsanız, Plane (`Uçak`) sınıfı Araba'nın (`Car`) mirasçısı olabilir. Hata! Bu tarz durumlar dönüşü olmayan sorunlara yol açabilir. 418 | 419 | ### 🤯 Nasıl Refactor Edilir? 420 | 421 | 1. Hangi sınıfın kaldırılmasının daha kolay olduğunu seçin: üst sınıf mı yoksa alt sınıf mı? 422 | 423 | 2. Alt sınıftan kurtulmaya karar verirseniz **Pull Up Field** ve **Pull Up Method** tekniklerini kullanın. Üst sınıfı ortadan kaldırmayı seçerseniz, **Push Down Field** ve **Push Down Method** tekniklerini tercih edin. 424 | 425 | 3. Sildiğiniz sınıfın tüm kullanımlarını, field listelerini ve yöntemlerini taşınacağı sınıfla aktarın. 426 | 427 | 5. Boş sınıfı silin. 428 | 429 | 430 | ## Form Template Method 431 | 432 | ### 🙁 Problem 433 | 434 | Alt sınıflarınız, benzer adımları aynı sırayla içeren algoritmalar içeriyorsa burada refactoring için çanlar çalıyor olabilir. 435 | 436 |
437 | 438 | ![](https://refactoring.guru/images/refactoring/diagrams/Form%20Template%20Method%20-%20Before.png) 439 | 440 |
441 | 442 | ### 😊 Çözüm 443 | 444 | Algoritma yapısını ve aynı adımları bir üst sınıfa taşıyın ve farklı adımların uygulanmasını alt sınıflarda yapacak şekilde oldukları yerde bırakın. 445 | 446 |
447 | 448 | ![](https://refactoring.guru/images/refactoring/diagrams/Form%20Template%20Method%20-%20After.png) 449 | 450 |
451 | 452 | ### 🤔 Neden Refactoring Uygulanmalı? 453 | 454 | Alt sınıflar paralel olarak, bazen farklı kişiler tarafından geliştirilir, bu da her değişikliğin tüm alt sınıflarda yapılması gerektiğinden kod tekrarına, hatalara ve kod bakımında zorluklara yol açar. 455 | 456 | ### ✅ Avantajları 457 | 458 | - Kod çoğaltma her zaman basit kopyalama/yapıştırma durumlarını ifade etmez. Çoğunlukla çoğaltma daha yüksek düzeyde gerçekleşir; örneğin sayıları sıralamak için bir yönteminiz ve yalnızca öğelerin karşılaştırılmasıyla farklılaşan nesne koleksiyonlarını sıralamak için bir yönteminiz olduğu durumlar gibi. Bir şablon yöntemi oluşturmak, paylaşılan algoritma adımlarını bir üst sınıfta birleştirerek ve yalnızca alt sınıflardaki farklılıkları bırakarak bu çoğaltmayı ortadan kaldırır. 459 | 460 | - Bir şablon yöntemi oluşturmak, Açık/Kapalı Prensibinin uygulamalı bir örneğidir. Yeni bir algoritma sürümü göründüğünde yalnızca yeni bir alt sınıf oluşturmanız gerekir; Mevcut kodda herhangi bir değişiklik yapılmasına gerek yoktur. 461 | 462 | ### 🤯 Nasıl Refactor Edilir? 463 | 464 | 1. Alt sınıflardaki algoritmaları, ayrı yöntemlerde açıklanan kurucu parçalarına ayırın. **Extract Method** tekniği bu konuda yardımcı olabilir. 465 | 466 | 2. Sonuçta ortaya çıkan tüm alt sınıflar için aynı olan yöntemler, **Pull Up Method** tekniği kullanılarak bir üst sınıfa taşınabilir. 467 | 468 | 3. Benzer olmayan yöntemlere **Rename Method** tekniği ile tutarlı adlar verilebilir. 469 | 470 | 4. Benzer olmayan yöntemlerin imzalarını **Pull Up Method** tekniği kullanarak soyut olarak bir üst sınıfa taşıyın. Uygulamalarını alt sınıflarda bırakın. 471 | 472 | 5. Ve son olarak, algoritmanın ana yöntemini üst sınıfa çekin. Artık hem gerçek hem de soyut olarak üst sınıfta açıklanan yöntem adımlarıyla çalışmalıdır. 473 | 474 | ## Replace Inheritance with Delegation 475 | 476 | ### 🙁 Problem 477 | 478 | Üst sınıfının yöntemlerinin yalnızca bir kısmını kullanan bir alt sınıfınız varsa neden bu sınıf bir alt sınıf olarak miras alıyor? 479 | 480 |
481 | 482 | ![](https://refactoring.guru/images/refactoring/diagrams/Replace%20Inheritance%20with%20Delegation%20-%20Before.png) 483 | 484 |
485 | 486 | ### 😊 Çözüm 487 | 488 | Bir field oluşturun ve içine bir üst sınıf nesnesi koyun, yöntemleri üst sınıf nesnesine devredin ve mirastan kurtulun. 489 | 490 |
491 | 492 | ![](https://refactoring.guru/images/refactoring/diagrams/Replace%20Inheritance%20with%20Delegation%20-%20After.png) 493 | 494 |
495 | 496 | ### 🤔 Neden Refactoring Uygulanmalı? 497 | 498 | Kalıtımı kompozisyonla değiştirmek, aşağıdaki durumlarda sınıf tasarımını önemli ölçüde iyileştirebilir: 499 | 500 | - Alt sınıfınız Liskov ikame ilkesini ihlal ediyor; yani, kalıtım yalnızca ortak kodu birleştirmek için uygulandıysa, ancak alt sınıfın üst sınıfın bir uzantısı olması nedeniyle uygulanmadıysa. 501 | 502 | - Alt sınıf, üst sınıfın yöntemlerinin yalnızca bir kısmını kullanır. Bu durumda, birinin aramaması gereken bir süper sınıf yöntemini çağırması an meselesidir. 503 | 504 | Temelde, bu yeniden düzenleme tekniği her iki sınıfı da böler ve üst sınıfı alt sınıfın ebeveyni değil yardımcısı yapar. Tüm üst sınıf yöntemlerini miras almak yerine, alt sınıf yalnızca üst sınıf nesnesinin yöntemlerine yetki vermek için gerekli yöntemlere sahip olacaktır. 505 | 506 | ### ✅ Avantajları 507 | 508 | - Bir sınıf, üst sınıftan miras alınan gereksiz yöntemleri içermez. 509 | 510 | - Delege alanına çeşitli uygulamalara sahip çeşitli nesneler yerleştirilebilir. Aslında **Strategy** tasarım modelini elde edersiniz. 511 | 512 | ### 🚫 Dezavantajları 513 | 514 | Birçok basit yetki verme yöntemi yazmanız gerekir. 515 | 516 | ### 🤯 Nasıl Refactor Edilir? 517 | 518 | 1. Üst sınıfı tutmak için alt sınıfta bir field oluşturun. İlk aşamada mevcut nesneyi içine yerleştirin. 519 | 520 | 2. Alt sınıf yöntemlerini,`this` yerine üst sınıf nesnesini kullanacak şekilde değiştirin. 521 | 522 | 3. İstemci kodunda çağrılan üst sınıftan miras alınan yöntemler için, alt sınıfta basit yetki verme yöntemleri oluşturun. 523 | 524 | 4. Miras tanımlamalarını alt sınıftan kaldırın. 525 | 526 | 5. Yeni bir nesne oluşturarak, eski üst sınıfın depolandığı field'ın başlatma kodunu değiştirin. 527 | 528 | ## Replace Delegation with Inheritance 529 | 530 | ### 🙁 Problem 531 | 532 | Bir sınıf, başka bir sınıfın tüm yöntemlerine yetki veren birçok basit yöntem içerir. Bu ne kadar doğru olabilir ki? 533 | 534 |
535 | 536 | ![](https://refactoring.guru/images/refactoring/diagrams/Replace%20Delegation%20with%20Inheritance%20-%20Before.png) 537 | 538 |
539 | 540 | ### 😊 Çözüm 541 | 542 | Sınıfı bir temsilci mirasçısı (delegate inheritor) yapın, bu da yetki verme yöntemlerini gereksiz kılar. 543 | 544 |
545 | 546 | ![](https://refactoring.guru/images/refactoring/diagrams/Replace%20Delegation%20with%20Inheritance%20-%20After.png) 547 | 548 |
549 | 550 | ### 🤔 Neden Refactoring Uygulanmalı? 551 | 552 | Yetki devri (Delegation), mirasa göre daha esnek bir yaklaşımdır çünkü yetki devrinin nasıl uygulandığını değiştirmeye ve diğer sınıfları da buraya yerleştirmeye olanak tanır. Bununla birlikte, eylemleri yalnızca bir sınıfa ve onun tüm genel yöntemlerine devrederseniz, yetki vermenin yararlılığı sona erer. 553 | 554 | Böyle bir durumda, delegasyonu kalıtımla değiştirirseniz, sınıfı çok sayıda delege etme yönteminden temizlersiniz ve her yeni temsilci sınıf yöntemi için bunları oluşturma zorunluluğundan kurtulursunuz. 555 | 556 | ### ✅ Avantajları 557 | 558 | Kod uzunluğunu azaltır. Tüm bu yetki verme yöntemlerine artık gerek yok. 559 | 560 | ### 🖐🏼 Ne Zaman Kullanılmamalı? 561 | 562 | - Sınıf, temsilci sınıfının genel yöntemlerinin yalnızca bir kısmına yetki içeriyorsa bu tekniği kullanmayın. Bunu yaparak Liskov ikame ilkesini ihlal etmiş olursunuz. 563 | 564 | - Bu teknik yalnızca sınıfın hala ebeveynleri yoksa kullanılabilir. 565 | 566 | 567 | ### 🤯 Nasıl Refactor Edilir? 568 | 569 | 1. Sınıfı, temsilci sınıfının bir alt sınıfı yapın. 570 | 571 | 2. Geçerli nesneyi, temsilci nesnesine referans içeren bir field'a yerleştirin. 572 | 573 | 3. Basit delegasyona sahip yöntemleri birer birer silin. Adları farklıysa tüm yöntemlere tek bir ad vermek için **Rename Method** tekniğini kullanın. 574 | 575 | 4. Temsilci alanına yapılan tüm referansları geçerli nesneye yapılan referanslarla değiştirin. 576 | 577 | 5. Temsilci alanını kaldırın. 578 | 579 | -------------------------------------------------------------------------------- /refactoring-techniques/simplifying-method-calls.md: -------------------------------------------------------------------------------- 1 | # Yöntem Çağrılarını Basitleştirme (Simplifying Method Calls) 2 | 3 | Bu teknikler yöntem çağrılarını daha basit ve anlaşılır hale getirir. Bu da sınıflar arasındaki etkileşim için arayüzleri basitleştirir. 4 | 5 | ## Rename Method 6 | 7 | ### 🙁 Problem 8 | 9 | Bir yöntemin adı, yöntemin ne yaptığını açıklamaması durumunda, koda bakan bir geliştirici işlevin ne yaptığını anlamak için vakit kaybedecektir. 10 | 11 |
12 | 13 | ![](https://refactoring.guru/images/refactoring/diagrams/Rename%20Method%20-%20Before.png) 14 |
15 | 16 | ### 😊 Çözüm 17 | 18 | Yöntemi, yöntemin amacına uygun şekilde yeniden adlandırın. 19 | 20 |
21 | 22 | ![](https://refactoring.guru/images/refactoring/diagrams/Rename%20Method%20-%20After.png) 23 |
24 | 25 | ### 🤔 Neden Refactoring Uygulanmalı? 26 | 27 | Belki de bir yöntem ilk oluşturulduğunda kötü bir şekilde adlandırılmış olabilir; örneğin, birisi yöntemi aceleyle oluşturmuş ve onu iyi adlandırmaya gereken özeni göstermemiştir. 28 | 29 | Diğer bir ihtimal ise, belki de yöntem ilk başta iyi adlandırılmıştı ancak işlevselliği arttıkça yöntem adı, yöntemin amacına uygun bir tanımlayıcı olmaktan çıkmış olabilir. 30 | 31 | ### 🤯 Nasıl Refactor Edilir? 32 | 33 | 1. Yöntem, bir üst sınıfta mı yoksa bir alt sınıfta mı tanımlandığına karar verin. Eğer bu iki durumdan biri var ise, burada listelenen tüm adımları diğer sınıflar için de tekrarlamanız gerekmektedir. 34 | 35 | 2. Bu madde, refactoring işlemi sırasında programın işlevselliğini korumak için önemlidir. Yeni bir adla yeni bir yöntem oluşturun. Eski yöntemin kodunu bu oluşturduğunuz yönteme kopyalayın. Eski yöntemdeki tüm kodu silin ve bunun yerine yeni yöntem için bir method çağrısı (method call) ekleyin. 36 | 37 | 3. Eski yönteme yapılan tüm referansları bulun ve bunları yeni oluşturduğunuz yönteme yapılan referanslarla değiştirin. 38 | 39 | 4. Eski yöntemi silin. Eski yöntem public bir arayüzün (interface) parçasıysa bu adımı gerçekleştirmeyin. Bunun yerine eski yöntemi kullanımdan kaldırılmış (deprecated) olarak işaretleyin. 40 | 41 | ## Add Parameter 42 | 43 | ### 🙁 Problem 44 | 45 | Bir yöntemin hedeflenen amacı gerçekleştirmek için yeterli veriye sahip olmaması sorun oluşturur. 46 | 47 |
48 | 49 | ![](https://refactoring.guru/images/refactoring/diagrams/Add%20Parameter%20-%20Before.png) 50 |
51 | 52 | ### 😊 Çözüm 53 | 54 | Gerekli verileri yönteme iletmek için yeni bir parametre daha oluşturun. 55 | 56 |
57 | 58 | ![](https://refactoring.guru/images/refactoring/diagrams/Add%20Parameter%20-%20After.png) 59 |
60 | 61 | ### 🤔 Neden Refactoring Uygulanmalı? 62 | 63 | Gelen yeni talepler doğrusultusunda, bir yöntemde değişiklik yapmanız gerekebilir. Bu değişiklikler sırasında kullanmanız gereken veri, daha önce yöntemde bulunmayan bilgi veya verilerin eklenmesini gerektirecektir. 64 | 65 | 66 | ### ✅ Avantajları 67 | 68 | Buradaki seçim, yönteme yeni bir parametre eklemek ile yöntemin ihtiyaç duyduğu verileri içeren yeni bir prive field eklemek arasındadır. Her zaman bir nesnede tutmanın bir anlamı olmayan, ara sıra veya sık sık değişen verilere ihtiyaç duyduğunuzda bir parametre tercih edilmesi daha mantıklı olacaktır. Bu durumda, refactoring işe yarayacaktır. Aksi takdirde, private bir field ekleyin ve yöntemi çağırmadan önce bu field'a gerekli değer atamasını yaptığınızdan emin olun. 69 | 70 | ### 🚫 Dezavantajları 71 | 72 | - Yeni bir parametre eklemek her zaman var olan parametreyi kaldırmaktan daha kolaydır; bu nedenle parametre listeleri sıklıkla çok yüksek boyutlara ulaşır. Bu kod koku Uzun Parametre Listesi (**Long Parameter List**) olarak bilinir. 73 | 74 | - Yeni bir parametre eklemeniz gerekiyorsa bu bazen sınıfınızın gerekli verileri içermediği veya mevcut parametrelerin ilgili verileri içermediği anlamına gelir. Her iki durumda da en iyi çözüm, verileri ana sınıfa veya nesnelerine yöntemin içinden zaten erişilebilen diğer sınıflara taşımayı düşünmek olakactır. 75 | 76 | ### 🤯 Nasıl Refactor Edilir? 77 | 78 | 1. Yöntem, bir üst sınıfta mı yoksa bir alt sınıfta mı tanımlandığına karar verin. Eğer bu iki durumdan biri var ise, burada listelenen tüm adımları diğer sınıflar için de tekrarlamanız gerekmektedir. 79 | 80 | 2. Bu ve aşağıdaki adım, refactoring işlemi sırasında programınızı işlevsel tutmak için kritik öneme sahiptir. Eski yöntemi kopyalayarak yeni bir yöntem oluşturun. Sonrasında, oluşturmuş olduğunuz yönteme gerekli parametreyi ekleyin. Eski yöntemin kod body'sini yeni yöntemin çağrısıyla değiştirin. Yeni parametreye bir varsayılan (default) bir değeri ekleyebilirsiniz. 81 | 82 | 3. Eski yönteme yapılan tüm referansları bulun ve bunları yeni oluşturulan yönteme yapılan referanslarla değiştirin. 83 | 84 | 4. Eski yöntemi silin. Eski yöntem public bir arayüzün (interface) parçasıysa bu adımı gerçekleştirmeyin. Bunun yerine eski yöntemi kullanımdan kaldırılmış (deprecated) olarak işaretleyin. 85 | 86 | 87 | ## Remove Parameter 88 | 89 | ### 🙁 Problem 90 | 91 | Bir yöntemin gövdesinde, yöntemin parametrelerinden birinin kullanılmaması bir sorundur. Geliştici, parametre listesi ve yöntem gövdesi arasında bağlantıyı kurmaya çalışırken vakit kaybedebilir. 92 | 93 |
94 | 95 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Parameter%20-%20Before.png) 96 |
97 | 98 | ### 😊 Çözüm 99 | 100 | Kullanılmayan parametreyi yöntemden kaldırın. 101 | 102 |
103 | 104 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Parameter%20-%20After.png) 105 |
106 | 107 | ### 🤔 Neden Refactoring Uygulanmalı? 108 | 109 | Bir yöntem çağrısındaki her parametre, onu okuyan programcıyı bu parametrede hangi bilgilerin bulunduğunu ve ne için kullanıldığını bulmaya zorlar. Ve eğer bir parametre yöntem gövdesinde kullanılmıyorsa, bu durumda geliştiricinin kafasının karışması boşunadır. 110 | 111 | Ve her durumda, ek parametreler çalıştırılması gereken ekstra kodlardır. Bir parametre belrtildiye, bu metod gövdesinde kullanılmalıdır. 112 | 113 | Bazen parametreye ihtiyaç duyulabilecek yöntemde yapılacak değişiklikleri öngörerek geleceğe yönelik parametreler ekleyebiliriz. Yine de deneyimler, bir parametreyi yalnızca gerçekten ihtiyaç duyulduğunda eklemenin daha iyi olduğunu göstermektedir. Sonuçta, beklenen değişiklikler genellikle sadece beklenen olarak kalabilir. Veya, çok uzak bir gelecekte hayata geçebilir. 114 | 115 | ### ✅ Avantajları 116 | 117 | Bir yöntem yalnızca gerçekten ihtiyaç duyduğu parametreleri içermelidir. 118 | 119 | ### 🖐🏼 Ne Zaman Kullanılmamalı? 120 | 121 | Yöntem alt sınıflarda veya üst sınıfta farklı şekillerde kullanılıyorsa, ayrıca parametreniz bu kullanımlarda aktif rol alıyorsa parametreyi olduğu gibi bırakın. 122 | 123 | ### 🤯 Nasıl Refactor Edilir? 124 | 125 | 1. Yöntem, bir üst sınıfta mı yoksa bir alt sınıfta mı tanımlandığına karar verin. Eğer bu iki durumdan biri var ise, burada listelenen tüm adımları diğer sınıflar için de tekrarlamanız gerekmektedir. 126 | 127 | 2. Bir sonraki adım, yeniden düzenleme işlemi sırasında programın işlevsel kalması açısından önemlidir. Eskisini kopyalayarak yeni bir yöntem oluşturun ve ilgili parametreyi oluşturduğunuz yöntemden silin. Eski yöntemin kodunu yenisine yapılan bir çağrıyla değiştirin. 128 | 129 | 3. Eski yönteme yapılan tüm referansları bulun ve bunları yeni yönteme yapılan referanslarla değiştirin. 130 | 131 | 4. Eski yöntemi silin. Eski yöntem public bir arayüzün (interface) parçasıysa bu adımı gerçekleştirmeyin. Bunun yerine eski yöntemi kullanımdan kaldırılmış (deprecated) olarak işaretleyin. 132 | 133 | 134 | ## Separate Query from Modifier 135 | 136 | ### 🙁 Problem 137 | 138 | Değer döndüren ama aynı zamanda nesnenin içindeki bir şeyi değiştiren bir yönteminiz var mı? Bir yöntemin iki işlemi aynı anda yapması sorun oluşturabilir. 139 | 140 |
141 | 142 | ![](https://refactoring.guru/images/refactoring/diagrams/Separate%20Query%20from%20Modifier%20-%20Before.png) 143 |
144 | 145 | ### 😊 Çözüm 146 | 147 | Yönteminizi iki ayrı yönteme bölün. Tahmin edebileceğiniz gibi, bu yöntemlerden biri değeri döndürmesi, diğer yöntem ise nesneyi değiştirmesi gerekiyor. 148 | 149 |
150 | 151 | ![](https://refactoring.guru/images/refactoring/diagrams/Separate%20Query%20from%20Modifier%20-%20After.png) 152 |
153 | 154 | ### 🤔 Neden Refactoring Uygulanmalı? 155 | Bu refaktoring tekniği, Komut ve Sorgu Sorumluluğu Ayrımını (Command and Query Responsibility Segregation) referans alır. Bu prensip bize, veri almaktan sorumlu kodu, bir nesnenin içindeki bir şeyi değiştiren koddan ayırmamızı önerir. 156 | 157 | Veri almak için kullanılan koda sorgu (query) adı verilir. Bir nesnenin görünür durumundaki şeyleri değiştirmeye yarayan koda değiştirici (modifier) adı verilir. Bir sorgu ve değiştirici birleştirildiğinde, state üzerinde değişiklik yapmadan veri almanın bir yolu yoktur. Başka bir deyişle, bir soru sorarsınız ve yanıtı alınırken bile state değiştirmiş olabilirsiniz. Sorguyu çağıran kişi yöntemin yan etkilerini bilmediğinde bu sorun daha da ciddi hale gelir ve bu da genellikle çalışma zamanı hatalarına yol açar. 158 | 159 | Ancak yan etkilerin yalnızca bir nesnenin görünür durumunu değiştiren değiştiriciler olması durumunda tehlikeli olduğunu unutmayın. Bunlar, örneğin bir nesnenin genel arayüzünden erişilebilen alanlar, bir veritabanındaki giriş, dosyalar vb. olabilir. Eğer bir değiştirici yalnızca karmaşık bir işlemi önbelleğe alır ve bunu bir sınıfın özel alanı içine kaydederse, bu durum neredeyse hiç bir yan etki yaratmaz. Etkileri. 160 | 161 | ### ✅ Avantajları 162 | 163 | Programınızın state değerini değiştirmeyen bir sorgunuz varsa, yalnızca yöntemi çağırmanızın neden olduğu sonuçtaki istenmeyen değişiklikler konusunda endişelenmenize gerek kalmaz. Yöntemi istediğiniz kadar çağırabilirsiniz. 164 | 165 | ### 🚫 Dezavantajları 166 | 167 | Bazı durumlarda bir komutu gerçekleştirdikten sonra veri almak daha uygun olur. Örneğin, bir veritabanından bir şey silerken kaç satırın silindiğini bilmek istersiniz. 168 | 169 | ### 🤯 Nasıl Refactor Edilir? 170 | 171 | 1. Orijinal yöntemin yaptığını döndürmek için yeni bir sorgu (query) yöntemi oluşturun. 172 | 173 | 2. Orijinal yöntemi, yalnızca yeni oluşturduğunuz sorgu yönteminin çağıracak ve sonucunu döndürecek şekilde değiştirin. 174 | 175 | 3. Orijinal yönteme yapılan tüm referansları sorgu yöntemine yapılan bir çağrıyla değiştirin. Bu satırın hemen öncesinde değiştirici (modifier) yönteme bir çağrı yapın. Bu yöntem, orijinal yöntemin koşullu bir operatör veya döngü durumunda kullanılması durumunda sizi yan etkilerden kurtaracaktır. 176 | 177 | 4. Artık uygun bir değiştirici yöntem haline gelen orijinal yönteminizde bulunan değer döndüren koddan kurtulun. 178 | 179 | 180 | ## Parameterize Method 181 | 182 | ### 🙁 Problem 183 | 184 | Birden çok yönteminiz olduğu bir senaryo düşünün. Bu yöntemler, yalnızca dahili (internal) değerleri, sayıları veya işlemleri açısından farklı olan ancak temelde benzer eylemleri gerçekleştirebilir. Böyle bir durumda gereksiz bir kod süreci 185 | 186 |
187 | 188 | ![](https://refactoring.guru/images/refactoring/diagrams/Parameterize%20Method%20-%20Before.png) 189 |
190 | 191 | ### 😊 Çözüm 192 | 193 | Gerekli değeri iletecek bir parametre kullanın ve bu yöntemleri birleştirin. 194 | 195 |
196 | 197 | ![](https://refactoring.guru/images/refactoring/diagrams/Parameterize%20Method%20-%20After.png) 198 |
199 | 200 | ### 🤔 Neden Refactoring Uygulanmalı? 201 | 202 | Benzer yöntemleriniz varsa, muhtemelen bunun gerektirdiği tüm sonuçlarla birlikte tekrarlı kodunuz vardır. 203 | 204 | Üstelik bu işlevselliğin başka bir versiyonunu eklemeniz gerekiyorsa başka bir yöntem daha oluşturmanız gerekecektir. Bunun yerine mevcut yöntemi farklı bir parametreyle çalıştırabilirsiniz. Bu işlemi yapmak, kodununuz daha stabil ve anlaşılır olmasını sağlayacaktır. 205 | 206 | ### 🚫 Dezavantajları 207 | 208 | - Bazen bu yeniden düzenleme tekniği çok ileri götürülebilir ve birden fazla basit yöntem yerine uzun ve karmaşık bir ortak yöntem ortaya çıkabilir. Bu da ayrıca kodunuzu karmaşık bir hale sokar. 209 | 210 | - Ayrıca işlevselliğin etkinleştirilmesini/devre dışı bırakılmasını bir parametreye taşırken dikkatli olun. Bu, sonuçta **Replace Parameter with Explicit Methods** tekniği aracılığıyla ele alınması gereken büyük bir koşullu operatörün oluşturulmasına yol açabilir. 211 | 212 | ### 🤯 Nasıl Refactor Edilir? 213 | 214 | 1. Bir parametre ile yeni bir yöntem oluşturun ve **Extract Method** yöntemi uygulayarak, bu yöntemi tüm sınıflar için aynı olan koda taşıyın. Bazen yöntemlerin yalnızca belirli bir kısmının aslında aynı olduğunu unutmayın yani tüm yöntem aynı değil ve düzenlemeye gitmeniz gerekecektir. Bu durumda refactoring, yalnızca aynı parçanın yeni bir yönteme çıkarılmasından oluşacaktır. 215 | 216 | 2. Yeni yöntemin kodunda özel/farklı değeri bir parametre ile değiştirin. 217 | 218 | 3. Her eski yöntem için, çağrıldığı yerleri bulun ve bu çağrıları, parametre içeren yeni yönteme yapılan çağrılarla değiştirin. Daha sonra eski yöntemi silin. 219 | 220 | ## Replace Parameter with Explicit Methods 221 | 222 | ### 🙁 Problem 223 | 224 | Bir yöntem, parametrenin her bir değerine bağlı olarak çalıştırılan farklı parçalara bölünmesi kodunuzu kirli gösterecektir. 225 | 226 | ```java 227 | void setValue(String name, int value) { 228 | if (name.equals("height")) { 229 | height = value; 230 | return; 231 | } 232 | if (name.equals("width")) { 233 | width = value; 234 | return; 235 | } 236 | Assert.shouldNeverReachHere(); 237 | } 238 | ``` 239 | 240 | ### 😊 Çözüm 241 | 242 | Yöntemin içerisinde bulunan ayrı bölümler için, ayrı birer yöntemlerine yöntem oluşturun. Oluşturduğunuz yöntemleri, orijinal yöntem yerine çağırın. 243 | 244 | ```java 245 | void setHeight(int arg) { 246 | height = arg; 247 | } 248 | void setWidth(int arg) { 249 | width = arg; 250 | } 251 | ``` 252 | 253 | ### 🤔 Neden Refactoring Uygulanmalı? 254 | 255 | Parametreye bağlı değişkenler içeren bir yöntem çok büyük bir hızla büyüyecektir. Her parçada önemli kod parçaları çalıştırılır. Bununla beraber, çok nadiren yeni varyantlar eklenir. 256 | 257 | ### ✅ Avantajları 258 | 259 | Kodun okunabilirliğini artırır. `startEngine()` işlevinin amacını anlamak `setValue("engineEnabled", true)` yönteminden çok daha kolaydır. 260 | 261 | ### 🖐🏼 Ne Zaman Kullanılmamalı? 262 | 263 | Bir yöntem nadiren değiştiriliyorsa ve içine yeni değişkenler eklenmemişse dokunmam daha sağlıklı olacaktır. 264 | 265 | ### 🤯 Nasıl Refactor Edilir? 266 | 267 | 1. Yöntemin parametrelere bağlı, her bir parçası için yeni bir yöntem oluşturun. Bu yöntemleri, ana yöntemdeki bir parametrenin değerine göre çalıştırın. 268 | 2. Orijinal yöntemin çağrıldığı tüm yerleri bulun. Bu yerlerde parametreye bağlı yeni değişkenlerden biri için çağrıda bulunan. 269 | 3. Orijinal yöntem için bir çağrı kalmadığında orijinal yöntemi silin. 270 | 271 | 272 | ## Preserve Whole Object 273 | 274 | ### 🙁 Problem 275 | 276 | Bir objeden birkaç değer alıyorsanız ve bunları parametre olarak bir yönteme aktarıyorsanız. Bu kodunuzu gereksiz uzun gösterecektir. 277 | 278 | ```java 279 | int low = daysTempRange.getLow(); 280 | int high = daysTempRange.getHigh(); 281 | boolean withinPlan = plan.withinRange(low, high); 282 | ``` 283 | 284 | ### 😊 Çözüm 285 | 286 | Bunun yerine nesnenin tamamını parametre olarak aktarmayı deneyin. 287 | 288 | ```java 289 | boolean withinPlan = plan.withinRange(daysTempRange); 290 | ``` 291 | 292 | ### 🤔 Neden Refactoring Uygulanmalı? 293 | 294 | Sorun şu ki, yönteminiz her çağrılmadan önce, parametre nesnesinin yöntemlerinin çağrılması gerekir. Bu yöntemler veya yöntem için elde edilen veri miktarı değiştirilirse, programda bu tür bir düzine yeri dikkatlice bulmanız ve bu değişiklikleri her birinde uygulamanız gerekecektir. 295 | 296 | Bu refactoring tekniğini uyguladıktan sonra, gerekli tüm verileri elde etmek için gereken kod tek bir yerde, yani yöntemin kendisinde depolanacaktır. Bu da olası değişikliklerde tek bir yerde değişiklik yapma esnekliği sunacaktır. 297 | 298 | ### ✅ Avantajları 299 | 300 | - Karmaşık parametreler yerine anlaşılır bir isme sahip tek bir nesne ile uğraşmak yeterli olacaktır. 301 | 302 | - Yöntemin bir nesneden daha fazla veriye ihtiyacı varsa, yöntemin kullanıldığı tüm yerleri yeniden yazmanız gerekmez; yalnızca yöntemin kendi içinde yazmanız yeterlidir. 303 | 304 | ### 🚫 Dezavantajları 305 | 306 | Bazen bu dönüşüm bir yöntemin daha az esnek hale gelmesine neden olur: önceden yöntem birçok farklı kaynaktan veri alabiliyordu ancak şimdi yeniden düzenleme nedeniyle kullanımını yalnızca belirli bir arayüze sahip nesnelerle sınırlıyoruz. Bu da yöntemin kullanımını güçleştirecektir. 307 | 308 | ### 🤯 Nasıl Refactor Edilir? 309 | 310 | 1. Yöntem içinde kullanmak üzere, gerekli değerleri alabileceğiniz nesne için bir parametre oluşturun. 311 | 312 | 2. Şimdi eski parametreleri yöntemden birer birer kaldırmaya başlayın ve bunları parametre nesnesinin ilgili yöntemlerine yapılan çağrılarla değiştirin. Bir parametrenin her değiştirilmesinden sonra programı test edin. 313 | 314 | 3. Yöntem çağrısından önce gelen parametre nesnesinden alıcı yani getter kodunu silin. 315 | 316 | 317 | ## Replace Parameter with Method Call 318 | 319 | ### 🙁 Problem 320 | 321 | Bir sorgu yöntemini çağırmak ve sonuçlarını başka bir yöntemin parametreleri olarak iletmek oldukça sık rastlanan bir pattern'dir. Bununla beraber bir yöntem ise sorguyu doğrudan çağırabilir. 322 | 323 | ```java 324 | int basePrice = quantity * itemPrice; 325 | double seasonDiscount = this.getSeasonalDiscount(); 326 | double fees = this.getFees(); 327 | double finalPrice = discountedPrice(basePrice, seasonDiscount, fees); 328 | ``` 329 | 330 | ### 😊 Çözüm 331 | 332 | Değeri bir parametre aracılığıyla iletmek yerine, yöntem gövdesinin içine bir sorgu çağrısı yerleştirmeyi kodun okunurluğu arttıracaktır. Bununla beraber ekstra değişken tanımlamalarının önünce geçer. 333 | 334 | ```java 335 | int basePrice = quantity * itemPrice; 336 | double finalPrice = discountedPrice(basePrice); 337 | ``` 338 | 339 | ### 🤔 Neden Refactoring Uygulanmalı? 340 | 341 | Uzun bir parametre listesini anlamak zordur. Ek olarak, bu tür yöntemlere yapılan çağrılar genellikle, gezinmesi zor ancak yönteme aktarılması gereken değer hesaplamaları ile bir dizi basamağa benzemektedir. Bu nedenle, bir yöntem yardımıyla bir parametre değeri hesaplanabiliyor ise, bunu yöntemin içinde yapın ve bu esktra parametreden kurtulun. 342 | 343 | ### ✅ Avantajları 344 | 345 | Gereksiz parametrelerden kurtuluyoruz ve yöntem çağrılarını basitleştiriyoruz. Bu tür parametreler genellikle şu anki proje için değil, asla gelmeyecek gelecekteki ihtiyaçlar dikkate alınarak oluşturulmaktadır. 346 | 347 | ### 🚫 Dezavantajları 348 | 349 | Yöntemi yeniden yazmanıza neden olacak diğer ihtiyaçlar için yakın bir gelecekte parametreye ihtiyacınız olabilir. 350 | 351 | ### 🤯 Nasıl Refactor Edilir? 352 | 353 | 1. Değer elde eden kodun geçerli yöntemdeki parametreleri kullanmadığından emin olun. Çünkü bu parametreler başka bir yöntemin içinden kullanılamayacaktır. Bu durumda kodun taşınması mümkün değildir. 354 | 355 | 2. İlgili kod tek bir yöntem veya işlev çağrısından daha karmaşıksa, bu kodu yeni bir yöntemde yalıtmak ve çağrıyı basitleştirmek için **Extract Method** yöntemini kullanın. 356 | 357 | 3. Ana yöntemin kodunda, değiştirilen parametreye yapılan tüm referansları, değeri alan yönteme yapılan çağrılarla değiştirin. 358 | 359 | 4. Artık kullanılmayan parametreyi ortadan kaldırmak için **Remove Parameter** tekniğini kullanın. 360 | 361 | 362 | ## Introduce Parameter Object 363 | 364 | ### 🙁 Problem 365 | 366 | Yöntemleriniz yinelenen bir parametre grubu içeriyorsa bu durum bir sorun olabilir. 367 | 368 |
369 | 370 | ![](https://refactoring.guru/images/refactoring/diagrams/Introduce%20Parameter%20Object%20-%20Before.png) 371 | 372 |
373 | 374 | ### 😊 Çözüm 375 | 376 | Bu parametreleri bir nesneyle değiştirin. 377 | 378 |
379 | 380 | ![](https://refactoring.guru/images/refactoring/diagrams/Introduce%20Parameter%20Object%20-%20After.png) 381 | 382 |
383 | 384 | ### 🤔 Neden Refactoring Uygulanmalı? 385 | 386 | Birden fazla yöntemde sıklıkla aynı parametre gruplarıyla karşılaşılabilir. Bu durum, hem parametrelerin hem de ilgili işlemlerin kod tekrarına neden olur. Parametreleri tek bir sınıfta birleştirerek, bu verileri işlemeye yönelik yöntemleri de oraya taşıyabiliriz. Böylelikle diğer yöntemleri bu koddan kurtarabilirsiniz. 387 | 388 | ### ✅ Avantajları 389 | 390 | - Daha okunabilir kod. Karmaşık parametreler yerine anlaşılır bir isme sahip tek bir nesne ile ilgilenmeniz gerekir. 391 | 392 | - Farklı yerlere dağılmış aynı parametre grupları, kendi türlerinde kod tekrarları yaratır: Aynı kod çağrılmazken, sürekli olarak aynı parametre ve argüman gruplarıyla karşılaşılır. Tüm bunları tek bir alan üzerinden yönetmek daha kolay olacaktır. 393 | 394 | ### 🚫 Dezavantajları 395 | 396 | Yalnızca verileri yeni bir sınıfa taşımayı planlayıp, herhangi bir davranışı veya ilgili işlemi bu sınıfa taşımayı planlamıyorsanız, bu bir **Data Class** kokusu olmaya başlar. 397 | 398 | ### 🤯 Nasıl Refactor Edilir? 399 | 400 | 1. Parametre grubunuzu temsil edecek yeni bir sınıf oluşturun. Sınıfı değişmez hale getirin. 401 | 402 | 2. Yeniden düzenlemek istediğiniz yöntemde, parametre nesnenizin aktarılacağı **Add Parameter** tekniğini kullanın. Tüm yöntem çağrılarında, eski yöntem parametrelerinden oluşturulan yeni nesneyi bu parametreye iletin. 403 | 404 | 3. Şimdi eski parametreleri yöntemden birer birer silmeye başlayın ve bunları kodda parametre nesnesinin alanlarıyla değiştirin. Her parametre değişiminden sonra programı test edin. 405 | 406 | 4. İşiniz bittiğinde, yöntemin bir bölümünü (hatta bazen yöntemin tamamını) bir parametre nesne sınıfına taşımanın herhangi bir anlamı olup olmadığına bakın. Eğer öyleyse, **Move Method** veya **Extract Method** tekniğini kullanın. 407 | 408 | 409 | ## Remove Setting Method 410 | 411 | ### 🙁 Problem 412 | 413 | Bir field'ın değeri yalnızca oluşturulduğunda ayarlanmalı ve daha sonra hiçbir zaman değiştirilmemelidir. Böyle bir durumda bu koşulu nasıl sağlayabilirsiniz ki? 414 | 415 |
416 | 417 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Setting%20Method%20-%20Before.png) 418 | 419 |
420 | 421 | ### 😊 Çözüm 422 | 423 | Oldukça basit! Field'ın değerini atayan veya değiştiren yöntemleri kaldırın. 424 | 425 |
426 | 427 | ![](https://refactoring.guru/images/refactoring/diagrams/Remove%20Setting%20Method%20-%20After.png) 428 |
429 | 430 | ### 🤔 Neden Refactoring Uygulanmalı? 431 | 432 | Bir alanın değerinde herhangi bir değişiklik yapılmasını önlemek istiyorsunuz. Ancak bunu nasıl sağlayacağınız konusunda kararsız iseniz, field'ın değerini değiştirilebilecek tüm yöntemleri kaldırın. 433 | 434 | ### 🤯 Nasıl Refactor Edilir? 435 | 436 | 1. Bir alanın değeri yalnızca yapıcıda (constructor) değiştirilebilir olmalıdır. Yapıcı değeri ayarlamak için herhangi bir parametre içermiyorsa bir tane ekleyin. 437 | 438 | 2. Tüm ayarlayıcı (`setter`) aramalarını bulun. 439 | 440 | - Geçerli sınıfın yapıcısına (`constructor`) yönelik bir çağrının hemen ardından bir ayarlayıcı (`setter`) çağrısı bulunursa, argümanını yapıcı (`constructor`) çağrısına taşıyın. Hemen sonrasında ayarlayıcıyı yani setter'ı kaldırın. 441 | 442 | - Yapıcıdaki (`constructor`) ayarlayıcı (`setter`) çağrılarını, field'a doğrudan erişimle değiştirin. 443 | 444 | 3. Ayarlayıcıyı (`setter`) silin. 445 | 446 | ## Hide Method 447 | 448 | ### 🙁 Problem 449 | 450 | Bir yöntem diğer sınıflar tarafından kullanılmamasını veya yalnızca kendi sınıf hiyerarşisi içinde kullanılmasını isteyebilirsiniz. Veya proje sizden bu gereksinimi bekliyor olabilir. 451 | 452 |
453 | 454 | ![](https://refactoring.guru/images/refactoring/diagrams/Hide%20Method%20-%20Before.png) 455 |
456 | 457 | ### 😊 Çözüm 458 | 459 | Yöntemi private veya protected yapın. 460 | 461 |
462 | 463 | ![](https://refactoring.guru/images/refactoring/diagrams/Hide%20Method%20-%20After.png) 464 |
465 | 466 | ### 🤔 Neden Refactoring Uygulanmalı? 467 | 468 | Çoğu zaman, değerleri almak ve ayarlamak için yöntemleri gizleme ihtiyacı, özellikle yalnızca veri kapsüllemenin biraz ötesine eklenen bir sınıfla başladıysanız, ek davranış sağlayan daha zengin bir arayüz geliştirilmesinden kaynaklanır. 469 | 470 | Sınıfa yeni davranışlar eklendikçe, genel alıcı ve ayarlayıcı yöntemlerinin artık gerekli olmadığını ve gizlenebileceğini görebilirsiniz. Alıcı veya ayarlayıcı yöntemlerini private yaparsanız ve değişkenlere doğrudan erişim uygularsanız, yöntemi silebilirsiniz. 471 | 472 | ### ✅ Avantajları 473 | 474 | - Yöntemleri gizlemek kodunuzun gelişmesini kolaylaştırır. Özel bir yöntemi değiştirdiğinizde, yöntemin başka hiçbir yerde kullanılamayacağını bildiğiniz için yalnızca mevcut sınıfın nasıl bozulmayacağı konusunda endişelenmeniz gerekir. 475 | 476 | - Yöntemleri private yaparak sınıfın genel arayüzünün ve genel olarak kalan yöntemlerin önemini vurgulamış olursunuz. 477 | 478 | ### 🤯 Nasıl Refactor Edilir? 479 | 480 | 1. Düzenli olarak private hale getirilebilecek yöntemleri bulmaya çalışın. Statik kod analizi ve iyi birim testi kapsamı büyük bir avantaj sağlayabilir. 481 | 482 | 2. Her yöntemi mümkün olduğunca private yapın. 483 | 484 | ## Replace Constructor with Factory Method 485 | 486 | ### 🙁 Problem 487 | 488 | Nesne alanlarındaki parametre değerlerini ayarlamaktan çok daha fazlasını yapan karmaşık bir kurucunuz (constructor) var. Bu olması gerekenden biraz fazla kompleks bir kurucuya sebep olacaktır. 489 | 490 | ```java 491 | class Employee { 492 | Employee(int type) { 493 | this.type = type; 494 | } 495 | // ... 496 | } 497 | ``` 498 | 499 | ### 😊 Çözüm 500 | 501 | Bir fabrika yöntemi oluşturun ve yapıcı çağrılarını değiştirmek için oluşturduğunuz yöntemi kullanın. 502 | 503 | ```java 504 | class Employee { 505 | static Employee create(int type) { 506 | employee = new Employee(type); 507 | // do some heavy lifting. 508 | return employee; 509 | } 510 | // ... 511 | } 512 | ``` 513 | 514 | ### 🤔 Neden Refactoring Uygulanmalı? 515 | 516 | Bu refactoring tekniğini kullanmanın en belirgin nedeni **Replace Type Code with Subclasses** tekniği ile ilgilidir. 517 | 518 | Daha önce bir nesnenin oluşturulduğu ve kodlanan türün değerinin ona aktarıldığı kodunuz olduğunu düşünelim. Refactoring yöntemini kullandıktan sonra birkaç alt sınıf ortaya çıkacaktır. Kodlanan türün değerine bağlı olarak bunlardan nesneler oluşturmanız gerekebilir. Orijinal kurucuyu (constructor), alt sınıf nesnelerini döndürecek şekilde değiştirmek imkansızdır. Bu yüzden, gerekli sınıfların nesnelerini döndürecek ve ardından orijinal kurucuya yapılan tüm çağrıların yerini alacak statik bir fabrika yöntemi oluşturmak sağlıklı bir çözüm olabilir. 519 | 520 | Fabrika yöntemleri, kurucuların (constructors) göreve uygun olmadığı diğer durumlarda da kullanılabilir. **Change Value to Reference** tekniği kullanırken önemli olabilirler. Ayrıca parametre sayısı ve türünün ötesine geçen çeşitli oluşturma modlarını ayarlamak için de kullanılabilirler. 521 | 522 | ### ✅ Avantajları 523 | 524 | - Bir fabrika yöntemi mutlaka çağrıldığı sınıfın bir nesnesini döndğrmek zorunda değildir. Genellikle bunlar, yönteme verilen argümanlara göre seçilen alt sınıflar olabilir. 525 | 526 | - Bir fabrika yönteminin neyi ve ne yaptığını nasıl döndürdüğünü açıklayan daha iyi bir adı olabilir; örneğin `Troops::GetCrew(myTank)`. 527 | 528 | - Her zaman yeni bir instance oluşturan yapıcının aksine, fabrika yöntemi önceden oluşturulmuş bir nesneyi döndürebilir. 529 | 530 | 531 | ### 🤯 Nasıl Refactor Edilir? 532 | 533 | 1. Bir fabrika yöntemi oluşturun. Mevcut kurucuya (constructor) bir çağrı yapın. 534 | 535 | 2. Tüm yapıcı çağrılarını fabrika yöntemine yapılan çağrılarla değiştirin. 536 | 537 | 3. Yapıcıyı private olarak işaretleyin. 538 | 539 | 4. Yapıcı kodunu araştırın ve geçerli sınıftan bir nesnenin oluşturulmasıyla doğrudan ilgili olmayan kodu izole etmeye çalışın. Daha sonrasında, bu kodu fabrika yöntemine taşıyın. 540 | 541 | ## Replace Error Code with Exception 542 | 543 | ### 🙁 Problem 544 | 545 | Bir yöntem, hatayı belirten özel bir değer mi (-1 gibi) döndürüyor? Böyle bir çözüm yolu kodun anlaşılırlığını düşürecektir. Projeye sonradan katılan biri döndürülen değerin nedenini anlamakta güçlük çekebilir. 546 | 547 | ```java 548 | int withdraw(int amount) { 549 | if (amount > _balance) { 550 | return -1; 551 | } 552 | else { 553 | balance -= amount; 554 | return 0; 555 | } 556 | } 557 | ``` 558 | 559 | ### 😊 Çözüm 560 | 561 | Bunun yerine bir hata fırlatın. 562 | 563 | ```java 564 | void withdraw(int amount) throws BalanceException { 565 | if (amount > _balance) { 566 | throw new BalanceException(); 567 | } 568 | balance -= amount; 569 | } 570 | ``` 571 | 572 | ### 🤔 Neden Refactoring Uygulanmalı? 573 | 574 | Hata kodlarının döndürülmesi, prosedürel programlamanın artık kullanılmayan bir özelliğidir. Modern programlamada hata işleme, istisna (exception) adı verilen özel sınıflar tarafından gerçekleştirilir. Bir sorun ortaya çıkarsa, bir hata "fırlatırsınız" (throw) ve bu daha sonra istisna işleyicilerden biri tarafından yakalanır (caught). Normal şartlarda göz ardı edilen özel hata işleme kodu devreye girerek yanıt verir. 575 | 576 | ### ✅ Avantajları 577 | 578 | - Çeşitli hata kodlarını kontrol etmek, kodu çok sayıda koşulundan kurtarır. İstisna işleyicileri, normal yürütme yollarını anormal olanlardan ayırmanın çok daha kısa ve öz bir yoludur. 579 | 580 | - İstisna sınıfları kendi yöntemlerini uygulayabilir, dolayısıyla hata işleme işlevselliğinin bir kısmını (hata mesajları göndermek gibi) içerir. 581 | 582 | - İstisnalardan farklı olarak, bir yapıcının yalnızca yeni bir nesne döndürmesi gerektiğinden, hata kodları bir yapıcıda kullanılamaz. 583 | 584 | ### 🚫 Dezavantajları 585 | 586 | Bir hata işleyicisi `goto` benzeri bir koltuk değneğine dönüşebilir. Bundan kaçının! Kod yürütmeyi yönetmek için istisnalar kullanmayın. İstisnalar yalnızca bir hata veya kritik durum hakkında bilgi vermek için atılmalıdır. 587 | 588 | ### 🤯 Nasıl Refactor Edilir? 589 | 590 | Bu refactoring adımlarını aynı anda yalnızca bir hata kodu için gerçekleştirmeye çalışın. Bu, tüm önemli bilgileri kafanızda tutmanızı ve hataları önlemenizi kolaylaştıracaktır. 591 | 592 | 1. Hata kodları döndüren bir yönteme yapılan tüm çağrıları bulun ve hata kodunu kontrol etmek yerine onu `try/catch` bloklarıyla sarın. 593 | 594 | 2. Yöntemin içinde bir hata kodu döndürmek yerine bir istisna (exception) atın. 595 | 596 | 3. Yöntem imzasını, atılan istisna hakkında (`@throws` bölümü) bilgi içerecek şekilde değiştirin. 597 | 598 | 599 | ## Replace Exception with Test 600 | 601 | ### 🙁 Problem 602 | 603 | Basit bir testin işi yapabileceği bir yere hata mı atıyorsunuz? Bu konuda oturup düşünmeye değer gibi! 604 | 605 | ```java 606 | double getValueForPeriod(int periodNumber) { 607 | try { 608 | return values[periodNumber]; 609 | } catch (ArrayIndexOutOfBoundsException e) { 610 | return 0; 611 | } 612 | } 613 | ``` 614 | 615 | ### 😊 Çözüm 616 | 617 | İstisnayı bir koşul testiyle değiştirin. 618 | 619 | ```java 620 | double getValueForPeriod(int periodNumber) { 621 | if (periodNumber >= values.length) { 622 | return 0; 623 | } 624 | return values[periodNumber]; 625 | } 626 | ``` 627 | 628 | ### 🤔 Neden Refactoring Uygulanmalı? 629 | 630 | Beklenmeyen bir hatayla ilgili düzensiz davranışları ele almak için istisnalar kullanılmalıdır. Testin yerine geçmemelidirler. Çalıştırmadan önce bir koşulun doğrulanmasıyla bir istisnadan kaçınılabiliyorsa, bunu yapın. Gerçek hatalara istisnalar ayrılmalıdır. 631 | 632 | Mesela bir mayın tarlasına girdiniz ve orada mayını tetiklediniz, sonuçta bir istisna oluştu; istisna başarılı bir şekilde ele alındı ​​​​ve siz, mayın tarlasının ötesindeki güvenli bir yere havaya kaldırıldınız. Ancak başlangıçta mayın tarlasının önündeki uyarı tabelasını okuyarak tüm bunlardan kaçınabilirdiniz. 633 | 634 | ### ✅ Avantajları 635 | 636 | Basit bir koşul bazen istisna işleme kodundan daha belirgin olabilir. 637 | 638 | ### 🤯 Nasıl Refactor Edilir? 639 | 640 | 1. Uç durumu için bir koşul oluşturun ve onu `try/catch` bloğunun önüne taşıyın. 641 | 642 | 2. Kodu bu koşulun içindeki `catch` bölümünden taşıyın. 643 | 644 | 3. `catch` bölümünde, olağan isimsiz bir istisnayı atmak için gereken kodu yerleştirin ve tüm testleri çalıştırın. 645 | 646 | 4. Testler sırasında herhangi bir istisna oluşturulmadıysa `try/catch` operatöründen kurtulun. 647 | --------------------------------------------------------------------------------