Məqalələr

Java Reflection`un real proyektdə istifadəsi

java-reflection
Written by Mushfiq Mammadov

Adətən Java ilə bağlı bəzi mövzular olur ki, onları oxuyanda ürəyində fikirləşirsən ki, görəsən heç bunları real proyektlərdə tətbiq edəcəm? Bu suallara öz verdiyin cavablar da əksər vaxtlar “çox güman ki istifadə etməyəcəm” olur. Amma bəzən real proyektlərdə elə situasiyalar ilə rastlaşırsan ki, bu mövzular əsl dərman kimi yerinə düşür. İdeya gəlir, tətbiq edirsən alınır və böyük zövq verir. Bu məqalə də həmin qəbildən olan nümunələrdəndir.

Birbaşa mətləbə keçək. Deməli proyektdə belə bir situasiya ilə rastlaşdım:
Class daxilində təxminən 30-a yaxın metod var və bunların sayı get-gedə arta bilər. Gələn sorğuya (request) əsasən hansı metodun çağırılacağını təyin etməlisən.

Ağıla gələn ilk həll variantı sorğuda göndərilən müvafiq field-ə əsasən, switch-case ilə uyğun metodun təyin edilib çağırılmasıdır. Kodun ilkin variantı təxminən aşağıdakı kimi olacaq. Real proyektdəki kod dəyişdirilib, minimallaşdırılıb, mahiyyət baxımından bənzər kod verilib. Məqalə şişməsin deyə burada kodun ancaq bəzi hissələri göstəriləcək, sonda github linki qeyd olunacaq, tam şəkildə oradan baxmaq olar.

ProvisioningRequest.java
ProvisioningCommand.java
ProvisioningService.java

Koddan da göründüyü kimi switch-case ifadələrinin sayı çoxdur. Burada hələ 15-ə yaxın metod qeyd olunub, təsəvvür edin real proyektdə onların sayı 30-a yaxındır və get-gedə arta bilər. Belə olan halda switch-case ifadəsi uzana-uzana gedəcək.

Kodun belə çox uzanmağı xoşuma gəlmədi, fikirləşdim görəsən bunu daha qısa şəkildə etmək olarmı?

Son günlərdə Java Reflection ilə bağlı bir məqalə oxumuşdum, ağlıma gələn ilk ideya java-reflection istifadə edərək metod adını dinamik təyin edib çağırmaq oldu. Deməli enuma konstruktor əlavə edib hər dəyər üçün müvafiq metod adını saxladım və gələn sorğudan da enum dəyərinə uyğun metod adını götürüb reflection istifadə edərək lazımı metodu çağırdım. Və istədiyim alındı 🙂

Dəyişikliklərdən sonra ProvisioningCommandProvisioningService classları aşağıdakı şəkildə oldu:

ProvisioningCommand.java
ProvisioningService.java

Təxminən 30 sətirlik switch-case ifadəsini (real nümunədə təxminən bundan 2 dəfə böyük) 2 sətirlik kod ilə əvəz etdik. Test sorğu göndərib yoxladıqda görürük ki, hər şey istədiyimiz kimidir:

provisioning-request

Düzdü reflectionun mütləq lazım olmadıqca istifadəsi tövsiyə edilmir, çünki “reflective” əməliyyatlar performans cəhətdən “non-reflective” əməliyyatlara nəzərən yavaş işləyir. Amma bizim nümunədə kiçik bir funksionallıq üçün istifadə etdiyimizdən performans baxımından elə böyük bir problem yaşamayacağıq.

Əlavə bir məsələni də qeyd edim, reflection ilə işləyərkən diqqətli olmaq lazımdı. Bizim nümunəmizdə əgər metod adını düzgün yazmasanız compile zamanı bununla bağlı sizə heç bir xəbərdarlıq verilməyəcək. Java reflectionu ancaq runtime zamanı yoxlayır, əgər metod adı düzgün yazılmazsa, Exception fırladacaq. Ona görə də yaxşı olar ki, reflection əməliyyatlar üçün testlər yazıb öncədən özümüzü sığortalayaq.   

Kod nümunəsinə bütöv şəkildə aşağıdakı github linkindən baxa bilərsiniz:

https://github.com/mmushfiq/java-reflection-example.git

Switch-case ilə olan nümunəyə “switch-case version” commitinə keçərək baxa bilərsiniz:

github-commit-browse-files

Bu məqaləmiz də bu qədər. Mövzu ilə bağlı əlavə fikirləriniz, başqa maraqlı təklifləriniz olarsa kommentdə qeyd etməyi unutmayın.

About the author

Mushfiq Mammadov

Leave a Comment

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.