Silmesi Kolay, Genişletmesi Zor Kod Yazmak (2016)
(programmingisterrible.com)- Kod, yazıldığı anda bakım maliyeti doğurur; bu yüzden çoğu zaman yeniden kullanılabilirlikten ziyade ileride silmesi veya değiştirmesi kolay bir yapı daha önemlidir
- API kullanıcıları arttıkça değişiklik maliyeti büyür; üçüncü taraf API bağımlılığı derinleştikçe dış değişimler kod tabanını daha fazla sarsar
- Tekrar, boilerplate, katmanlama, büyük kod yığınları, modül ayırma ve özellik bayrakları, duruma göre bağımlılık yönetimi araçlarına dönüşür
- İyi ayrıştırma, ortak işlevleri bir araya toplamak değil; değişmesi zor ya da değişme olasılığı yüksek tasarım kararlarını birbirinden gizlemeye daha yakındır
- İyi kod, en baştan kusursuz kod değil; zaman geçse de daha az engel çıkaran legacy koddur ve nihayetinde silmesi kolay koddur
Kod maliyettir, silmek maliyeti düşürmektir
- Her kod, yazıldığı anda bakım maliyeti yaratır; yeniden kullanım kod miktarını azaltabilir ama sonradan fikir değiştirmeyi zorlaştırabilir
- Bir API’yi kullanan kod ne kadar çoksa, API değişiklikleri de o kadar fazla yeniden yazma maliyeti getirir
- Üçüncü taraf API’lere ne kadar çok bağımlı olursanız, o API değiştiğinde alacağınız etki de o kadar büyük olur
- Büyük ölçekli sistemlerde, kodun birbirine nasıl geçtiği ve hangi parçanın hangi parçaya bağımlı olduğu zaman geçtikçe daha zor bir mesele hâline gelir
- Kod satırı sayısına “üretilen satır” değil “harcanan maliyet” olarak bakarsanız, kod silmek bakım maliyetini düşürmek demektir
- Amaç yalnızca yeniden kullanılabilir yazılım yapmak değil, atılabilir yazılım yapmaktır
0. adım: Kod yazmamak
- Kod satırı sayısı tek başına her şeyi anlatmaz; ama 50 satır, 500 satır, 5.000 satır, 10.000 satır, 25.000 satır gibi ölçek önemlidir
- 1 milyon satırlık bir monolith’i değiştirmek, 10 bin satırlık bir monolith’i değiştirmekten daha fazla zaman, para ve emek ister
- Kod arttıkça ortadan kaldırması zorlaşır; ama tek bir kod satırını azaltmak neredeyse hiçbir şey tasarruf ettirmez
- Silmesi en kolay kod, en başta yazılmamış koddur
1. adım: Kopyala-yapıştır yapmak
- Yeniden kullanılabilir kodu gelecekteki kullanım yerlerini tahmin ederek önceden yazmaktansa, birden fazla kullanım senaryosu gerçekten ortaya çıktıktan sonra yazmak daha kolaydır
- Kod tabanında birkaç kez kopyala-yapıştır yapmak, gerçek kullanım biçimlerini anlamak için iyi bir yoldur
- Bir kodu paylaşılan API hâline getirdiğiniz anda o kodu değiştirmek zorlaşır
- Bir fonksiyonu çağıran kod, yalnızca belgelenmiş davranışa değil, uygulamada gözlenen kasıtlı ve kasıtsız davranışlara da bağımlı hâle gelir
- Bir fonksiyonun içindeki kodu silmek, fonksiyonun kendisini silmekten daha basittir
2. adım: Kopyala-yapıştırı durdurmak
- Yeterince tekrarlanmış kodu fonksiyona çıkarmanın zamanı gelmiş demektir
- Yapılandırma dosyasını açıp hash table döndüren kod, dizin silme kodu gibi standart kütüphane üzerinde sık gereken utility türü kodlar buna girer
utili tek bir dosya yerine dizin olarak tutup farklı utility’leri farklı dosyalara koymak daha iyidir- Tek bir
utildosyası büyümeye devam eder; fazla büyüdükten sonra bölmek zorlaşır
- Tek bir
- Uygulamaya veya projeye daha az özgü kodun yeniden kullanımı daha kolaydır; değişme ya da silinme olasılığı daha düşüktür
- Loglama, üçüncü taraf API’ler, file handle’lar, process’ler gibi kütüphane kodları buna girer
- Listeler, hash table’lar ve collection’lar yalnızca basit arayüzleri nedeniyle değil, zamanla kapsamları büyümediği için de kolay kolay silinmez
- Esas nokta, silmesi zor kısımları silmesi kolay kısımlardan olabildiğince uzak tutmaktır
3. adım: Daha fazla boilerplate yazmak
- Kütüphane yazmak kopyala-yapıştırı önleyebilir; ama pratikte kütüphaneyi kullanmak için bol miktarda boilerplate yazarsınız
- Boilerplate, her seferinde biraz farklı yerleri değiştirmeniz bakımından kopyala-yapıştırmaya benzer
- Bu tür tekrar, bağımlılıkları azaltıp esneklik kazanmanın bedeli olarak söze döküklüğü kabullenme biçimidir
- Boilerplate gerektiren kütüphaneler çoğu zaman ağ protokolleri, wire format’lar, parsing araçları gibi politika ile protokolün karıştırılmasının zor olduğu durumlardır
- Protokol, programın ne yapabileceğiyle ilgilenir
- Politika, programın ne yapması gerektiğiyle ilgilenir
- Bu tür kodlar çoğunlukla başka bilgisayarlarla iletişim kurmak veya başka dosyalarla çalışmak için gereken şartlardır; bu yüzden silmeleri zordur
- İş mantığını bu kodların içine serpiştirmemek önemlidir
- Daha fazla satır yazacaksanız bile, bu satırları silmesi kolay kısımlarda yazmak daha iyidir
4. adım: Boilerplate yazmamak
- Boilerplate fazla çoğaldığında, esnek kütüphaneyi saran; politika, workflow ve durum hakkında görüş sahibi bir kütüphane yazmanın zamanı gelmiştir
- Kullanımı kolay bir API yapmak, boilerplate’i kütüphaneleştirmeye yakındır
- Python HTTP istemcisi
requests, daha uzun ve ayrıntılıurllib3üzerinde basit bir arayüz sunan bir örnektirrequests, HTTP kullanımının yaygın workflow’unu ele alır ve pratik ayrıntıları gizlerurllib3, pipelining, bağlantı yönetimi vb. sağlar ve ayrıntıları kullanıcıdan gizlemez
- Bir kütüphaneyi başka bir kütüphaneyle sarmak yalnızca ayrıntıları gizlemek değil, concern separationdır
utildizinine iş mantığı koymamak; uygulaması basit kütüphanelerin üzerine kullanımı kolay kütüphaneler yığmak daha iyidir- Üçüncü taraf kütüphaneleri de sarmanın iyi olduğu durumlar vardır
- Tüm projenin belirli bir seçime kilitlenmemesi için kendi kodunuza uyan bir kütüphane oluşturabilirsiniz
- Kullanımı iyi API ile genişletilebilir API çoğu zaman birbiriyle çatışır
- Katmanlama, ileride silinecek kod yazmaktan ziyade, silmesi zor kodu iş mantığıyla kirletmeden kullanımı kolay hâle getirmeye daha yakındır
5. adım: Büyük kod yığınları yazmak
- Kopyala-yapıştır, refactoring, katmanlama ve composition yapsanız da kodun eninde sonunda bir iş yapması gerekir; bu yüzden bazen geri kalanı bir arada tutan büyük bir kod yığınına ihtiyaç olur
- İş mantığı, bitmeyen edge case’ler ve hızlı hack’lerle tanımlanabilir
- Oyun kodu veya kurucu kodu da önemli ölçüde zaman kazanmak için kestirme yollar seçen aynı tür kod olarak görülebilir
- Birbirine dolanmış 18 küçük hatayı ortadan kaldırmaktansa tek bir büyük hatayı silmek bazen daha kolaydır
- Programlamanın çoğu keşifseldir; bu yüzden en baştan doğruyu tutturmaya çalışmaktansa birkaç kez yanılıp yinelemek daha hızlı olabilir
- İlk oyununuzu yaparken önce motor yazmayın; bir uygulama yazmadan önce web framework’ü yapmaya kalkmamak daha iyidir
- Monorepo da benzer bir ödünleşimdir
- Kodu önceden nasıl böleceğinizi bilmek zordur ve güçlü biçimde bağlı 20 parçadansa tek büyük hata dağıtmak daha kolaydır
- Kodun yakında atılacağını, silineceğini veya kolayca değiştirileceğini biliyorsanız daha fazla kestirme yol seçebilirsiniz
- Amaç aynı çamur yığınını on kez tekrarlayıp hatayı mükemmelleştirmek değil; her seferinde yeni hatalar yapıp yeni riskler alarak iterasyonla biriktirmektir
- Projeler sonunda ya başarısız olur ya da legacy code’a dönüşür; başarısızlık başarıdan daha sık yaşanır
- Kodu parça parça silmektense tamamını silmek daha kolaydır
6. adım: Kodu parçalara ayırmak
- Büyük çamur yığınını yapmak en kolaydır ama bakım maliyeti en yüksektir
- Basit görünen bir değişiklik, kod tabanının neredeyse her yerini geçici çözümlerle kurcalamanıza yol açabilir
- Bütün hâlinde silmesi kolay olan kod, parça parça silmesi zor hâle gelir
- Modülleri ortak işlevlere göre değil; geri kalanla paylaşılmayan şeylere ve gizlenmesi gereken tasarım kararlarına göre ayırmak daha iyidir
- D. Parnas’ın ölçütü gibi, zor veya değişme olasılığı yüksek tasarım kararlarını listeleyip her modülü bu kararları diğer modüllerden gizleyecek şekilde tasarlayabilirsiniz
- Modüller yeniden kullanım için değil, değişebilirlik için yapılır
- Tek sorumluluk ilkesi, “her modül yalnızca tek bir zor problemle ilgilenmeli” diye görülebilir; ama daha önemli olan, “her zor problem yalnızca tek bir modülde ele alınmalı” noktasıdır
- Bir modül iki iş yapıyorsa, çoğu zaman bir tarafı değiştirmek için diğer tarafı da değiştirmeniz gerektiği içindir
- Basit arayüzlü korkunç tek bir component, dikkatli koordinasyon gerektiren iki component’ten daha kolay olabilir
Gevşek bağlılık ve ortak arayüz
- Diğer kısımları yeniden yazmadan bazı parçaları silebildiğiniz sistemlere genellikle gevşek bağlı denir
- Gevşek bağlılık, fikir değiştirdiğinizde çok fazla kodu değiştirmeniz gerekmeyen duruma yakındır
- Bir değişkeni bir kez hardcode etmek, değişken yerine komut satırı flag’i kullanmak bile duruma göre gevşek bağlılık olabilir
- Microsoft Windows, dış API ile iç API’yi ayırarak bu amaca ulaşır
- Dış API, masaüstü programlarının yaşam döngüsüne bağlıdır
- İç API, temel kernel’a bağlıdır
- API’yi gizlemek, çok sayıda yazılımı bozmadan esneklik sağlar
- HTTP de gevşek bağlılığa örnek sunar
- HTTP sunucusunun önüne cache koyabilirsiniz
- Görselleri CDN’e taşıyıp yalnızca linkleri değiştirseniz de tarayıcı bozulmaz
- HTTP hata kodları, yaygın problemlere benzersiz kodlar vererek client’ın çok sayıda hatayı onun yerine ele almasını sağlar
- Arıza işleme biçimi, kodu küçük parçalara bölerken birlikte düşünülmelidir
Arıza yönetimi ve bağlılık
- Erlang/OTP, arızaları supervision tree ile ele alan görece özgün bir yöntem kullanır
- Erlang sistemindeki her process kabaca bir supervisor tarafından başlatılır ve izlenir
- Process’te sorun çıkarsa sonlandırılır
- Process sonlanırsa supervisor onu yeniden başlatır
- Supervisor’ı bootstrap process başlatır; supervisor’da arıza olursa bootstrap process onu yeniden başlatır
- Temel fikir, hatayı işlemeye çalışmaktansa hızlı başarısız olup yeniden başlamanın daha hızlı olduğudur
- Geçici arızalar bazen kapatıp açma yöntemiyle bastırılır
- Hata işleme ve kurtarma işlerini kod tabanının dış katmanlarında yapmak daha iyidir; bu end-to-end principle olarak bilinir
- Hataları bağlantının ortasında değil iki ucunda ele almak daha kolaydır; içeride ele alınsa bile en üst seviye kontrol yine gerekir
- Hata işleme, sistemi güçlü biçimde birbirine bağlayan birçok yoldan biridir
IMAP, dosya sistemleri, SQL, middleware
- IMAP, neredeyse her işlemin kendine özgü seçenek ve işleme sahip istisnai bir biçim olduğu; bu yüzden hata işlemenin sancılı olduğu bir örnektir
- IMAP’te hata, başka işlem sonuçlarının ortasında belirebilir
- UUID yerine her mesajı tanımlamak için benzersiz token’lar üretir; bu token’lar da işlem sonuçlarının ortasında değişebilir
- Birçok IMAP işlemi atomic değildir
- E-postayı bir klasörden diğerine güvenilir biçimde taşımanın bir yolunun ortaya çıkması 25 yıldan fazla sürdü
- Özel UTF-7 encoding’i ve kendine özgü base64 encoding’i de vardır
- Dosya sistemleri ve veritabanları, uzak depolama için daha iyi karşılaştırma örnekleri sunar
- Dosya sistemi sabit bir işlem kümesine ve birden fazla nesneye sahiptir
- SQL, dosya sisteminden daha geniş bir arayüz gibi görünür; ama kümeler üzerinde birden fazla işlem ve birden fazla satır örüntüsünü izler
- Veritabanları her zaman birbirinin yerine geçemez; ama kendi sorgu dilinizi yazmaktansa SQL ile çalışan bir şey bulmak daha kolaydır
- Twitter’ın Finagle’ı, servisler için ortak bir API kullanarak timeout işleme, retry mekanizması ve kimlik doğrulama kontrollerinin istemci ve sunucu koduna kolayca eklenmesini sağlar
- Gevşek bağlılığın iyi örnekleri çoğu zaman tekdüze arayüz örnekleridir de
- Sağlıklı bir kod tabanının kusursuz modüler olması gerekmez; ama hareketli parçalar arasında yeterli mesafe olmalıdır
- Gevşek bağlı kodun silmesi illa kolay değildir; ama değiştirmesi ve yerine başkasını koyması çok daha kolaydır
7. adım: Kod yazmaya devam etmek
- Eski kodla uğraşmadan yeni kod yazabiliyorsanız yeni fikirleri denemek çok daha kolaydır
- Esas mesele microservice mi monolith mi olduğu değil; ne yaptığınızı anlamaya çalışırken sistemin üzerine bir iki deney koyabilmenizdir
- Özellik bayrakları, sonradan fikir değiştirebilmenin bir yoludur
- Özellik bayrakları yalnızca özellik denemeleri değil, yazılımı yeniden dağıtmadan değişiklikleri dağıtmayı da mümkün kılar
- Google Chrome, düzenli yayın döngüsünde uzun ömürlü feature branch’leri birleştirmenin en zor kısım olduğunu gördü
- Yeni kodu yeniden derlemeden açıp kapatabiliyorsanız büyük değişiklikleri küçük merge’lere bölebilir ve mevcut kodu etkilemeyebilirsiniz
- Yeni özellik aynı kod tabanında daha erken görünürse, uzun vadeli özellik geliştirmenin diğer kısımlara etkisini daha net görebilirsiniz
- Özellik bayrağı basit bir komut satırı anahtarı değil; özellik yayınını branch merge’ünden ve kod dağıtımından ayırmanın bir yoludur
- Yeni yazılım dağıtımı saatler, günler, haftalar alabildiğinde runtime’da fikir değiştirebilme yeteneği daha da önemli hâle gelir
İyi kod, engel çıkarmayan legacy koddur
- Yineleme yapmanızdan daha önemli olan, bir geri bildirim döngüsüne sahip olmanızdır
- Modülleri yeniden kullanım için yapmak yerine, değişiklik için component’leri izole etmek esastır
- Değişime yanıt vermek, yalnızca yeni özellik geliştirmeyi değil eski özellikleri kaldırmayı da kapsar
- Genişletilebilir kod yazmak, üç ay sonra ilk seçimin hâlâ doğru olmasını ummaktır
- Silinebilir kod bunun tersi varsayımdan yola çıkar
- Katmanlama, izolasyon, ortak arayüz ve composition; iyi yazılımın kendisinden ziyade zamanla değişebilen yazılım üretmenin yollarıdır
- Her şeyi atmanız gerekmez ama bazı şeyleri silmeniz gerekir
- İyi kod, en baştan doğru yazılmış kod değil; engel çıkarmayan legacy koddur
- İyi kod silmesi kolay koddur
1 yorum
Hacker News yorumları
Sevdiğim sözlerden biri şudur: basitlik sağlamlıktır
Lehman’ın sürekli değişim yasasına benzer şekilde, bir sistemin karmaşıklığı ne kadar düşükse onu değiştirmek de o kadar kolay olur demek
Geleceğe hazırlık için genişletilebilir kod yazmaktansa, sezgisel kod ile geleceğe hazırlanmanın daha iyi olduğunu düşünüyorum
Örneğin soyutlamayı yalnızca gerçekten gerektiğinde yapmak, basit tekrarları kabul etmek, başlangıçta monolit olarak başlamak ve yatay ölçeklemeden önce dikey ölçeklemeyi denemek gibi
Birden fazla 0→1 sistem geliştirdim; hepsinde ortak akış bu yöndeydi
https://en.m.wikipedia.org/wiki/Lehman%27s_laws_of_software_...
Uç durumları ele almamak kodu sağlam yapmaz; ne kadar daha basit görünürse görünsün
“Basitlik” nedir ve sisteme nasıl uygulanır tartışması açılıyor; Rich Hickey’nin ele alacağı kadar karmaşık bir soru bu
Belki “aptal olan sağlamdır” ya da “dolaysız olan sağlamdır” niyeti daha iyi anlatabilir
Sadece gereken işi yapan kodu yazmak yeterli. Varsayımsal ölçekleme sorunları icat etmeyin, akıllı görünmek için zeki soyutlamalar üretmeyin; monolit olarak yazıp bir VM’e koyarsanız hemen üretime alınabilir
Sorun çıkarsa o zaman çözersiniz; mümkünse nakit akışı pozitife döndükten sonra olması daha iyi
0 kullanıcılı “köpekler için AirBnb” girişimi neden C100K’yı dert ediyor? AWS’nin sizi serverless’a para ödemeye ikna etmesi sizin çıkarınız için miydi, yoksa sizden para çekmek için mi
İlgili yazılar:
Write code that is easy to delete, not easy to extend (2016) - https://news.ycombinator.com/item?id=24989351 - Nov 2020 (30 comments)
Write code that is easy to delete, not easy to extend (2016) - https://news.ycombinator.com/item?id=23914486 - July 2020 (109 comments)
Write code that is easy to delete, not easy to extend - https://news.ycombinator.com/item?id=18761739 - Dec 2018 (2 comments)
Write code that is easy to delete, not easy to extend - https://news.ycombinator.com/item?id=11093733 - Feb 2016 (133 comments)
Gençken yaptığım hataları kısaca özetlemek gerekirse, artık tersine silmek için tasarıma inanıyorum
Eskiden her durumu öngören ve her gereksinimi karşılayan harika bir sanat eseri yapabileceğimi sanırdım. Ama kimse gelecekteki gereksinimleri bu kadar iyi tahmin edemez
Bir gün yaptığım şey birinin gözünde “şu aptal şey” olacak ve ben bugün onunla ne kadar gurur duyarsam duyayım, onların hepsini yıkıp atması haklı olabilir
Bu yüzden kaldırması kolay hale getirmeye enerji harcamak daha iyi. Bu çoğu zaman bağımlılığı azaltır; ama önemli nokta, bunun her şeyi meta yapılandırılabilir bir framework’e ayırmaya hevesli genç geliştiricinin bağımlılıktan arındırmasıyla aynı şey olmamasıdır
Bazen anlaşılması kolay güçlü bağlılık daha iyi olabilir
https://news.ycombinator.com/item?id=41219130
Örneğin CommonExcelFileParser, CommonExcelFileParserUtilities, HasExcelParseStatus, ProductImportExcelParser, ProductImportExcelParserView, ProductImportExcelParserResultHandler gibi şeyler ortaya çıkar ve çevredeki kodun temeli haline gelir
Bir frontend projesine React veya Angular ile başlarsanız başka bir şeye taşımak Sisifos’un işi haline gelir; buna benzer
Gerçekte insanlar bütün bir platform inşa eder ve gelecekte sorun çıkaracak seçimler olsa bile, bağlılık nedeniyle refactoring yapmak az soyutlanmış bir kod tabanına kıyasla çok daha zorlaşır
İnsanlar KISS ve YAGNI uygulayıp silmesi kolay kod yazmaktansa böyle şeyleri daha çok seviyor gibi; böyle olduğunda ne yapmak gerektiğini bilmiyorum
İş gereksinimleri değişir ve hareket eder; bu yüzden onları tahmin etmeye çalışmayın, değiştirmesi ya da atması kolay şeyler yazın
Framework’ler ve kütüphaneler biraz farklıdır. Dünyadaki değişime uyum sağlamaları gerekir ama bunu çok daha ılımlı bir hızda yapmaları yeterlidir
En büyük sorun, Rails veya Asp.Net gibi bir framework’ün zaten kullanıldığı iş uygulamalarında geliştiricilerin bir de “framework” yapmak istemesidir
Linux çekirdeği yazmıyorsanız Linux çekirdeği gibi yazmamalısınız
Bu yazıda testler ve gözlemlenebilirlik konusuna hiç değinilmemesi epey tuhaf
Testlerin de bakım maliyeti var, ama bir şeyi kaldırdığınızda bir şeyleri bozma riskini azaltırlar
Üstelik bir servisi dış çağıranlara açtıysanız, bazı çağrıları kullanımdan kaldırılacak olarak işaretleyip daha sonra silebilmenin sağlam bir yoluna da, hâlâ çağrılıp çağrılmadığını ve kimin çağırdığını gözlemlemenin bir yöntemine de ihtiyacınız var
Yakın zamanda dışa açık bir GraphQL resolver’ı ilk kez yarı otomatik biçimde kaldırdık; belirli bir resolver’ın ne kadar sık kullanıldığına dair metrikler zaten vardı, bunları parse ederek silinemeyecek resolver’ların listesini elde ettik
GraphQL’de zaten deprecated annotation var, ama bizim servisimiz bu annotation’ı özel olarak işlemiyordu
Bu yüzden deprecated bir fonksiyon çağrıldığında bunu gösteren gözlemlenebilirlik ekledik ve prod ortamında yeterince uzun süre çalıştırdıktan sonra, dışa açık kodu güvenle silebilir hâle geldik
Aşırı karmaşık hâle getirmeye başlarsanız her şey birbirine bağlı bir karmaşaya dönüşür ve geliştirici bir değişikliğin neyi etkileyeceğini bilemez
Elbette bunu berbat etmenin birçok yolu var. Aptalca “en iyi pratik” ilkelerini izleyebilirsiniz ya da hangi servisi kimin tükettiğini bilmediğiniz bir şekilde “mikroservis” yapabilirsiniz. Ama o zaman silmesi kolay bir şey yapmış olmazsınız
Dış tüketim iyi bir örnek. Bir servisi devreden çıkarma konusunda tüketicilere makul bir uyarı vermek mantıklıdır; ama istediğinizde gerçekten kapatamıyorsanız kolayca silinecek şekilde tasarlanmış bir sistem değildir
Doğru yaklaşım buysa öyle yapabilirsiniz. Yalnız testlerin ve gözlemlenebilirliğin bir şeyin kırılıp kırılmadığını size söylemesini beklemek muhtemelen pek iyi çalışmaz
Testlere karşı değilim, ama uzun ve karmaşık bir zincirde bir şeyi kırıp kırmadığınızı söyleyen bir güvenlik mekanizması olarak olağanüstü olduklarını söylemek zor. Çünkü gerçekten koruma sağlayacak test kapsamına sahip olmak da çok zordur
Kodun bir kısmını silerseniz testlerin de bir kısmını silebilirsiniz
Yazıdaki gibi yalnızca koddan bahsedilip testler üzerindeki ilgili etkilerin örtük olarak dahil edildiği düşünülebilir
Yazı testlerden bahsetmedi diye test yazmayın dediği varsayılamaz
Şu bölüme bakınca başlığın her zaman doğru olmadığını hissediyorum: silmesi kolay kod çoğu zaman genişletmesi de kolay kod olur
Çünkü katmanlıdır, modülerdir ve arayüzler ya da başka tip sözleşmeleri gibi soyutlamalar üzerinden farklı parçaları birbirinden yalıtır
Hesaplamalı fizik öğrencilerine en iyi hesaplamanın, hiç yapmak zorunda kalmadığınız hesaplama olduğunu söyleyegeldim
Kişisel olarak kodu iki parçaya ayırıyorum: iş mantığı ve gerçek implementasyon
İş mantığı doğası gereği yinelenebilir, ama teknik ayrıntılar çok fazla yinelenmemeli
Gerçek implementasyon, iş mantığını doğrudan barındırmadığı ve uygulamadan bağımsız tutulduğu sürece istediği kadar dağınık olabilir
Böyle yaptığınızda bir şeylerin berbat ve düzgün çalışmadığını fark ettiğinizde, implementasyondan gerçek spesifikasyonu geriye doğru izleyip zorla düzeltmek yerine tüm implementasyonu silip atma seçeneğiniz olur
İlk paragraftaki “kod yeniden kullanımının sorunu, daha sonra fikrinizi değiştirmenizi engellemesidir” ifadesi bariz bir hata
Genel olarak söylersek yanlış. Fikriniz değiştiğinde kod on yere kopyala-yapıştır yapılmışsa on yeri düzeltmeniz gerekir
Buna karşılık bir fonksiyonun içindeyse bir kez değiştirmeniz yeter. On çağrıdan birinin değişmemesi gerektiğini sonradan fark etseniz bile, o noktada kopyala-yapıştır yapabilir ya da fonksiyonu daha genel hâle getirebilirsiniz
Karşıdan karşıya geçerken bakmadan geçmek gibi, kopyala-yapıştır neredeyse her zaman kötü bir fikirdir
Ama kötü soyutlama aylar süren teknik borç ödemesine yol açar
Elbette cevap “kötü soyutlamalar yapmayın”dır; ama ekipler ve değişen ürün gereksinimleri içinde bunun nasıl sonuçlandığını hepimiz biliyoruz
Ortak UI widget’larını içeren bir git submodule’ümüz var; artık içlerinden birini değiştirmek neredeyse imkânsız, bu yüzden bileşeni projenin içine kopyalayıp yerelde değiştirmek daha kolay
Bu bir sorun. Paylaşılan kod mümkün olduğunca az olmalı; paylaşımın kendisi değişikliği zorlaştırır
Her şey tek bir fonksiyondaysa çoğu geliştirici o fonksiyonu 10 durumun hepsini karşılayacak şekilde değiştirmeye çalışır. Oysa en başta tek bir fonksiyon olmaması gerekirdi
Bir kez bağlanıp sistemin parçalarını tutan yanlış bağlanmış bir düğümü çözmektense, kopyala-yapıştır yapılmış on yeri düzeltmek çok daha kolaydır
Dışarıdan bakınca bu konuda kendi içinde çelişiyor gibi görünüyor, ama yavaş okuyunca kopyala-yapıştırı hangi kodun soyutlanması gerektiğini ve gerçekten izlenmesi gereken desenin ne olduğunu gösteren bir sinyal olarak kullandığını görüyorsunuz
Yazılımla ilgili türlü türlü kaidenin, neredeyse dinî ilkeler gibi şeylerin sürekli tekrarlanması tuhaf
Kâğıt üzerinde hepsi harika görünüyor ve sağduyu gibi geliyor, ama 50 yıl geçmesine rağmen yazılım vakaların %90’ında çöp
Yine de bunlar dâhiyane içgörüler ya da gümüş kurşunlarmış gibi sürekli tekrar gündeme getiriliyor
Burada harika bir sonuç önerme var. Kötü kodu kaldırmak çok daha zor olduğu için daha uzun süre kalır