Yazılımın ilk 250 günü - Part 11

13 dk okuma

101. Gün

Composition ve dependency kavramlarının ayrımını örneklendirmek istedim ve bir tane ürettim. İnsan, dağ, Dünya. İnsan ve dağı Dünya içerir. Burada bir sahiplik ve "part-whole" ilişkisi bulunur. Dünya varolmak için dağa ya da insana bağımlı değildir. Yani burada bir "dependency" dünya için yoktur. Burada en genel manada "association" bulunur. Association için ayırt edici bir örnek olarak Ay'ı verebiliriz. Dünya bulundurduğu okyanus nesnesinde gelgitleri sağlamak için Ay uydusunu kullanabilir. Burada sahiplikten öte "kullanmak" vurgulanır. Bu da bir accosication'dır. İnsan dünyanın bir parçasıdır fakat insan dünya nesnesi dışında da var olabilir (Uygun şartlar oluştuğunda farklı gezegenlerde, uydularda yaşamını sürdürebilir). Dağ ise dünya dışına çıkamaz. Dünya her ikisine sahip olsa da böyle bir fark bulunmaktadır Dünya-insan ve Dünya-dağ arasında. Dünya-insan ilişkisi üst kümesi asscociation olan bir aggregation ilişkisidir. Dünya-dağ ilişkisi ise üst kümesi association olan bir composition ilişkisidir. Bu düşünce sınırlarını genişletirsek örnek verimsiz olabileceği için bu dar çerçeveden bakarak konsepti kavrayabiliriz.

Inheritance ise anlaşılması daha basittir: İnsan, Dünya değildir. Onun özelliklerini almamalıdır (Hepimiz topraktan geldik, toprağa gideceğiz gibi düşüncelere girilmemeli tabii ki). İnsan bir primat, bir hayvan, bir canlı, somut bir varlıktır. Hepsinden insana ait ortak özellik ve yordamlar inherit edilebilir. Inheritance'ın sorunu çelik gibi olmasıdır. Kolay biçimde esnemez, döverek şekil vermek zordur. Bu yüzden GoF kitabında "prefer composition over inheritance" der. Her gördüğün yerde composition ilişkisi kur demek değildir bu. Composition'ı tercih et der çünkü dependency injection/setter kullanarak nesnenin davranışını değiştirmek daha kolaydır. Inheritance ta ise birden fazla tipten nesne türetmek mümkün değildir (En azından çoğu yazılım dilinde) ve coupled(bağlı)'dır. Bu yüzden interface ve abstract class kullanımı önem kazanır. Birbirinin tamamlayıcısı olan SOLID prensiplerine ise bu yazıda girersem konu daha da uzayacaktır. Inheritance çelik gibi demiştik, composition ise bakır gibidir. Dövüp işlemek, şekil vermek, modifiye etmek daha kolaydır. Inheritance'ı da bakır gibi kullanabilmek için SOLID prensiplerini elzem bir şekilde bilmek ve sınıfların tasarım aşamasında bu prensiplere dikkat etmek gereklidir. Kısaca SOLID'in OCP, Liskov, ISP prensiplerinde sağlanan polimorfizm bu esneklikte en önemli konudur.

En iyi öğrendiğim konular bu söylediklerimdi. Umarım yanlış öğrenmemişimdir. Tek bir cümle ile tüm yapıyı en iyi şekilde anlatmanın bu konuda olabileceğini henüz sanmıyorum.

Bugün yaptıklarımı düşündüm. Sitedeki nesneleri, ilişkilerini, yapılarını düşünmek en çok yaptığım şeydi. Bugün ürünler ve kategoriler üzerine çalışıp sınıf diyagramlarını çıkarırım diye düşünmüştüm. O kadar çok birbirine bağlı kısım vardı ki hangi birine odaklanmalıyım bazen şaşırdım ve bazı yerleri farklı bir senaryoyu düşünürken inceleyip burada kullanılan nesnelerle bağlayabilirim dedim. Inheritance bulunan yerlerde Liskov'u düşündüm mü örneğin? Hayır düşünmedim. Yaptığım şey yanlış, bunun farkındayım ve kendimi kınıyorum. Ama humiliation'dan zevk almadığım için bu kınamayı kısa sürdürüp "ona da odaklanacaksın" diyorum kendime.

2 ay sonrasında üretken olabilecek miyim? "Only God knows" demek en doğrusu olsa da yapabileceğimi düşünüyorum. 4 ayda katettiğimiz yola bakıyorum ve farklı insan hikayelerine de göz atıyorum bu konuya başlangıçta insanların gelişim süreçleri hakkında. 4 aylık süre içinde hangi konumdayım tam bilmesem de yeterince emek verdiğimi biliyorum. Ve sizin de oldukça fazla yardım ettiğinizi. 4 ayda neler olmadı ki. Rüyalarıma defalarca girdiğini hatırlıyorum kodlama, proje süreci, başaramamak, başarmak, her alarm sesi duyulunca rüyada "evet burayı tamamladım, şimdi şu kısmı tamamlayayım"lı yazılım süreci yönetimi gibi konuların. Sonunda da altın bileziği elime takmış olurum umarım.

102. Gün

Bugün de aynı konular üzerine devam ettim. Dün ürün ve kategori üzerine düşünüp bir şeyler yapmaya çalışmıştım ama tamamlanmamıştı. Bugün eksik olan bazı kısımlarına eklemeler yapıp sonrasında ürünü sepete ekleme, satın alma kısımlarına baktım. Henüz tamamlanmadı. Son 3 gündür beynimin içi öyle dolu ki, kış aylarında evin içinde çok yavaş hareket eden “soğukkanlı” bir böceğin durgunluğu beynimde yaşanan şeymiş gibi hissediyorum. Yine de bir şekilde ilerleme oluyor tabii ki. En azından systemin üzerine düşünüp daha yakından tanıyorum düşününce.

103. Gün

Gün boyu ödeme sistemi üzerinde durdum. Başlangıçta ödeme yöntemleri ile kurulan ilişkiyi düşündüm. Sonrasında Iyzico’dan alınan ve Iyzico’ya verilen parametreleri onların sitesinden okudum. Bu parametrelerin Gpay, Paytr, Papara’da da olduğunu varsaydım. Ya da en azından çok benzerlerinin olması gerektiğini düşündüm. Ödeme sistemini dizayn ederken birbiri ile çok ilişkili yapılar vardı. Arayüz-abstract class kullanımı zorunluydu. Ama nerelerde ne kadar sayıda ilişki olduğunu çözemiyordum. Sonrasında ödeme konusunda daha önce insanlar hangi tasarım desenlerini kullanmışlar ona baktım. Genelde factory method, strategy ve facade pattern’ler ile karşılaştım. Özellikle simple factory ve strategy pattern’in beraber kullanılması ile ilgili benzer birçok örnek vardı hem authentication hem de checkout konusunda. Sonrasında günün çoğunluğunu tekrar bu tasarım desenlerini anlamak, kendi sistemim üzerine nasıl oturtabileceğim üzerine teorik olarak tasarlamakla geçti. Strategy pattern’e bakakerken open-closed principle direkt gözüme çarpmıştı. Sanki tüm amacı onu sağlamakmış gibi geldi. Factory ile aslında çok farkını bulamadım. Her ne kadar stack overflow’da çokça farklarından bahsetmiş olsalar da ben henüz kavrayamadım. En net gördüğüm düşünce, ödeme metotların ortak bir yapısı olması gerektiğiydi ve hardcoded bir yapı ile hepsini kullanmak yerine OCP’ye uyarak, sisteme yeni bir ödeme metodu eklediğimizde ya da sildiğimizde sistemdeki eski kısımlarda güncelleme yapmamak gerektiği üzerineydi. Sadece bir simple factory tasarım deseni yeterli olur diye düşündüm ve bunu uygulamaya başladım. Henüz bitmedi. En son kanıya varma sebebim Factory-Strategy desenlerinin farkını anlayamadığım için olabilir. Yapı olarak çokça benzeseler de kullanılma sebepleri farklıymış anladığım kadarıyla. Tasarım desenleri karşıma problemler çıktıkça kullanabileceğim ve aklımda yer edecek konular sanırım. Onu da çözeceğim.

Neredeyse her yeni gün çok fazla şey yapmak istiyorum: algoritmalar kitabını tamamen her noktasına kadar anlamak, kendim örnekleri tekrarlamak, sonrasında kodlayıp mükemmel bir frontend ile kullanıcı etkileşimli algoritma kütüphanesi yaratmak, yapay zeka çalışmak (web alanında ne yapılabilir farklı olarak) ve kendimce ufak projeler çıkarmak, javascript’I hatim etmek (plain-normal-, node, hatta react öğrenmek). Genel olarak huzurluyum çünkü sevdiğim ve tatmin olduğum bir konu hepsi. Elbette bu uç örnekler işten öte hobi olarak sonra yapılabilecek şeyler. Fakat hobi olarak yapılabilecek şeyler olması işin en güzel yanı.

Enflasyondan etkilenmemek ya da para birimlerinin volatilitesinin olmadığı bir sistem üzerine hâlâ daha iyi bir araştırma yapamadım ve üstünde duramadım. Ama o da hep aklımın bir köşesinde.

104. Gün

SOLID'i tam olarak kullanmalıyım derken kullanıcı ile bilgileri içeren her kısmı farklı class'lar oluşturarak yapmıştım. User class'ından gereken kısımları çeker ve işlemleri o şekilde tamamlarım diye düşünmüştüm. Bunu da DI kullanarak yapabilirdim. Yanlış düşünmüşüm. SOLID'deki single responsibility'yi biraz daha büyük ölçekten sisteme bakarak düşünmem gerekiyormuş belki de. Kendime kırıldım. Fatih Terim'in takıma strateji verirken sürekli gazlama metodunu kullandığı gibi kendimi gazlamış olabilirim. Düşe kalka yürümeyi öğreneceğim. İlk yürümeyi öğrenen çocuğun ebeveyninden destek almadan bir şeyler yapma çabası gibi oldu sanki bu hafta. Kendi ayaklarım üzerinde durabilmek dileğiyle yakın zamanda (yazılım açısından).

105. Gün

Bugün ortaya karışık ilerledim. Daha önce üstüne okumalar yaptığım seo üzerine ilk defa somut olarak nasıl çalışıldığını gördüm. Daha doğrusu SEO'dan öte bugün Google Analytics ne işe yarar, kullanıcı istatistiklerinin neler olduğu (demografi verileri, ilgi alanları, oturum süreleri, etkinlikleri(örneğin satın alma), kullanılan tarayıcı bilgileri, erişim yapılan ülke bilgisi, siteye giren kullanıcının siteden hemen çıkma oranı, gibi), kullanıcı trafiği ile ilgili verileri, siteye erişimde kullanılan yolları (edinme diye geçiyordu: paid search örneğin), site reklamının hangi yollarla verildiğini ve analytics'de bu reklamlarla gelen kullanıcıların hangi türü reklamdan geldiğini görmek gibi konuları öğrendim. Etkinlik oluşturmadan bahsetmiştim. Daha çok retargeting ve remarketing'de işe yarayan, kullanıcı verisinin gerçek zamanlı incelenebildiği bir konseptmiş kendisi. Criteo kullanımını gördüm ayrıca. Google ads yerine kullanılabildiğini (mesela firefox'ta da reklam verilebiliyor) öğrendim.

Site haritasının önemini, dizine eklemenin (indeksleme) ne işe yaradığını anladım. Soft 404 hatasının ve noindex tag'inin kullanılmasının SEO'nun kabusu olduğunu öğrendim.

Bugün asıl öğrendiğim konu şu oldu: bir şeyi söyleyeceğim demişsem, not almışsam, onu unutmamalıyım. Böyle bir lüksüm yok. Bakınız: Fransızca.

Bir yerde hata olduğunda en basit raporlama şeklinin hata ve hatanın olduğu yeri başlık olarak belirttikten sonra açıklaması ve ekran görüntüsünün ilgili kişiye gönderilmesi olduğunu gördüm.

Sonrasında bol bol Google'ın kendi dokümanlarından SEO hakkında okumalar yaptım. Öncesinde de biraz daha sınıf diyagramlarına baktım. Eksikler bolca bulunsa da temel iskeletin bir parçası oluştu diye düşünüyorum ve kodlarken yapının sağlam temellere oturacağını düşünüyorum.

106. Gün

Bugün hem SEO kısmına hem de var olan görevimize devam ettim. SEO konusunda o kadar çok bilgi var ki yine de hazmederek öğrenmeye çalışıyorum. Başucu kaynağım google developers dokümanları. İki gündür iş bitiminde onlara bakıyorum. Bugün çalışmalarımızdan aklımda en çok kalan, siteye verilen linkler ve sitede var olan linkler üzerine çalışmalar oldu. Örneğin donanım haber footer'ına backlink vermenin sağladığı katkıyı gördüm. Donanım haber bu backlink'e sahipti ve nofollow tag'i bulunmuyordu örneğin. nofollow tag'i bulunmazsa site itibarının (reputation) google gözünde düşme ihtimali var. Spam bir lir siteye link gidebilir, trafik hacmimizi daraltabilir gibi zararlı yanları bulunmaktadır. Donanım haber neden nofollow tag'ı kullanmamış peki? Google'a bu linkin sponsorlu olduğunu söylüyor. Sponsorlu link olduğunu gören Google "aa tamam o zaman sorun yok" diyor. nofollow'a benzer olarak noreferar ve noopener tag'leri de bulunmakta. Özetle benim bunları sitemdeki linklerde kullanmam gerekiyor SEO için.

Bugün ayrıca Semrush, Ahrefs, Serp gibi gibi uygulama ve konulara baktım. Biraz aşina oldum. Semrush'ın sayfalar için öneri fikirlerini görünce biraz da algoritmasına hayran kaldım. Sayfalandırmalar (pagination) hakkında bir hata gösteriyordu ( hepsi aynı sayfa başlığını gösteriyordu ve sorun buradan kaynaklanıyordu). Akşam bunun üstüne biraz araştırma yaptım birkaç faydalı çözüm yöntemi farklı kaynaklarda sunulmuş: "Use Rel='next' and Rel='Prev' for Paginated Page Series", "Use the Canonical Tag Rel='Canonical'", "Remove Content from the Google Index", ve daha fazlası. Ama hangisi daha etkili olabilir onu henüz bilmiyorum.

SEO üzerine okuma yaparken Google'ın fotoğraflar için birkaç önerisine denk geldim şu an kullandığım/ız'dan farklı olarak: Örneğin <pictures> tag'i ile resimleri sunmanın responsive'lik açısından daha fayalı olduğunu belirtmiş. Bir de SVG formatlı fotoğrafları da oldukça fazla methetmiş diğer raster graphic'li formatalara (jpg, png gibi). Anladığım kadarıyla SVG formatlı resimler daha az boyuta sahip olduğu için HTTP request'lerini azaltmak için faydalıymış. Data URI'ı da oldukça övmüş fakat dezavantajlarının çokluğunu görünce onu çok araştırmadım. Ek olarak, örneğin <img srcset> tag'i ile resim eklenmek istenirse bunun her tarayıcıda algılanamayabileceğini belirtip "img src" olarak da yedek bir url vermeyi tavsiye etmiş. Bana çok saçma geldi. Her tarayıcı desteklemiyorsa ve tavsiye edilen kullanım yönteminin büyük artıları yoksa neden tercih etmeliyim? Bence tercih etmemeliyim.

107. Gün

Öncelikle veritabanı ile ilgili işlerin ardından kullanacağım sorgular için hem bir veritabanı bağlantısı hem de sorgular için genel bir çalışma yapmam gerektiğini anladım.

Planım şuydu: Önce bir singleton class oluşturacaktım veritabanı bağlantısı için. Ama bu bağlantı sadece mysql'e değil, aynı zamanda PostgreSQL'e de yapılabilecek şekilde flex bir yapıda olmalıydı. Bunun için singleton sınıfımdaki contructor'in içinde bir yapı kurdum. Mysql server'a mysqli ve pdo ile bağlanma seçeneği ve bir de PostgreSQL server bağlantısını ortak bir yapı ile kurmaya çalıştım. Bağlantılar ile ilgili logic'i ortak arayüze sınıflara aktardım. Veritabanı bağlantısının amacı ona bilgiler vermek ve bilgiler almak olduğu için bu iletişim içeriğini ve methodlarını içeren bir Query sınıfı oluşturdum. En son hâlinde _<<$query = new Query($mysqli); $query->insert(["table" => "Directors", "keys" => ["Name", "Surname", "Age"], "values" => ["Stanley", "Kubrick", "66"]]);>>_ diyerek sistemdeki herhangi bir yerde bu tür sorguları basit şekilde yapabilecek. Eğer başarabilirsem.

Şu aşamada yazmaya öyle odaklandım ki, henüz gerçek veritabanı bağlantısı kurmadım ve kodda ne kadar hata var henüz bilmiyorum. Mantığını doğru kurabilirsem yarın o hataları da düzeltebileceğime inanıyorum.

Hem mysqli hem de pdo için ortak bir yapı kurmaya çalışıyorum özetle. Biraz gereksiz zahmet gibi görünebilir. Hatalarda fazla zamanımı alacak olursa future development olarak bir tanesi sonraya bırakılabilir.

Bugün özellikle prepared statement'ı mysqli bağlantısı ile oluştururken zorlandım ve büyük ihtimal zor çözeceğim. Çünkü query builder çalışırken de en büyük sorunu hep orada yaşıyordum.

108. Gün

Veritabanı sorgu sınıfı için gerekli metotları bugün tamamlamam gerekiyordu. Dün insert kısmını, bugün de kalan kısmı bitirilip kullanabilecek formatlara uygun yeterli seviyede sorgular yapabilmeme izin vermeliydi.

İki gün içinde yapılanlar ve yarın yapılması beklenen şu şekilde özetlenebilir:
  1. Singleton bir veritabanı bağlantısının oluşturulacağı ve bu bağlantıyı elde edeceğim bir sınıf oluşturuldu.
  2. Bu sınıf bağlantıyı oluştururken bağlantı metoduna göre farklı sınıfları çağırabilirdi (başta composition olarak düşünmüştüm aradaki bağlantıyı fakat, ikinci oluşturulan sınıf(örneğin MYSQLI sınıfı) Query sınıfı için de kullanılıyordu. Bu yüzden farklı iki sınıfın kullanıldığı tek bir sınıf olduğu için aradaki ilişki aggregation yani pass by reference'tı.
  3. MYSQL ya da POSTGRESQL sınıfı ortak bir yüze sahip olması gerekir. Gelecek kullanımlarda client'a kolaylık sağlar.
  4. Normalde hem mysqli hem de pdo için CRUD metotlarını yazacaktım fakat prepared statement'lar biraz fazla zamanımı aldığı için sadece PDO bu örnekte tercih edildi.
  5. Şu an sorgular sınırlı koşullar altında çalışmaktadır. Bu koşulların bu proje için şu aşamada yeterli olduğunu düşünülüyor.
  6. Sorun özellikle şurada olabilir: Örneğin "WithMySQL" sınıfında hem mysql yöntemleriyle bağlantı veritabanı oluşturuluyor hem de crud işlemleri sağlanıyor. Farklı sınıflara ayırma imkanı vardı. Hatta daha şık olurdu. Bu durumun bilincinde olarak yazıldı.
  7. Yarın büyük ihtimalle daha önce tasarlayıp kullanıcıdan veri alışverişinde bulunduğumuz eski bir projenin frontend'inden yararlanıp kullanıcı kaydı ve giriş aşamaları bu dizayn ile sağlanabilir. Ya da sadece PHP kısmına devam edilebilir.

109. Gün

Bugünün sorunu şuydu: Nedeni olduğum hataların bazılarını hata beklentisi olmadan yapıyorum. Bazı hataları ise bilerek oluşturuyorum, ya da sistem doğru çalıştığı için o hata geliyor. Bazı yerlerde hatayı isteyip istemediğimi çözemediğim oldu. Günün en büyük problemi hatalarla mücadeleydi.

Bugün yapılan: Veritabanı ve sorgu sınıfları kullanıcıyı kaydetmek, aktivasyon linki göndermek, dönen linke göre kullanıcıyı aktif edip kullanılan aktivasyon kodunu "kullanılmış olarak" etiketlemek için oluşturulan kayıt olma ile ilgili sınıflarda kullanıldı.

Bir konu var aklıma takılan: uzun süre kullanılmamış aktivasyon linklerini geçersiz kılmak (kod state'ini değiştirerek örneğin) için ne yapılabilir? Mysql'de bir olay (event) yaratıp, gerekli sql sorgusunu oluşturdum fakat veritabanında böyle bir işlem için yetkim olmadığını gördüm. Bu problemi henüz düzeltemedim. Ayrıca locale'den email gönderemeyeceğimi düşünerek (onun da bir yolu vardır tabii ki), o kısmın gerçekleştirildiğini varsayarak işlemler yaptım. Açıkçası kayıt aşaması tamamlandı gibi görünüyor sunucu taraflı olarak. Yarın giriş kısmını tamamlayacağım. Sonrasında kayıt ve girişin prototip üretimini (frontend ile) tamamlayıp diğer aşamalara geçeceğim.

110. Gün

110 gün içindeki en verimsiz gündü öğle yemeği saatine kadar. Mide problemi odaklanmayı kötü etkiledi. Bugün çok bir şey yapamadım o yüzden. Dün yapılan çalışmadaki son fatal error'u çözdüm. Sonrasında kayıt işlemini kullanıcı facebook ve twitch ile de gerçekleştirebildiği için örnek olarak bir fonksiyon ile api ye sağlanan ve alınan parametreleri input/output olarak ekleyeceğim. Bu kısmı da tamamlayınca kayıt bitmiş oluyor.