RetroLambda – Her yer lambda Her yerde lambda

Açıkçası uzun süre Java 6  kullanan biri olarak, Java 7 bana hiç cazip gelmemişti. Genelde enterprise düzeyde uygulamalar yazdığımdan ve bunu yaparken de spring kullandığımdan çok bir artısını görmedim. Özellikle multi-thread uygulamalar geliştiriyorsanız bir çok yenilik getiriyor Java 7 ama bu yeniliklerin hiç biri Java 8’deki kadar uygulamanızı nasıl geliştirdiğinizi etkilemiyor. Bir Stream API ya da Lambda ifadeleri kadar insanı heyecanlandırmıyorda.

Her ne kadar Java 8 beni heyecanlandırsa da ne yazık ki geliştirdiğim projelerde daha Java 8 kullanma imkanına sahip olamadım. Şu anda geliştirmekte olduğum proje Java 7 ile geliştirilirken, bundan önceki projem Java 6 ile geliştiriliyordu. Baktığınız zaman ikisi de miladını doldurdu. Her ikisinede (Java 7 ve Java 6) Oracle artık destek vermediğini duyurdu. Bunun çeşitli sebepleri var tabi. Heralde bu sebeplerden en önemlisi, Java’nın tam anlamıyla geriye dönük desteği vermiyor oluşudur. Her bir yeni versiyondan sonra, Oracle, bir de geriye dönük desteklenmeyen ya da farklı davranan yerlerin listesini yayınlar. Örneğin Java 7 ve Java 6 arasındaki tutarsızlıklara ya da Java 8 ve Java 7 arasındaki tutarsızlıklara bakabilirsiniz. Her ne kadar bu tutarsızlıklara denk gelmeniz pek olası gözükmese de büyük ölçekli kurumsal bir uygulamada siz ya da sizin kullandığınız bir kütüphane bu farklılıkları tutturabiliyor.java_lambda

Lambda ifadelerini ya da Stream API’nı kullanmamanız için sadece bu tutarsızlıklara denk gelmeniz gerekmiyor. Bir şirket politikasına da denk gelebilirsiniz ki bence bu çok daha büyük bir sorun. Bu sorunlar sadece sizden, projenizden ya da şirketinizden kaynaklı da olmayabilir. Android uygulaması geliştirdiğinizi düşünün. Andorid uygulaması geliştirirken en çok Java 7 kullanabiliyorsunuz onu da anca KitKat ve üzeri için kullanabiliyorsunuz.

İşte tam bu noktada RetroLambda oyuna dahil oluyor. RatroLambda sizin için, Java8 lambda ifadelerinizi “backport” ediyor. Siz yine Java8’de geliştiriyorsunuz fakat kodunuzu, sorunsuz bir şekilde Java 7 ya da Java 6 üzerinde hatta android üzerinde çalıştırabiliyorsunuz. RetroLambda temel olarak java byte kodları ile oynuyor ve sizi Java8 bağımlılıklarından kurtarıyor. Ben detaylı olarak bunu nasıl yaptıklarına değinmeyeceğim. Ama araştırırsanız bu çoğu yere farklı uzunluklarda anlatmışlar. Benim anlatacağım, javada bunu nasıl kullanabileceğiniz. Bir iki cümleyle de android üzerinde nasıl kullanabileceğinizi anlatacağım.

Peki Lambda Nedir?

RetroLambda’ya geçmeden önce lambda ifadelerinin ne olduğuna ve bizi nelerden kurtardığına kısaca değinmek itiyorum. Eğer daha önce Google Guava ya da RxJava benzeri, daha fonksiyonel programlamaya yönelik araçlar kullandıysanız, bir çok “anoynymous” sınıf kullanmışsınızdır. Hani şu bir ya da daha fazla methodtan oluşan, isimsiz olarak, satır içinde tanımladığımız sınıflar var ya işte onları kastediyorum. Lambda ifadeleri temelde bizi bu sınıflardan kurtarıyor. Bir “syctactic sugar” olarak düşünebilirsiniz. Özellikle fonksiyonel programlama dillerinde bir hayli kullanılan yapılar bunlar. Bir çok genel amaca yönelik OO dillerde de bu zaten destekleniyor. Bakmayın java’ya biraz geç geldi. Tabi bu yapı için bir diğer ihtiyacını olan şey de fonksiyonları parametre olarak geçmeniz. Ama okadar detayına girmeyeceğim. Biraz daha görselleştirmek adına, Guava ile öncesi ve sonrası şeklinde kod bloklarımıza bakalım.

Örneğin elimizde bir listede User nesneleri olsun.

Bizse bu liste üzerinde kullanıcı adına göre arama yapıp, verdiğimiz parametre ile başlayan sonuçları dönelim. Bunu Guavasız ve Java 8 öncesinde lamdasız yapmak istersek aşağıdaki gibi bir for yazmamız lazım.

Lamdasız ve Guavasız

Gördüğünüz gibi çok güzel olmayan bir kod elde etmiş olduk. Bunu guava ile yapmak istersek daha güzel fakat yeterince güzel olmayan bir kod elde etmiş oluyoruz.

Lamdasız fakat Guavalı

Burada Predicate ile bir “anoynymous” sınıf oluşturmuş olduk. Bence daha güzel oldu. Zaten Java 6 ya da Java 7 projelerimde sıkça kullanıyorum bu kütüphaneyi. Java 8 projesi geliştirdiğimde Stream API’dan dolayı ihtiyacım olacağını sanmıyorum.

Evet şimdi de bunu Lambda ifadeleri ile nasıl yazacağımıza bakalım.

Lambdalı

Gördüğünüz gibi çok daha basit bir hale geldi. Hatta okadar basit ki ayrı bir methoda çıkmaya bile gerek yok. İşte biz bu ifadeleri Java 7 ve Andorid sistemlerde nasıl kullanabileceğimize bakacağız.

RetroLambda

RetroLambday’ı projenize entegre etmenizin farklı yolları bulunuyor. Standalone uygulamanıza javaagent olarak vereiblirsiniz ya da build döngünüze oturtabilirsiniz. Build döngüsüne rahat oturtabilmeniz için popüler build araçarını da destekliyor. Ben normal java projelerinde ağırlıklı Maven kullandığımdan maven ile ne şekilde yapacağınıza değineceğim.

Maven

Maven ile projenizi build ederken sadece aşağıdaki plugin’i eklemeniz yeterli. Plugin sizin için lambda ile oluşan sınıfların yerine, Java7 (ya da target versiyonunuz neyse) uyumlu sınıfları koyacaktır.

pom.xml

Burada dikkat etmeniz gereken noktalar aşağıdaki gibidir.

  • Geliştirirken Java 8 kullandığımız için, “compile” plugin’inde kaynak kodumuzu ve hedefimizi Java 8 olarak veriyoruz.
  • Daha sonra retrolambda pluginini ekliyoruz. RetroLambda’da gerçekte kodumuzu çalıştırmayı hedeflediğimiz ortamı giriyoruz. Biz Java 7’yi hedef aldığımızdan buraya 1.7 giriyoruz.
  • Başka bir bağımlılık vermemize gerek yok. Örneklerde kullandığımız guava kütüphanesini ekliyoruz sadece. RetroLambda için ek bir kütüphaneye ihtiyacımız yok.

Şimdi ise örnek kodumuza bakalım. Maven projemize App.java sınıfını ekliyoruz ve içeriğini aşağıdaki gibi yapıyoruz.

App.java

Bu kodumuzu IDE içerisinden yani Java 8 ile çalıştırdığımızda aşağıdaki çıktıyı alıyoruz.

Java8-Output

Daha sonra projemizi, maven shade plugin’i ile çalıştırılabilir JAR haline getiriyoruz ve Java 7 ortamında çalıştırıyoruz. Java 7 otamında ise aynı çıktıyı alıyoruz.

Java7-Output

Şimdi ise benzer işlemi kısaca andorid’te nasıl yapacağımıza bakalım.

Andorid

RetroLambda tüm popüler ortamları desteklediğinden yapmanız gereken tek şey gradle build döngünüze retrolambda’yı eklemek. Ne yazıkki Java 7 de olduğu kadar rahat bir şekilde eklenemeyecek. Ama mantık olarak aynı şeyleri yapacağız. Önce kaynak kodlarımızın Java 8 içerdiğini belirteceğiz. Sonra eklentiyi tanımlayıp ilgili ayarlarını yapacağız. Tüm değişikliklerimizi build.gradle üzerinde yapacağız.

Kaynak Kodu Versiyonlarının Tanımlanması

Kaynak kodu versiyonlarımızı tanımladığımıza göre şimdi build döngüsüne ilgili eklentimizi kayıt edelim. Bunun için aşağıdaki eklemeleri yapıyoruz.

Build Döngüsünün Kurulması

Son olarak ayarlarımızı yapalım. Android için geliştirme yaparken JAVA8_HOME ve JAVA6_HOME sistem değişkenlerinin tanımlı olması gerekiyor. Bu değişkenlerimizi ayarlarımızda kullanacağız.

Ayarların Yapılması

Sonoctobiwan

Umarım RetroLamba’nın neler getirdiğini ve nasıl kullanabileceğinizi açıklayabilmişimdir. Java’da geliştirilmiş örneğin kaynak kodlarını aşağıdaki adresten indirebilirsiniz.

Git: https://github.com/bhdrkn/Java-Examples/tree/master/retrolambda-sample

End of Line