Server Side Bir Projede Olmazsa Olmazlar || Olursa Güzel Olurlar

Server-side geliştirme yaparken projemizde olursa olmazsa olmaz OR güzel olur diyebileceğimiz bazı modüller&özellikler vardır ve bu özellikler bir çok kitap yazarı, ünlü blogger veya eğitmenler tarafından kabul görmüş özelliklerdir. Yazının başlığına bakacak olursak "Olmazsa Olmazlar" şeklinde ancak yazılım denen şey tabi ki "it depends on the business" duruma göre,ihtiyaca göre geliştirilen bir şey ve "Olmazsa Olmaz" dan kasıt bu zamana kadar hem kendi okuduğum çeşitli makalelerde vurgulanan hemde geliştirmiş olduğum çeşitli projelerde deneyimlediklerimden yola çıkarak 5 farklı önemli özellik var ki bu özellikler gerçekten kurumsal veya büyük çaplı bir projede farkında olarak veya olmadan size oldukça fazla fayda sağlamaktadır.

Bu 5 başlığı sırasıyla yazacak olursak;

  1. Security,
  2. Exception Handling,
  3. Logging,
  4. Response Consistency,
  5. Development Environment

 

1- Security

Bazı bilgiler vardır uygulamanız için veya uygulamayı kullanan kişiler için çok ama çok önemlidir. Örneğin; tckn bilgisi, banka hesap numarası, userId bilgisi, username-password bilgisi vs. bu gibi bilgilere hiç kimsenin ulaşmasını istemeyiz. Günümüzde fiddler, wireshark vb. tool'ları kullanarak client-server arasındaki gidip gelen http paketleri rahatlıkla dinlenmekte ve kötü niyetli bazı kişiler araya girerek giden data'da bulunan tckn,accounNumber,amount vs gibi alanları değiştirip bir çeşit dolandırıcılık yapabilmekteler. Genel de çözüm olarak "ya https yaparız abi hiç bişey olmaz.." şeklinde cümleler kurulup service'i https olarak dışarıya açarlar ve bu tehlikeyi önlediklerini sanarlar ancak artık https bile çeşitli yollar denenerek decrypte edilebilmekte.

Security'den kasıt aslında token based authentication vs. değilde request&response gelip giderken data için uygulanabilecek security. Tabiki de service'e gelecek olan client'ları belli authentication ve authorization kontrollerinden geçirdikten sonra içeriye almak gibi bir çok yöntem mevcut ancak data-trasnfer sırasında belli bazı önlemler alarak projenizin güvenliğini biraz daha atırabilirsiniz. Bunun için çeşitli yöntemler bulunmakta. Property bazında istenilen değeri şifleme veya maskeleme. Örneğin; UserLoginRequest adında bir modeliniz var ve içerisinde bulunan UserName, Password string alanlarını şifreleyebilirsiniz. Diğer bir yöntem ise endpoint'e gelen request ve endpoint'ten çıkan response modellerinizin tamamını şifreleyerek data transferini sağlayabilirsiniz ki bu daha base-oriented bir çözüm gibi duruyor. Örnek bir response örneği aşağıdaki gibi olabilir.

public class BaseResponse
{
	public object Data {get;set;} // şifrelenmiş bir şekilde endpoint'in return ettiği response Data içerisinde gönderilebilir
	public bool IsCrypted {get;set;} her endpoint şifrelenmiş şekilde response dönmeyebilir, client'ı bilgilendirmek adına bir bool alan tutabilirsiniz
}

Not: Checksum'da unutulmaması gereken diğer bir yöntemdir. Checksum kullanarak gelip giden data uzunluğu belli bir algoritma ile şifrelenip çift taraflı kontrol uygulanarak da güvenlik sağlamak işinizi baya bi kolaylaştırabilir.

 

2- Exception Handling

"Hatasız kod olmaz.."

Exception handling her bir proje için oldukça önemli bir konudur. Hatasız kul olmayacağı gibi hatasız kod da olmaz. Exception fırlatabileceğiniz düşündüğümüz yerleri zaten önceden tedbirini alıp handle ediyoruzdur ama asıl önemli olan beklenmedik hataları nasıl handle edeceğimizdir. En yaygın hatalardan biri olan null reference exception hemen hemen bütün projelerde başımıza gelmiş bir exception türüdür ve projeniz bu hatayı fırlattığında client'a http500 internal server error dönecektir. Peki bu tür hataları handle etmek için ne yapmak gerekir ?? Bir çok projede olduğu gibi her yere try catch koyarak kodunuzu spaghetti code haline getirip yönetilmesi zor bir proje haline getirmek heralde yapılabilecek en kolay çözüm. Öyle projeler var ki denk geldiğim adam try catch e bile güvenmeyip iç içe 2 try catch yazmış.

Bu ve benzeri durumlardan sakınmak gerekir. Open-source dünya ile birlikte exception handling için bir çok kütüphaneler-yöntemler mevcut. Projeniz için her yerde kullanabileceğiniz küçük küçük interceptor'lar yazarak exception handling'inizi tek bir yerden yönetebilir ve projenize reuseable fonksiyonaliteler kazandırabilirsiniz. Aspect-Oriented Programming anlayışı aslında en güzel örnek Nuget'te bulunan çeşitli kütüphaneler ile bir kaç dakika içerisinde bu modülleri projenize ekleyebilirsiniz.

Bu gibi yapılar ile çok kolay şekilde projenizi yönetebilir ve tek bir yerden kontrol edilebilir kodlar geliştirebilirsiniz. Böylelikle yarın bir gün exception handling ile ilgili değişiklikler yapmak istediğinizde bu işlem saatlerinizi almak yerine bir kaç dakikada yapabileceğiniz bir geliştirme olacaktır.

 

3- Logging

"Log, uğrunda ölen olmadıktan sonra log değildir.."

Log bir projede her şeydir. Küçük çaplı projeleri baz almazsak log yapısı büyük çapta olan projeler için oldukça hayati önem taşır. Öyle bir an gelir ki log'a attığınız küçücük bir byte size dünyaları kazandırır. Tabi log işlemi yaparken kayda değer şeyler logluyor olmak oldukça önemlidir. Özellikle dışa bağımlı çalıştığınız projelerde yani external bir service call işlemi olan yapılarda gelip giden request & response'ları context halinde logluyor olmak oldukça kolaylık sağlar. Gerek db ye gerekse file log yaparken bütün bu işemleri uçtan uca logluyor olmak ve aralarında ilişkileri bir unique identifier kullanarak loglamak gerekir. Örnek verecek olursak "getAccountList" adında geliştirdiğiniz bir endpoint var ve client'lar bu endpoint'e request atarak hesap listesini alıyor sizde client bu endpoint'e geldiğinde arka tarafta başka bir endpoint'e gidip hesap listesi ile ilgili farklı service call işlemleri yapıyorsunuz. Geliştirmiş olduğunuz log yapısından beklenen, belli bir context olarak uçtan uca hem client'ın request'ini hemde sizin server-side da yapmış olduğunuz diğer servis çağrımlarını logluyor olması gerekir. Bu size şunu kazandırır production'da olan bir müşteri şöyle bir şikayetle müşteri hizmetlerine şikayet bırakabilir "ben saat 11:38'den hesaplarım sayfasını görüntüleyemiyorum, sayfa boş geliyor..." bu gibi durumlarda hemen müşteri numarasından yola çıkarak log'ları kontrol ettiğinizde sorunun sizin geliştirdiğiniz service katmanından değilde dışa bağlandığınız service'den kaynaklandığını kolaylıkla görebilirsiniz. Bu logları internal ve external olarak ayırmakta fayda olabilir zira proje müdürü sizden ilerleyen zamanlarda yüzdelik olarak success ve fail oranlarını isteyebilir yani aslında tutmuş olduğunuz log'lardan yola çıkılarak proje yöneticileri analiz dahi yapmak isteyebilirler. Loglama ile ilgili örnek yazıları buradan göz atabilirsiniz.

Not: Log için çok çeşitli open source kaynaklar bulunmakta. Geliştirmelerinizi loosely coupled olacak şekilde yapıyor olursanız ilerde log yapınızla ilgili kolay değişiklik yapabilir, farklı log yapılarına kolay geçişler sağlayabilirsiniz.

 

4- Response Consistency

Response tutarsızlığı herhalde Türkiye de geliştirilen server-side projelerde ki en büyük sorunlardan biri olabilir. Bir çok defa dış servislere bağlı proje geliştirmiş biri olarak aynı namespace altında olup farklı farklı response'lar dönen durumlarla epeyce bir karşılaştım. Peki projenizde bulunan end-point'lerin döndükleri response'ların tutarlı olması neden önemlidir ? Bu sorunun cevabı hem server-side'da bulunan proje açısından hemde client açısından büyük öneme sahiptir.

Server-side açısından; öncelikle uygulamada exception-handling, logging, caching vs. gibi özellikleri geliştirirken endpoint'lerinizin return ettikleri response'ların bir BaseResponse.cs'den türüyor olması tercih edildiğinde bu gibi operasyonlar için yapılması gereken geliştirmelere harcanan eforu hemen hemen yarı yarıya azaltabilirsiniz. Yapmış olduğunuz BaseResponse.cs içerisinde Error case'leri için de bir property'iniz olması gerekir çünkü client'a farklı akışları olan error-exception mesajları dönebilirsiniz. 

Örnek BaseResponse.cs

public class BaseResponse
{
	public object Data {get;set;} // endpoint'in return ettiği response
	public ErrorModel Error {get;set;} // endpoint'in return ettiği error model
}

Client açısından; yukarıda ki BaseResponse örneğinden yola çıkacak olursak client tarafta geliştirilen network-layer da gelen response açılarak endpoint'in gönderdiği Data içerisinde bulunan gerçek response alınabilir ve sonrasında alt katmanlara gönderilip işlenebilir ve bunu yapabiliyor olmak client yazan arkadaşlar bilirler ki büyük bir nimettir. Servisten hata geldiğinde ise ErrorModel tipinde olan Error property'imiz içerisinde client'a gelen hata mesajı yine network katmanında alınıp base'den hata yönetimi yapılabilen bir layer'a gönderilip gerek pop-up ile hata mesajını gösterme gerekse kullanıcının o hata türünü aldığında uygulamada nasıl bir akışa yönlendirilmesi gibi işlemler yapılmasına kolaylık sağlanabilir.

 

5- Farklı Development Environment

"Dev de çalışıyor ama Test ortamında çalışmıyor..."

Development environment oldukça önemli bir diğer konudur. Farklı ortamlarda geliştirme yapıyor olmak biz developer'lar için eksik konfigurasyon vs gibi durumlarda başımızı ağrıtan bir durum olsada aslında çok önemli bir konudur. Bilindiği üzre Production seviyesinde geliştirme yapmak mümkün değil ama geliştirmekte olduğumuz ürünü prod'a aldığımızda sorunsuz çalışması istenir. Projenizi geliştirirken o an geliştirdiğiniz ortam, test işlemlerinin yapıldığı ortam ve production ortamlarının her birinde farklı konfigurasyonların olduğu server'lar sql'ler vs. bulunur. Geliştirme yaparken bu ortamların yönetimi ve konfigürasyonu oldukça basit ve ortamlar arası geçiş sorunsuz 1-2 hareketle geçilebiliyor olması beklenir. Peki bu development ortamları nelerdir ?

Development
Development ortamı ismindende anlaşıldığı üzre developer'ların geliştirme yaptığı ortam. Bu ortam developer istediğini yapmakta özgürdür diyebiliriz. Developer kritik kararlar alıp anlık değişiklikleri projede deneyebilir çünkü bu ortam onun kendi bireysel ortamıdır diyebiliriz.

Integration
Development ortamında bireysel olarak yapılan geliştirmelerin ortak bir branch'e commit'lenip bütün geliştirmelerin ortak bir alanda gözlemlendiği alan diyebiliriz. Kısaca bu ortamın amacı yapılan işlerin stage'ing den önce combine edilip developer'ların saptayabildiği bir hata varsa hemen fix edilip ürünü görücüye çıkartma şeklinde tanımlayabiliriz.

Staging
Staging Production'dan önceki ortamdır ve sahip olduğu özellikler itibari ile production'ın ile bire bir aynı olması beklenir. Örneğin benzer özelliklere sahip sunucular, sql server'lar, canlıda olan database'in bir gün öncesinin verilerine sahip bir database vs. gibi. Staging ortamına bir çok yerde Pre-Production da denilmekte.

Production
Son adım olarak da Production ortamı artık geliştirmiş olduğunuz projeyi canlıya aldığınız ve son kullanıcının erişimine açtığınız yerdir. Prod'a gelene kadar ki ortamlarda yapılan geliştirmeler sorunsuz-planlı bir şekilde yapıldığı taktirde testler sonucunda ürün prod'a alınır.

 

Yazının başında da belirtiğim gibi "it depends on the business" yani işe bağlı projeye bağlı. Olursa güzel olur diyebileceğimiz bu modülleri projelerinizde farklı şekillerde düşünebilir entegre edebilirsiniz.

Add comment