KISS Eylem İlkesi

Jan 04 2023
Neden basit tuttuğumuza dair kısa bir örnek KISS, Trendyol'da özellikleri uygularken benimsediğimiz ilkelerden biridir. Çoğumuz kod bloklarını incelerken bazı karmaşık uygulamalarla karşılaştık; Uyum sağlamanın veya üretim sorununu çözmenin ne kadar zaman alacağını okumak ve anlamak zor.

Neden basit tuttuğumuza dair kısa bir örnek parçası

KISS, Trendyol'da özellikleri uygularken benimsediğimiz ilkelerden biridir. Çoğumuz kod bloklarını incelerken bazı karmaşık uygulamalarla karşılaştık; Uyum sağlamanın veya üretim sorununu çözmenin ne kadar zaman alacağını okumak ve anlamak zor.
Önce KISS prensibini inceleyelim, ardından kısa bir örnek verelim.

ÖPÜCÜK nedir?

KISS , " Keep It Simple, Stupid " (en yaygın) kelimelerinin kısaltmasıdır . Ancak "çok basit tutun", "kısa ve basit tutun", "basit ve anlaşılır tutun" veya "küçük ve basit tutun" gibi pek çok varyasyon vardır. (sadece programlama değil).

Sadece bir bakışla kolay görülebilir; ama aslında, KISS'i başarmak zordur ve aynı zamanda yaşlılar tarafından bile gözden kaçırmak kolaydır.
İnsanoğlunun dahilerinden bazı alıntılar:

"Basitlik en üst düzeyde karmaşıklıktır" - Leonardo Da Vinci
"Az daha çoktur" - Ludwig Mies van der Rohe
"Eklenecek bir şey kalmadığında mükemmelliğe ulaşılmamış gibi görünüyor, ancak çıkarılacak bir şey kalmadığında" - Antoine de Saint-Exupery

Ayrıca Occam'ın usturasını da inceleyebilirsiniz .

Yazılım Tasarımında KISS'i benimsemenin faydaları

  • KISS daha iyi kullanılabilirlik sağlar: Basit ve sezgisel yazılım, kullanıcıların anlaması ve kullanması için daha kolaydır, bu da deneyimlerini geliştirebilir ve yazılımın benimsenmesini artırabilir.
  • KISS daha iyi bakım sağlar: Basit bir tasarıma sahip yazılım, geliştiricilerin anlaması ve değiştirmesi için daha kolaydır; bu da, yazılımı kullanım ömrü boyunca sürdürmek için gereken zaman ve çabayı azaltabilir.
  • KISS daha iyi güvenilirliğe yol açar: Basit bir tasarıma sahip yazılım, güvenilirliğini artırabilecek ve maliyetli arıza süresi riskini azaltabilecek şekilde hatalara ve hatalara daha az eğilimlidir.

KISS'i benimserken elde edebileceğimiz faydalar bile:

  • Sınırlı işlevsellik: Basitliğe odaklanarak, yazılımın işlevselliğini sınırlamak ve karmaşık sorunları çözme konusunda daha az yetenekli hale getirmek mümkündür.
  • Azaltılmış esneklik: Basit yazılımlar daha az esnek olabilir ve değişen gereksinimlere veya yeni kullanım durumlarına uyarlanabilir.
  • Uzun vadede artan karmaşıklık: Bazı durumlarda, başlangıçta basit olacak şekilde tasarlanan yazılımlar, yeni özellikler eklendikçe veya yazılım değişen ihtiyaçları karşılamak üzere değiştirildikçe zaman içinde daha karmaşık hale gelebilir.

Bir örnek

Sorun

Farazi ama ortak bir problem düşünelim; çok sayıda veri var, eşit olarak dağıtılmış, rastgele, benzersiz bir tamsayı anahtarı olan 100 milyon demet diyelim. Onlardan bir şeyler alıp hesaplamamız ve bu hesaplamanın sonucunu saklamamız gerekiyor ve bu işlemin en fazla iki saatte bir yapılması gerekiyor ve o verinin tamamını tüketirsek hafıza ve CPU limitlerini, hesaplama mantığını aştığını varsayalım. karmaşık ama gerekli ve optimize edilmiştir ve sahip olduğumuz kümelerin fiziksel sınırları nedeniyle kaynak sınırlarını artırmak bir seçenek değildir, ancak küçük CPU ve belleğe sahip 5 ayrı bölmeye sahip olabiliriz. Sonunda, iyi haber şu ki, sonuca hemen ihtiyacımız yok, eninde sonunda olabilir ve her hesaplama, önceki sonuçlara gerek kalmadan en son sonucu verir.

çözüm yolu

Tahmin edebileceğiniz gibi, bu sorun verileri bölerek ve gruplayarak çözülebilir; ama nasıl. Her demetin benzersiz tamsayı anahtarları sayesinde onu bir pivot olarak kullanabiliriz. Çoğumuz, belirli bir süre veya zaman diliminde kodların çalıştırılmasına yardımcı olan cron işlerini kullandık veya duyduk, kullanabiliriz. Geriye kalan tek şey, verileri daha küçük veri bölümlerine nasıl bölebileceğimizdir.

İlk Teklif

Verileri parçalara (daha küçük bölümlere) bölmek için böyle bir tasarım kullanabiliriz; zamanlanmış bir cron işi her başlatıldığında; bu tuşların son rakamının belirli bir rakam olduğu verileri tüketebiliriz. Bu belirli rakam için, mevcut dakikanın 10 modunu alabiliriz ve iş her 7 dakikada bir ateşlenir. Örneğin; Job 12:14'te çalıştırılırsa 4 ile biten anahtarın datası tüketilir ve her 7 dakikada bir diğerleri tüketilir.

sözde kod

@CronJob("every 7 minutes")
@CronLock("until execution done")
function processData() {
   try {
     const digitToBeProcessed = new Date().getMinutes() % 10;
     processDataWithLastDigit(digitToBeProcessed);
   }
   catch(e) {
     logger.error("there is an error while processing data with last keys:".digitToBeProcessed, e.stack);
   }
   releaseCronLock();
}

12:00, 12:07, 12:14, 12:21, 12:28, 12:35, 12:42, 12:49, 12:56, 13:03, 13:10, ...

0, 7, 4, 1, 8, 5, 2, 9, 6, 3, 0 ...

Birinci Teklifin Değerlendirilmesi

Koda ilk bakışta dakika modülasyonu konusunda kafamız karışabilir. Böyle bir bağımlılık, böylesine kontrolsüz ama çok önemli bir parametre nedeniyle, özellikle herhangi bir belgeleme veya yorum olmaksızın belirsizdir. Derinlere inerken, elbette, bu uygulamanın verileri bölmek için olduğunu anlayacağız; ancak daha önce yaptığım gibi atış dakikalarını yazmadan her rakamın isabet alacağına ikna olmak zor. Bundan sonra bazı sorular ortaya çıkacak; Parti 7 dakikayı aşarsa ne olur? Veri artışı ile yüksek ihtimal, bir sonraki haneyi atlayacaktır. Bu kaçırılan rakamın ne zaman vurulacağını görmek zor. Peki ya cron period 7 parametresini 9 dakika olarak değiştirmek başka bir şeyi etkileyebilir mi?

Özetlemek gerekirse, daha önce de belirttiğim gibi KISS'in temel faydalarına göre, daha iyi sürdürülebilirlik ve güvenilirliği kaçırabiliriz, Ayrıca anlaşılması zor ve bazı net olmayan sonuçları var.

Başka Bir Teklif

Tüketeceğimiz son hane parametresi üzerinde daha fazla kontrol kurabiliriz. Dağıtılmış bir önbelleğe bir karşı basamak koyarsak, her bölme bir sonraki basamağın tüketileceğini bilebilir. Bir bölmenin işi başladığında, o rakamı alır, 1 ile artırır (9'a ulaşırsa, sonra 0'a sıfırlar) ve ardından tuşların son rakamı bu sayaca eşit olan verileri tüketir.

sözde kod

@CronJob("every minute") 
  @CronLock("until execution done")
  function processData() {
      const digitToBeProcessed = distributedCacheClient.getDigitAndIncreaseIfExceed9SetAs0();
      try {
        processDataWithLastDigit(digitToBeProcessed);
      }
      catch(e){
          logger.error("there is an error while processing data with last keys:".digitToBeProcessed, e.stack);
      }
      releaseCronLock();
  }

{ "digit": 8 }

  • Her veri tüketileceğinden ve her bölme sıralı basamaklarla tam yük içinde çalışacağından, bölme verimliliğini artırabiliriz. Bir basamağın verileri diğer basamaklardan daha erken işlenirse bölme beklemez, yalnızca bir sonrakini alır.
  • Dakika modülasyonunun belirsizliğini göz ardı edebiliriz, işleme sayaç tarafından daha fazla kontrol edilecek ve her rakamın isabet alacağı kesindir.
  • Bir parçayı yeniden hesaplamak istiyorsak önbelleği o parçanın son rakamıyla güncellemek yeterlidir.
  • Veri anahtarlarının eşit dağılımı yine de dikkate alınacaktır ancak önemli olmayan bozulmalar yapılabilir. Bölme verimliliğindeki artış nedeniyle, bir basamaklı işlem daha uzun sürerse, diğer bölmeler diğer basamakları işleyebilir.

Teklif değerlendirmeleri ve sözde kodlar konusunda desteği için Tuğba Bakırdöken'e teşekkür ederiz .

Okuduğunuz için teşekkürler. Umarım zaman ayırdığınıza değmiştir.