MarketApp makalesini, hem konu bütünlüğü bozulmasın hemde çok uzun olmasın diye iki kısıma ayırdım. Bu makalede Asp.Net Core ile bir web api yazacağız ve GraphQL kullanarak tek bir endpoint ile bütün isteklere cevap vereceğiz. Bir sonraki makalede ise Xamarin Forms ile bir mobil uygulama yazacağız ve bu uygulama verileri bu makalede yazdığımız servisden çekecek.

Bu arada bende GraphQL’i ilk defa kullanıyorum. Yaptığım bazı yöntemler yanlış olabilir yada best practice bu şekilde olmayabilir bu alanda uzman kişiler geri bildirim yaparlarsa memnun olurum. Bu örneği biraz detaylı yaptım çünkü önümüzde bir proje var, onu yaparken GraphQL kullanabilir miyiz sorusuna cevap almak istiyorum. Bu makale sonunda önümüzdeki zamanlarda GraphQL’i kullanıp kullanmayacağımı belirten bir sonuç yazacağım.

Giriş – GraphQL de ne ola ki ?

Teknik bir makale okurken veya yazarken konu dışına çıkılmasını sevmem ama burada anlatacaklarım özellikle yazılım dünyasına yeni başlayanlar için önemli.

Öncelikle bu makalenin ana konusu GraphQL, Giriş kısmında GraphQL üzerinden yeni bir teknoloji nasıl öğrenilir ondan bahsedeceğim. GraphQL teknolojisini duyduk, çok beğendik ve ben bunu sonraki projemde kullanırım dedik. Direk GraphQL de şu nasıl yapılırı araştırıp kodlamaya geçmek hatalı bir başlangıç olur, bunun yerine Neden sorusunu sormalıyız. Çünkü her teknoloji varolan bir soruna çözüm üretmek için çıkar, Çözümü anlamak için önce sorunu anlamamız lazım. Peki sorun ne ? Web servislerden en çok çeken Mobil uygulama geliştirici arkadaşımıza soralım;

-“Sorun nerede ? Rest de mi , Backend’ci de mi ? ”

+ “Sorun aslında her ikisinde, Adam bir endpoint yazıyor, ben kullanıcı adı ve doğum tarihini istiyorum adam bana 7 ceddini gönderiyor zaten mobil tarafda internet limitli, kullanıcıyı gereksiz verileri çekmekle bekletiyoruz. Bu yine iyi eğer istediğim endpoint yazılmamış ise, dataları tek istek de alamıyorum  ve iki, üç istek atmak durumunda kalıyorum ondan sonra loading ekranı niye bu kadar uzun diyorlar. Geçen loading ekranın da 5 kişiyi kaybettik 😀 bu işin tadı kaçtı baba, bu böyle olmaz. ”

Arkadaşımızın sorunu gayet açık ihtiyacı ise, tek bir istek ile sadece kendi istediği dataları alacak. İşte GraphQL bu soruna çözüm getiriyor. Hemde tek bir endpoint üzerinden yapacağız bütün isteklerimizi. Neden sorusuna cevap aldıktan sonra Nasıl sorusunu soralım. GraphQL aslında uygulama seviyesinde bir sorgulama yapıyor gelen isteği yönlendirdikten sonra gelen yanıtı istemciye döndürüyor. GraphQL için nasıl sorusunu teorik olarak açıklamak biraz zor, karmaşık gelebilir ama örnek uygulama yaparken daha iyi anlaşıcağını düşünüyorum. Yeni bir teknolojiyi öğrenirken bu aşamadan sonra resmi dokümantasyonu okuyup terminolojiye aşina olduktan sonra örnekleri incelemeli ve daha farklı ve kapsamlı bir örnek yapmalıyız. Çünkü genelde aynı örneği yapmak kolay oluyor ama biz bir ürün geliştirirken kullandığımız stack’de birden fazla teknoloji kullanacağımız için yeni öğrendiğimiz teknolojiyi bir çok teknoloji ile kullanmak zor oluyor ve kimsenin bahsetmediği eksik yanlarını ürünü geliştirirken fark ediyoruz. Bu durum ile karşılaşmamak için resmi örnekleri yaptıktan sonra kapsamlı bir örnek yapmalıyız.

Ek olarak yukarıda yeni bir teknoloji öğrenirken izlenecek bazı adımlardan bahsettim peki bu fikrimi neye göre beyan ettim diye sorarsanız kendimden biliyorum, Bir senior(usta demeyi daha çok seviyorum) yazılımcı ile beraber proje geliştirirken, Diyelim ki projeye yeni bir plugin veya kütüphane veya teknoloji dahil edeceksiniz. Projeye hem çırak hem usta yazılımcı hakim iken, yeni teknolojiyi anlayıp projeye dahil etme işlemini usta yazılımcı çok daha çabuk yapıyor bunun sebebi tecrübe ama burada ufak bir nüans var. Usta yazılımcı bu teknoloji olmadan da bu tarz sorunları kendine özgü şekilde çözüyordu ve sorunu çok iyi biliyordu. Yeni teknolojiye baktığı zaman aslında kendisinin yaptığı çözümün daha sistematik bir şekilde yapıldığını fark ettiği için o teknolojiyi hem daha çabuk öğreniyor hemde kıymetini daha iyi biliyor. Genel olarak yazılımcılara bakarsanız; Nesne yönelimli programlamanın kıymetini prosedürel programlama yapan bilir, Jquery’nin kıymetini Javascript yazan bilir, Angular, React, Vue kıymetini Jquery yazan bilir, Docker’ın kıymetini sanallaştırma yapan bilir, .Net Core’un kıymetini IIS ile uğraşan bilir ve hakeza örnekler arttırılabilir. Aslında arada nostalji yapıp eskiden nasıl yazılım geliştiyorlardı diyip eski teknolojileri kurcalamak iyi olabilir. 🙂

Kazanımlar

-Model Class’lar ile PostgreSQL veri tabanında tablolar oluşturma

-Veri tabınına başlangıç kayıları eklemek (DbInitialize)

-Temel CRUD işlemleri

-Asp.Net Core Web Api’yi GraphQL ile kullanmak

Örneğimizi yapmaya başlayabiliriz..

1)Asp.Net Core Web Api oluşturma

Proje yapımız aşağıdaki gibi olacaktır. Servisimiz basit bir alışveriş uygulamasının, ihtiyacı olan istekleri karşılayacak.

Unutmadan projede kullandığım pluginleri buraya yazayım. 🙂 İster Nuget ile isterseniz proje(.csproj) dosyasına ekleyerek yükleyebilirsiniz.

Projenin kodlarını Github’da paylaşacağım şuradan ulaşabilirsiniz bu yüzden bazı temel kodları buraya yazmayacağım. Bu  kısımda anlattığım kodları Github’da bulabilirsiniz. İlk önce Modellerimiz oluşturalım. Kategori, Ürün,  Kullanıcı, Yorum ve Sipariş modelleri uygulamamız için yeterli olacaktır. Daha sonra veri tabanında bu modellere karşılık gelecek tabloları belirtmek için DbContext’i yazalım. Daha sonra veri tabanı ilk oluşturulduğunda tablolar boş kalmasın, üzerinde çalışmalar yapabileceğimiz bazı datalar olsun diye DbInitializer sınıfını oluşturalım. Normalde cli ile veri tabanını manuel olarak oluşturabiliriz ama DbInitalizer içinde bunu kontrol edip otomatik olarak oluşturulmasını sağlıyoruz zaten. Son olarak;

-appsettings.Development içine connection stringi ekliyoruz

-Startup.cs içinde ConfigureServices metodumuza

postgreSQL entity framework için gerekli ayarları belirtiyoruz.

-Statup.cs içinde Configure metodunda  DbInitializer.Initialize(app);  çağırmayı unutmayalım. Eğer bir eksik yoksa projeyi çalıştırdığınızda veri tabanında tablolarımız oluşmuş ve kayıtlarımız eklenmiş olacaktır.

Şimdi veri tabanımız ile doğrudan etkileşimde bulanacak repository’lerimizi yazalım. Bu kısımı neden bu şekilde yaptık diye bir sorunuz varsa önce DI(Dependency Injection) konusunu araştırabilirsiniz. Interface’lerimiz aşağıdaki gibidir.

CRUD işlemlerini çok temel bir şekilde yaptım, daha detaylı da yapılabilirdi. Asenkron olarak çalışabilir, geriye daha anlamlı mesajlar döndürebilirdi.  Bu arada neden ekleme, silme ve güncelleme işlemlerinde geriye model döndürüğümü merak edenler, sebebi GraphQL’dir. Beni bu konuda biraz ayar etti 🙂 istediğim verileri geriye döndüremedim. Ama şuanki hali de bu örnek için iş görüyor, sorunu çözersem github’a gönderirim. Şimdi Repository sınıflarımızı oluşturalım ve kendisine ait interface’den miras alıp ilgili metodları implement’e edelim. Daha sonra Startup.cs içinde injection işlemlerini aşağıdaki gibi yapalım.

Yukarıda yüklenmesi gereken paketleri yazmıştım eğer eklemediyseniz bu aşamada GraphQL paketini projeye ekleyebilirsiniz.

GarphQL’de şema yapısında iki temel root type vardır. Biri query diğeri mutation’dır. query de veri tabanından veri okuma ile ilgili field’larımızı tanımlayacağız. Mutation’da ise veri yazma ile ilgili field’larımız bulunacak. Uygulamanın bitmiş hali aşağıdaki gibi olacak. İlk resimde iki adet root type bulunmakta, ikinci resimde query field’ları ve üçüncü resimde mutation field’ları görülmektedir.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bütün object type’ları ve field’ları buraya yazmayacağım. Sadece Product için olanları yazacağım geri kalanları Github da bulabilirsiniz. Şimdi en temel bileşen olan Object type’dan başlıyalım.

Object type aslında bizim modellerimize karşılık gelmektedir. Şimdi Product için bir object type tanımlayalım ve onun üzerinden object type’ları anlamaya çalışalım.

ObjectGraphType sınıfından miras aldık ve Constructor içinde Product modelimize karşılık gelen alanları, Field’lar ile tanımladık. Category, Review ve Order ile olan relation’lar için ise, resolve fonksiyonlar yazdık.

Product için query field’ları yazalım.

İki adet field yazdık ve resolve fonksiyonlar ile dataların nereden alınacağını belirttik. Dikkat ettiyseniz Id’ye göre ürünlerin getirildiği field’da, istemciden alınan parametreye göre sonuç döndürüyoruz. Burada argüman kullanımını görmüş olduk.

Şimdi Mutation sınıfı tanımlayıp, gerekli field’ları yazalım.

Bu field’larda ekleme, silme ve güncelleme işlemlerini yaptık. aslında query field’ları tanımlamaktan pek farkı yok sadece resolve fonksiyonların içinde, gelen isteği doğru yönlendirmek önemli. Dikkat edilecek bir diğer nokta ise IntGraphType zaten default gelen bir GraphQL type’i ama birde ProductInputType var bunu biz tanımladık. Bu şekilde argüman işlemleri daha kolay oluyor. Aşağıda ProductInputType tanımlaması bulunmaktadır.

InputObjectGraphType’den türetip ilgili field’ları tanımlıyoruz.

Object type, query, mutation ve field’ları yazdık şimdi de şemamız da root type’ları tanımlayalım.

Diğer Modellerimiz için aynı işlemleri tekrar edeceğiz, bu işlemleri yaptıktan sonra, nihayet bir tek endpoint’imizi yazacağız 🙂

Route attribute ile yolu belirttik. Post metodumuza gelecek olan parametreleri yakalamak için GraphQLQuery sınıfını tanımladık.

Controller’da şu işlemleri yapıyoruz; IDocumentExecuter’dan türettiğimiz instance’ı execute etmek için gelen parametreleri konfigüre ediyoruz ve geri kalanı GraphQL’e bırakıyoruz biz zaten gerekli olan bütün tanımlamaları yaptık. Gelen parametrelerde query’e göre ilgili field’a yönlendirme yapılacak ve dönen yanıt kullanıcıya iletilecek.

Son olarak Startup.cs’nin son hali aşağıdaki gibidir.

Projemizi tamamladık. Videoda GraphiQL ile endpoint’imizi test ettim.

Elimden geldiğince GraphQL’i anlatmaya çalıştım, bahsetmeyi unuttuğum bir çok nokta olabilir. Bu servisi yazmak benim bir hayli zamanımı aldı çünkü pek kaynak yok. Zaten GraphQL yeni bir teknoloji iken .Net ekosisteminde pek gelişmiş değil. Resmi sitesinde iki adet plugin var. Sizde GraphQL’i daha detaylı araştırmak istiyorsanız aşağıya eklediğim linkler işinize yarayabilir.

– http://graphql.org/learn/

https://github.com/graphql-dotnet/graphql-dotnet kullandığımız plugin

-Bu konuda gördüğüm tek Türkçe içerik link

-Bu Rus abimizin yaptığı örnek bana çok yardımcı oldu link. Ayrıca bloğunda çok değerli yazılar var.

-Bu Alman abimizin yazısı da çok güzel link. Yazdığı yazı Reddit’de bahsedilmiş, abimiz gaza gelip plugin çıkarmış detaylı inceleyemedim ama bakmak da fayda var.

Sonuç

GraphQL gerçekten çok güzel bir teknoloji, peki projelerimizde kullanmalı mıyız ? Bence her teknoloji gibi bu teknolojiyi de doğru yerde kullanmak gerekir. Eğer projemiz çok büyük ise ve servisimiz çok fazla kişiye hizmet veriyorsa, özellikle mobil client’lar ile veri alışverişi fazla ise kesinlikle kullanmalıyız. Ama projemiz daha küçük çaplı ise böyle bir atraksiyona girmeye gerek yok çünkü ciddi bir iş yükü getiriyor ki, biz daha temel bir servis yazdık içinde authentication, authorization vb.. bir çok özellik eklemedik. Küçük projelerde endpoint sayısını arttırmak daha mantıklı geliyor. Tabi bu benim şahsi fikrim, siz farklı düşünüyorsanız yorum olarak yazabilirsiniz böylece fikir alışverişinde bulunmuş oluruz.

Kaynak Kodlar