Canlı ortamda coroutine’ler

Hadi Tok
GDGIstanbul
4 min readMar 18, 2019

--

Coroutine’ler Kotlin’de ve Android geliştirmede gündemdeki konulardan. CitizenMe Android uygulamasında coroutine’ler RxJava'nın Single, Maybe ve Completable classlarının yerini aldı. Devfest istanbul’da bu konu ile alakalı yaptığım sunuma buradan erişebilirsiniz. Bugün bu geçişten sonraki deneyimlerimizden bahsedeceğim. Başlamadan önce Channel’ları henüz kullanmaya başlamadık. Cold streaming özelliği geldiği zaman bu konuyu tekrar değerlendirmeyi düşünüyorum. Yani Channel’lar bu yazının kapsamının dışında.

Söylemeliyim ki RxJava’yı gerçekten seviyorum. Daha önceki bir yazımda RxJava’nın Android’de neden kullanılması gerektiğini düşündüğümü anlatmıştım. RxJava Java dünyasında asenkron programlama için en iyi tool’lara sahip ve bence hala en iyi seçenek. CitizenMe Android uygulamasında Observable pattern için hala kullanıyoruz. Fakat coroutine’lerin Kotlin’deki en iyi seçenek olduğunu söyleyebilirim.

Okunabilirlik

Muhtemelen bu en bariz olanı fakat RxJava’dan coroutine’lere geçtikten sonra kodun ne kadar iyi yönde değiştiğini anlatamam. Coroutine kullanımı kodun takibini kolaylaştırdı. Kodda asıl iş yapan kısımlar ortaya çıktığı için problemleri fark etmek daha kolaylaştı. Coroutine başlatıcıları(async , lauch ) yerine mümkün olduğunca suspend fonksiyonları kullanmayı ilke edinmek de okunabilirliği daha da artırıyor.

Unit Testing

Corutine’lere geçmeye karar vermemizin ana sebebi unit testing olabilir. RxJava kullanılan koda unit test yazarken bazı problemler yaşadık. Bir test tamamlandıktan sonra tamamlanan testin kullandığı objeler tekrardan yaratılmalıdır ki sonraki testler temiz bir başlangıç yapabilsin. Temiz bir başlangıç ile testlerin birbirinden bağımsızlığı sağlanır ve diğer testlerden etkilenmezler. Birden fazla test içeren bir test suitlerimizde bazı RxJava operasyonlarının sızıntı yaparak sonraki testlerin sonuçlarını etkilediklerini fark ettik. Tek başlarına çalıştıklarında problem olmayan testler suit ile birlikte çalıştırdıklarında farklı sonuçlar veriyorlardı. Bu yüzden bazı yerlerde sleep() ya da timeout kullanmamız gerekti. Bunların deterministik olmadıklarını düşünürüm ve bunları kullanmak test sürelerini uzatıyor.

Coroutine’lerin kullanıldığı kodun testleri MockK ile çok basit. Coroutine'leri test ederken every{} ve verify{} gibi normal fonksiyonlar yerine, runBlocking{} bloğunun içerisinde coEvery{} ve coVerify{} gibi coroutine fonksiyonları kullanmak gerekiyor. Bu yol ile sleep() ya da timeout kullanmak gerekmiyor. International Women’s Day 2019 İstanbul etkinliğinde MockK hakkında bir sunum yapacağım. Etkinlik hakkında daha fazla bilgiye buradan erişebilirsiniz.

Asenkron işleri birleştirme

RxJava ile yaşadığım problemlerin birisi de aynı anda çalışan işlerin operatörler ile birleştirilmesiydi. Buradaki ana problem esasen birleştirilme işleminin debug edilmesi. Coroutine’ler “Structured Concurrency” sayesinde her bir işlemde neler olmuş görmek çok kolay. Ayrıca bunları hayata geçirmek de kolay. Görüntüde aynı anda çalışan iki işin sonuçlarını birleştirme ile bunları sıra ile çalıştırma arasında çok bir fark yok. Bu da okunabilirliği çok yüksek kılıyor. “Structured Concurrency” ile error handling de problemler yaşadım, bunları sonraki bölümde biraz daha ayrıntılı inceleyeceğim.

Error handling

Söylemeliyim ki error handling coroutine’ler ile uzmanlaşması en zor alan. try-catch bloğunuzun olduğu yerde uygulamanızın göçtüğünü gördüğünüzde kendinizi kafanızı kaşırken bulmanız olası. Dmytro Danylyk genel olarak coroutine’ler hakkında olan fakat bu tür problemleri engelleminizi sağlayacak postunu tavsiye edebilirim.

Stacktraceler ile de problemler yaşadık. Coroutines 1.1 bu problemlerin bazılarını düzeltmiş olsa da (alakalı GitHub issue) Retrofit2 coroutines adapter ile benzer sorunlar devam ediyor. Bu problemlerin Retrofit’in sonraki versiyonunda bu PR ile kendinden coroutine desteği sağlayınca düzeleceğini ümit ediyorum.

Son olarak söz verdiğim gibi Structured Concurrency… Bu aynı anda çalışan operasyonlar için kısa ve öz bir yöntem olsa bile bazı öngöremediğiniz davranışlara şahit olabilirsiniz. Bu konuda benim tavsiyem Coroutines Guide’ı okuyup ayrı bir projede bunu denedikten sonra productionda kullanmanızdır.

Problemler yaşanabilse bile nihayetinde coroutine’leri kullanmak çok keyifli. Her ne kadar kullanımı kolay gibi görünse bile ne yaptığınızı bilmiyorsanız daha önceden öngöremediğiniz durumlarla karşılaşmanız olası. Doğru bir şekilde çözmeye çalıştığı problemin büyüklüğüne bakarak bunun aslında normal olduğunu söylemek adil olur bence. Coroutine’leri ilk incelediğimde ve kullanmaya başladığımda yukarıda verdiğim kaynakların nerdeyse hiçbirisi mevcut değildi. Umarım bu kaynaklar sizi bazı sorunlardan kurtarabilir.

--

--

Hadi Tok
GDGIstanbul

Google Developers Expert for Android | Software Engineer @Facebook | ⋰Ẍ⋱Circassian⋰Ẍ⋱