Linkwind SAAS projesinde hangi teknolojileri kullandık ve neler öğrendik

Geliştirdiğimiz Linkwind projesinin duyurusunu buradaki yazı ile yapmıştım. Bilmeyenler için fazla vaktinizi almadan projenin ne olduğunu birkaç cümle ile açıklamak istiyorum.

Linkwind projesi tek satır kod dahi yazmadan kendi HackewNews benzeri link paylaşım ve tartışma platformunuzu kurmanızı sağlayan bir SAAS(Software as a service) platformu. Linkwind websitesine girip hesabınızı oluşturuyorsunuz ve platformunuz saniyeler içerisinde kullanıma hazır hale geliyor. Detaylı bilgi için Linkwind websitesini ziyaret edebilir veya buradaki yazıyı okuyabilirsiniz.

Bu yazıda da projeyi geliştirirken hangi teknolojileri kullandığımızı, front-end ve back-end tarafını hangi diller ile kodlağımızı ve uygulamayı hangi platformda nasıl host ettiğimizden bahsedeceğim. Geliştirilen bir projede hangi teknolojilerin ne amaçla ve hangi spesifik probleme çözüm olarak kullanıldığı gibi tecrübelerin çok yararlı olduğunu düşünüyorum. Sektöre yeni başlayan yazılımcı arkadaşlar geliştirecekleri projeler için bu teknolojilerden yararlanabilir veya tecrübeli yazılımcı arkadaşlarımız da listede daha önce duymadıkları bir teknoloji varsa bunlar hakkında bilgi edinebilirler.

Linkwind projesinin geliştiricileri olarak bu projede, daha önce kullanmadığımız yeni teknolojileri kullanmak istedik. Yani bir çoğu bizim için yeni teknolojiler. Belki size tanıdık gelebilir ve projelerinizde aktif olarak zaten kullanıyorsunuzdur ama biz bu teknolojilerin bazılarını ilk defa bu projede deneyimledik.  Bu yüzden yan projelerin bu amaç doğrultusunda bile yazılımcılara çok değerli tecrübeler kattığına inanıyorum. Kullanılan teknolojilerle ilgili ilk izlenimlerimizi de fazla detaya girmeden aktarmaya çalışacağım.

Detaylara geçmeden önce kullandığımız teknolojilerin listesine bir göz atalım:

Golang

Projeyi tamamen Go programlama dili ile geliştirdik. Back-end tarafında http isteklerini karşılamak için herhangi bir third-party web framework kullanmadık. Go dili ile çok tecrübemiz olmadığı için direkt olarak bir web framework kullanmaktansa Go'nun kendi http paketinin işleyişinin nasıl olduğunu anlamak istedik. Bu sayede varsa Go'nun kendi http paketinin artılarını eksilerini görüp oradaki acıyı deneyimleyerek, geliştirilen third party web frameworklerinin hangi problemleri çözdüğünü daha iyi anlayabiliriz diye düşündük. Böylelikle sonraki projelerde kullanıma değer olup olmadıklarını daha kolay anlayabilirdik.

Front-end tarafında da tüm altyapıyı Go'nun template mekanizması üzerine oturttuk. Go'nun template paketi bir çok temel ihtiyacı karşılıyor. Fakat tüm html sayfalarınızı base bir layout template'i üzerinden sunmak istediğinizde sistem biraz karmaşık gelebilir ama gözünüzü korkutmasın. İşin içine girince alışıyorsunuz:)

Başlarda template dilinde ihtiyacımız olan kodları bulmakta zorlandık açıkçası. Go'nun kendi dokümantasyonunda sadece bazı temel template kodları paylaşılmış fakat hepsinin açıklamarıyla olduğu bir dokümantasyon yoktu veya biz bulamadık. Ama internette biraz araştırma yaptıktan sonra hepsi kolayca bulunabiliyor.

PostgreSQL

Veritabanı olarak tercihimizi PostgreSQL'den yana kullandık. PostgreSQL bana göre marketteki en iyi veritabanı çözümlerinden bir tanesi. Relational bir veritabanının sağladıkları yanında NoSQL veritabanlarının sağladığı bir çok kolaylığı da sağlıyor. Bunun yanında performansının MySQL ve MSSQL'e göre kat ve kat daha iyi olduğunu gözlemledik.

Go ile postgresql tarafına bağlanırken bir ORM paketi kullanmadık. Go'nun kendi database/sql paketinin üzerine github.com/lib/pq adresindeki PostgreSQL driverini kullandık. Aslında ORM kullanmamamızın amacı yine Go'nun kendi paketini deneyimleyip altyapıyıdaki zorlukları görebilmekti. Edindiğimiz tecrübeye göre ORM paketlerinden birini kullanmak data katmanındaki kod karmaşıklığını azaltıp, tekrar eden bağlantı ve raw SQL kodlarını azaltacaktır. Bu sayede daha temiz bir kod yapısı elde edip ve kod yönetiminizi daha esnek bir hale getirebilirsiniz.

Bulma CSS Framework

Bulma'yı Linkwind.co websitesini tasarlamak için kullandık. Bootstrap'ı daha önce zaten bir çok projede kullanmıştık ve o yüzden bu projede yeni bir front-end framework'u deneyimlemek istedik. Bulma'nın kullanımı bize çok daha kolay geldi. Grid sistemi Bootstrap'e göre çok daha basit ve anlaşılır.

Framework ayrıca tamamen customize edilebilir bir yapı sunuyor. CSS tarafındaki herşey değişkenlerle yönetilebildiği için renkler vs herşey özelleştirilebiliyor. Ayrıca kullanmak istemediğiniz UI elementlerini CSS'ten çıkararak CSS boyutlarında da büyük bir tasarruf sağlayabiliyorsunuz.

Tailwind CSS Framework

Tailwind'i duymayanınız yoktur heralde. Biz de o kadar çok duyduk ki hazır yeni bir projeye başlıyoruz deyip kullanmak istedik. Tailwind Bootstrap ve Bulma gibi frameworklere göre daha farklı bir css framework'u sunuyor. Şöyle düşünün, bir projede ihtiyacınız olan tüm css yardımcı classlar önceden tanımlanmış ve kullanımınıza hazır hale getirilmiş. Örneğin margın-left: 5px gibi bir css kodu için ml-5 diye bir class varsayılan olarak tanımlı geliyor. Sizin tek yapmanız gereken bu yardımcı css classlarını kullanarak UI'nızı geliştirmek.

Bizim Tailwind'ı kullanma motivasyonlarımızdan ilki bu yeni framework'u deneyimlemek istemekti. İkincisi ise önceki projelerimizde biz de bir çok yardımcı class oluşturup kullandığımız için bize daha yakın bir framework olduğunu düşündük. Tailwind'i Linkwind websitesinin haricinde SAAS tarafındaki web uygulamasında kullandık. Golang ile yazılan back-end'in servis ettiği ve Go'nun tempalate engine'i üzerinde oturtulan UI'da css dokunuşlarının hepsini Tailwind ile yaptık. İtiraf etmeliyim ki responsive sayfa mekanizmasına bir türlü alışamadım. Nedense kavramakta güçlük çektim. Ama ben daha çok back-end tarafına yakın olduğum için bu durum bana özel olabilir.

Takip edip işlerine saygı duyduğum, alanında uzman bir çok Front-end geliştiricisine göre Tailwind'in yapmak istediği inline-style css kodu yazmaktan öteye geçemiyor. Bence belli bir oranda da bu konuda haklılar. Sürekli css yardımcı classlarını kullanmanın inline-style css kullanmaktan pek farkı kalmıyor. O yüzden front-end uzmanlarına kulak verin derim.

PgAdmin

Pgadmin'i PostgreSQL üzerinde yarattığımız linkwind veritabanı işlemlerini yönetmek için kullandık. Tablo oluşturma, index oluşturma gibi işlemleri bir arayüz aracılığıyla yapmak istediğimiz için PgAdmin'nin sağladığı kolaylıklardan faydalandık. Hem localimizde hemde server tarafında PgAdmin'i sıklıkla kullandık.

Golang fresh

Fresh; Go ile yazılmış web uygulamanızda, herhangi bir go veya template dosyası üzerinde değişiklik yaptığınızda, bu değişiklikleri algılayıp uygulamanızı otomatik olarak derleyip restart ediyor. Bu sayede yaptığınız her değişiklikte tekrar tekrar go uygulamanızı build edip run etmek zorunda kalmıyorsunuz.

Go ile proje kodlamaya başladığımda sürekli yaptığım bu build işlemleri beni çok rahatsız etmişti ve bunu otomasyona bağlamak için biraz araştırma yapmıştım. Github üzerinde bu işi yapan bir çok proje bulabilirsiniz ama fresh bizim işimizi gördü. Belki Go programlamada bizden daha tecrübeli olan arkadaşların daha iyi bir çözümü vardır. Varsa yorumlara yazarsanız sevinirim.

Fresh ile Go uygulamanızı restart etmeyi tetikleyecek dosya formatlarını belirleyebiliyorsunuz. Böylelikle belirlediğiniz dosya formatları üzerinde bir değişiklik olduğu anda Go uygulamanız otomatik olarak yeniden başlatılıyor ve değişikliklerinizi görebiliyorsunuz.

StimulusJS

SAAS uygulamasında upvote/downvote ve comment/reply kısımlarında daha iyi bir kullanıcı deneyimi sunmak için back-end tarafında gidecek istekleri javascript ile gerçekleştirmek istedik. Bu yüzden vanillajs'in sunduklarından daha iyi olan, daha organize bir kod yapısına sahip bir kaç javascript çözümü aradık. Jquery kullanmak istemedik çünkü jquery bana göre çok esnek bir kütüphane olmasına rağmen daha structured bir kod sağlamada yetersiz kalıyor. İpin ucunu kaçırıp kod karmaşıklığını arttırma ihtimaliniz çok yüksek.

React veya Vue gibi daha geniş kapsamlı bir framework de kullanmak istemedik. Çözmeye çalıştığımız çok basit bir problem olduğu için gereksiz yere bu kadar kapsamlı frameworkler kullanmak anlamsız olurdu. Bu yüzden Jquery ve React/Vue framewroklerinin arasında kalan mütevazı bir kütüphane bulduk.

SimulusJS Basecamp şirketinin kendi içerisinde kullanıp herkese açık hale gitirdiği bir javascript kütüphanesi. Javascript kodlarınızı bir controller mantığı ile tasarlıyorsunuz. Bu sayede seperation of concerns prensibini ihlal etmeden, daha temiz ve organize olmuş bir kodunuz oluyor. Şunu söylemekte fayda var. Stimulus front-end tarafındaki tüm problemlerinizi çözen bir js kütüphanesi değil. Serverside rendering gibi özellikler de sunmuyor. İhtiyaçlarınıza göre daha kapsamlı bir framework tercih edebilirsiniz.

Sentry

Tüm hataları loglalayıp bugları yönetmek için Sentry'i kullanıyoruz. Bilmeyenler için neden Sentry'i tercih ettiğimizi söyleyelim. Sentry hataları yönetmek için tek bir merkezi dashboard sunuyor. Takımdaki geliştiriciler farklı hesaplar üzerinden bu dashboarda erişebiliyorlar. Bugları ilgili yazılımcılara atayabiliyorsunuz.

En sevdiğim özelliklerinden bir tanesi de, tekrar tekrar gelen hataları tek bir hata logunun altında toplayıp, bu hatanın toplamda kaç defa geldiği ve kaç farklı kullanıcıdan geldiği gibi bilgileri size sunabiliyor olması. Golang tarafında da sentry implementasyonu çok basit. Bir Sentry hesabı oluşturduktan sonra buradaki dökümantasyona göre Go entegrasyonunu basitçe yapabilirsiniz.

Deployment

Deployment ile ilgili kullandığımız tüm teknolojilerden bu başlık altında bahsedeceğim. Linkwind.co ve SAAS web uygulamasını DigitalOcean'daki $5'lik bir linux droplet üzerinde host ediyoruz.

Uygulamayı linux sunucusuna deploy etmek için Docker kullanıyoruz. Websitesi, SAAS uygulaması, veritabanı ve Pgadmin için birer docker image yaratıp deploy işlemlerini docker imajlar üzerinden yapıyoruz. Başta docker compose ile uygulamaları tek bir compose dosyası ile orkestre etmek istedik ama nginx tarafında custom işlemlerimiz olduğu için ve bu işleri docker compose tarafında bir türlü beceremedik. Bu yüzden her bir imajı server tarafında ayrı ayrı run ederek deploy etmeye karar verdik.

İmajlar için DockerHub kullanıyoruz.

Linux terminal tarafında fazla uzman olmadığımızdan dolayı, server tarafındaki docker containerları yönetmeyi bir UI üzerinden nasıl yapabiliriz diye arayışa girdik. Biraz araştırmadan sonra karşımıza Portainer diye bir servis çıktı. Containerlarınızın çalıştığı sunucuya portainer imajını kurup bir port üzerinden erişime açmanız Portainer'i ayağa kaldırmak için yeterli oluyor. Ardından bir admin hesabı oluşturduktan sonra tüm containerlarınızın yönetimini Portainer üzerinden yapabiliyorsunuz.

Linkwind websitesini dış dünyaya Nginx üzerinden açıyoruz. Diğer docker containerları localde çalışarak belirli portlar üzerinden dışarıya açılıyorlar. Nginx reverse proxy görevi görerek dışarıdan gelen http isteklerini containerlara iletiyor.

SSL sertifika oluşturma ve yenileme işlemlerini Let's Encrypt ile yönetiyoruz.

Daha önce söylediğim gibi kendi link paylaşım ve tartışma platformunuzu kurmanız için Linkwind üzerinde hesap oluşturduğunuzda size platform-isminiz.linkwind.co isminde bir subdomain tahsis ediliyor. Bütün sub domainler varsayılan olarak https desteği ile geliyor. Bunun teknik detayını buradaki yazıda anlatmıştım. Bu sistemde arka planda Let's Encrypt kullanıyoruz.

Platformunuz için kendi custom domaininizi kullanmak isterseniz bu da mümkün. Bunun için OpenResty, Lua ve Lua-resty-auto-ssl servislerinden yararlanıyoruz. Kullanıcılara custom domain kullanma desteğini nasıl verdiğimizi detaylı bir yazıda burada anlatmıştım. Dilerseniz makalemizi okuyarak bu konudaki teknik bilgiyi de edinebilirsiniz.

Sanırım hepsi bu kadar. Linkwind projesini geliştirirken kullandığımız teknolojiler bunlardı. Projeyi geliştirme yolculuğunda bilmediğimiz bir çok yeni şey öğrenip, bir çok yeni teknolojiyle tanışma fırsatımız oldu. Bir yan proje yapmak için motivasyon bulamıyorsanız, yeni teknolojiler öğrenme motivasyonu bile tek başına yeterli. Biz projeyi geliştirirken çok eğlendik. Artık önümüzdeki maçlara bakma zamanı.

Sağlıcakla kalın.