Uçtan Uca Mobil Uygulama Geliştirmek - Bölüm 1: Backend Side
Merhabalar, bu Ramazan Bayram’ının tatilini değerlendirip WaaperHD adında bir proje geliştirdim. Projenin asıl amacı şirket içinde oluşturduğumuz Android modülleri test etmekti. Bunun için bir proje fikrine ihtiyacım vardı. Aklıma bir Wallpaper uygulaması yapmak geldi. Bunu en başta bir mobil uygulama şeklinde yapmayı düşündüm ama veriyi aldığım servisin ücretsiz versiyonunda request kısıtlaması olduğu için aklıma backendini yazıp belli saatlerde ücretsiz hizmet aldığım servisten veri alıp aldığım veriyi database kaydederek mobil uygulamaya ise databaseye yazdığım veriyi manipüle ederek göndermek geldi. Evet proje en başta bu amaç ile geliştirildi ve uygulamadan pasif bir gelir elde etmek istedim ama proje geliştirme sürecinde proje amaçtan çok hobiye döndü ve üstünde baştan sona performans almak için neler yapabileceğime dair çalışmalar gerçekleştirdim. Bu yazımda bu çalışmalar sonucunda ortaya çıktı. Bu yazı serimde basit bir projenin mobil tarafını ve backend tarafını birbirinden ayırmaksızın bir projeyi nasıl geliştiririz, geliştirdiğimiz projeden nasıl performans alabiliriz konuları temamız olacak.
Not: Projeniz büyüdüğünde çok daha farklı konular işin içine giriyor. Aşağıdaki önerileri basit öneriler olarak düşünebilirsiniz.
Yazımız iki bölümden oluşacak;
Backend Side: Bu bölüm backend’te yaptığım tercihleri neden yaptığımı ve performans almak için neleri hangi amaç ile kullandığımı anlatacağım bölüm olacak.
Client Side: Bu bölüm asıl uzmanlık alanım olan mobil tarafta gelen veriyi nasıl yönettiğimi ve uygulamayı geliştirirken nasıl bir yapıda geliştirdiğimi anlattığım bölüm olacak.
Proje Nedir?
Proje, kullanıcının mobil uygulamada gördüğü bir wallpaperı telefonda arka planı yapmasını sağlıyor. İster ise background aramasıda yapabiliyor.
Backend Side
Aslında geniş çaplı bir proje geliştirecekseniz projenizin esnek, ilgili servislerin yapabildiklerine göre oluşturacağınız servise en uygun teknolojileri seçmeniz daha iyi olacaktır. Son dönemde oldukça popüler olan Microservis mimarisini önereceğim bunun için. Örneğin bir proje geliştiriyorsunuz ve bir serviste makine öğrenmesi kullanacaksınız bunun için gibip Java kullanmazsınız Python kullanırsınız. İşte microservis mimarisi size böyle kolaylıklar sağlar ama dezavantajlarıda vardır.
Daha önce Spring kullanarak geliştirdiğim bir projenin linkini kaynak olması için burada paylaşıyorum;
Böyle bir mimaride loglama oldukça önemli. Çünkü çok fazla servis var hangi verinin nereden geldiğini anlamak oldukça önemli. Bunun için ise şu yazımı şuraya bırakıyorum;
Ciddi anlamda iyi bir proje yapmak istiyorsanız size vereceğim tavsiyelerden birisi ise şu olacak; Docker
Docker kullandıktan sonra derdiniz bitmiyor birde bunu daha sağlıklı yönetmek ve scale edebilmek için Docker Swarm, Kubernetes vb. teknolojileri kullanmanız gerekmekte. Yukarıda paylaştığım Github linkinde Docker Swarm kullanımıda mevcut.
Bunları yaptınız derdiniz bitti mi? Tabi ki hayır…. Birde CI/CD süreçleri mevcut. Projeyi geliştirdiğinizde elinizde minimum 10 tane proje olacak bunları teker teker elinizde deploy edemesiniz. Bunun için ise Jenkins kullanmanız gerekecek. Daha farklı servisler var ama ücretsiz ve popüler olduğu için Jenkins kullanabilirsiniz. Ve yaşadığınız bir sorunun cevabını daha hızlı bulabilirsiniz.
Yukarıdaki teknolojilerin hepsi başlı başına birer konu ama benimkisi gibi basit bir proje yapacaksanız yukarıdaki teknolojileri kullanmanız bir hata olacaktır. Çünkü projeniz 3 veya 4 servisten oluşuyor olacak. Bunun için yukarıdaki teknolojileri kullanmak delilik olurdu.
Madem kullanmayacaktın neden bize söylüyorsun?
Bu yazıdaki amaçlarımdan biriside bakın bunlarda var araştırın demek.
Projemizin backendi Spring Boot ile yazıldı.
Peki neden Spring Boot?
Node.js’te bir seçenekti benim için ama gerek JPA gerekse Swagger’ı otomatik generate etmesi ve Kotlin desteği beni Spring Boot’a itti.
Database Seçimi
MongoDB. Çünkü okuma hızı NoSQL yapısından dolayı oldukça iyi. Bir abimizden şöyle birşey duymuştum “Serkan 13 milyon veriyi 3 saniye içinde listeledi”. Hiç o kadar verim olmadı ama bunu söyleyen abimize oldukça güveniyorum.
1.DTO
Evet arkadaşlar performans için DTO oldukça önemli bir konudur. Yav sadece veri neresi önemli olabilir ki?
Şöyle düşünelim mobil uygulamanın arayüzündeki veriyi göstermek için ne kadar veriye ihtiyacımız var? Örneğin şu aşağıdaki arayüz
Yukarıdaki ekranda sadece görseller var. Peki burada DAO yani DB’de kullandığın objeyi kullanmanın mantalitesi nedir ki?
Ben eğer DAO yu clienta dönseydim sırf bir sayfada 9 tane resim göstermek için şöyle bir veri dönmeliydim (Veriler örnek olması için sallanmıştır :) )
Evet sadece 9 tane resim göstereceğiz. Sizcede saçma değil mi? Benim sadece bir görsel linkine ve görselin uniq id sine ihtiyacım var. Listelemede yukarıdaki veri yerine 9 tane resim için şöyle bir DTO kullandım;
Aradaki veri farkına bakar mısınız? 82 satır nerede 36 satır nerede. Tabi ki 2. paylaştığım response ilkine göre daha hızlı geliyor olacak.
2. Pagination
Bunu konuşuyor olmamıza bile gerek yok. Bir responsede 100 tane veri geleceğine 10 tane veri geliyor hem client yorulmuyor hemde sunucu.
3. HTTP Cache
Evet arkadaşlar HTTP Cache diye bir konu mevcut. Bunun ne işe yaradığından bahsetmeyeceğim ama öğrenebileceğiniz yazıları paylaşayım
4. In Memory Cache
Aklınıza şöyle bir soru gelmiyor mu? Sürekli değişmeyen veya bazı kurallara bağlı olarak değişen bir veriyi neden sürekli DB’den alıp clienta gönderiyoruz ki. Evet arkadaşlar DB’den veri almak oldukça maliyetli bir olay. Backend uygulamanızdan DB’ye bir port açılıyor o veriler byte byte geliyor ooooo. O veri geleceğine ben onu memoryde tutsam DB’ye gitmek yerine memorydeki veriyi göndersem clienta nasıl olur? Örneğin anasayfanın listelenmesi için kullandığım veriyi clienta döndükten sonra memoryde tutuyorum taa ki DB’ye yeni bir veri gelene kadar. Spring bunu destekliyor arkadaşlar. Ve oldukça basit bir kullanımı var bunun dışında In memory cachede farklı çözümler mevcut bkz: Redis
5. API Design
Bu bir performans konusu değil ama önemli bir konu benim için. Arkadaşlar kafanıza göre API’de endpoint oluşturamazsınız bunun bir adabı var
Yukarıdaki geliştirmeleri yaptıktan sonra ücretsiz bir sunucu kullanmama ücretsiz bir DB kullanmama rağmen clienta veriyi 4 m/s de dönebildim. Kanıtlarım var
Yukarıda Heroku’nun loglarını görüyorsunuz. İlk servisi çağırdığım zaman response hızı 36 m/s den ikinci çağırmamda response 4 m/s ye düştü.
Projenin servislerinin linkini buraya bırakıyorum ama kaynak kodlarını bırakamıyorum çünkü özel keyler mevcut içinde
Burada doğru kod yazmaktan bahsetmek istemedim. O tarafa Bölüm 2 de girmek istedim.
Bu yazımız bu kadar. İkinci yazı da görüşmek üzere