Reaktiv proqramlaşdırma java. FRP: Funksional Reaktiv Proqramlaşdırma olduğu kimi. ReactiveCocoa-nın əsas komponentləri




Zaman keçdikcə proqramlaşdırma dilləri yeni texnologiyaların ortaya çıxması, müasir tələblər və ya kod yazı üslubunu yeniləmək üçün sadə bir istək səbəbindən daim dəyişir və inkişaf edir. Reaktiv proqramlaşdırma Reaktiv Kakao kimi müxtəlif çərçivələrdən istifadə etməklə həyata keçirilə bilər. O, Objective-C dilinin imperativ üslubunun əhatə dairəsini dəyişdirir və proqramlaşdırmaya bu yanaşma standart paradiqmanı təklif etmək üçün çox şeyə malikdir. Bu, əlbəttə ki, iOS tərtibatçılarının diqqətini cəlb edir.

ReactiveCocoa Objective-C-yə deklarativ üslub gətirir. Bununla nə demək istəyirik? C, C++, Objective-C və Java və s. kimi dillərin istifadə etdiyi ənənəvi imperativ üslubu aşağıdakı kimi təsvir etmək olar: Siz müəyyən bir şəkildə icra edilməli olan kompüter proqramı üçün direktivlər yazırsınız. Başqa sözlə, siz nəyisə “necə etmək olar” deyirsiniz. Deklarativ proqramlaşdırma nəzarət axınını "necə etməli" təyin etmədən, "nə etməli" hərəkətlər ardıcıllığı kimi təsvir etməyə imkan verir.

İmperativ və Funksional Proqramlaşdırma

Proqramlaşdırmaya imperativ yanaşma kompüterin tapşırıqları yerinə yetirmək üçün atmalı olduğu hər bir addımın ətraflı təsvirini nəzərdə tutur. Əslində, imperativ üslub yerli proqramlaşdırma dillərində istifadə olunur (və ya maşın kodunu yazarkən istifadə olunur). Bu, yeri gəlmişkən, əksər proqramlaşdırma dillərinin xarakterik xüsusiyyətidir.

Əksinə, funksional yanaşma yerinə yetirilməli olan funksiyalar toplusu ilə bağlı problemləri həll edir. Siz hər bir funksiya üçün giriş parametrlərini və hər bir funksiyanın nə qaytardığını müəyyən edirsiniz. Bu iki proqramlaşdırma yanaşması çox fərqlidir.

Əsas dil fərqləri bunlardır:

1. Dövlət dəyişiklikləri

Təmiz funksional proqramlaşdırma üçün heç bir yan təsir olmadığı üçün vəziyyət dəyişikliyi yoxdur. Yan təsir bəzi xarici qarşılıqlı təsir nəticəsində qaytarılan dəyərə əlavə olaraq vəziyyət dəyişikliklərini nəzərdə tutur. Alt ifadənin SR (referensial şəffaflıq) tez-tez "yan təsirlərin olmaması" kimi müəyyən edilir və ilk növbədə saf funksiyalara aiddir. SP funksiyanın icrasına funksiyanın dəyişkən vəziyyətinə xaricdən giriş əldə etməyə icazə vermir, çünki hər bir alt ifadə tərifinə görə funksiya çağırışıdır.

Hər şeyi aydınlaşdırmaq üçün təmiz funksiyalar aşağıdakı xüsusiyyətlərə malikdir:

  • yeganə diqqətəlayiq nəticə qaytarılan dəyərdir
  • giriş parametrlərinin yeganə asılılığı arqumentlərdir
  • arqumentlər hər hansı bir çıxış yaratmazdan əvvəl tam müəyyən edilir

Funksional yanaşmanın yan təsirləri minimuma endirməsinə baxmayaraq, hər hansı bir inkişafın ayrılmaz hissəsi olduğu üçün onlardan tamamilə qaçınmaq olmaz.

Digər tərəfdən, imperativ proqramlaşdırmada funksiyaların istinad şəffaflığı yoxdur və bu, deklarativ və imperativ yanaşma arasında yeganə fərq ola bilər. Yan təsirlərdən vəziyyət və I/O həyata keçirmək üçün geniş istifadə olunur. Mənbə dildəki əmrlər vəziyyəti dəyişə bilər, nəticədə eyni dil ifadəsi üçün fərqli dəyərlər yaranır.

Bəs ReactiveCocoa? Bu, açıq şəkildə təmiz funksiyaları daxil etməyən, konseptual olaraq imperativ dil olan Objective-C üçün funksional çərçivədir. Bir vəziyyət dəyişikliyindən qaçmağa çalışarkən, yan təsirlər məhdudlaşmır.

2. Birinci sinif obyektləri

Funksional proqramlaşdırmada birinci dərəcəli obyektlər olan obyektlər və funksiyalar var. Bunun mənası nədi? Bu o deməkdir ki, funksiyalar parametr kimi ötürülə, dəyişənə təyin edilə və ya funksiyadan qaytarıla bilər. Niyə rahatdır? Bu, funksiya göstəriciləri (char *(*(**foo)()); - əylənin!) olmadan icra bloklarını idarə etməyi, funksiyaları müxtəlif üsullarla yaratmağı və birləşdirməyi asanlaşdırır.

İmperativ yanaşmadan istifadə edən dillərin birinci dərəcəli ifadələrlə bağlı öz qəribəlikləri var. Objective-C haqqında necə? Bağlama tətbiqləri kimi bloklara malikdir. Daha yüksək dərəcəli funksiyalar (HFO) blokları parametr kimi götürərək modelləşdirilə bilər. Bu halda blok bağlanmadır və müəyyən bloklar dəstindən daha yüksək səviyyəli funksiya yaradıla bilər.

Bununla belə, funksional dillərdə FVP-nin manipulyasiyası prosesi daha sürətlidir və daha az kod sətirləri tələb olunur.

3. Əsas axın nəzarəti

İmperativ üslub dövrələri funksional proqramlaşdırmada rekursiya funksiyasına çağırışlar kimi təqdim olunur. Funksional dillərdə iterasiya adətən rekursiya vasitəsilə həyata keçirilir. Niyə? Yəqin ki, mürəkkəblik naminə. Objective-C tərtibatçıları üçün döngələr proqramçı üçün daha uyğun görünür. Rekursiyalar RAM-ın həddindən artıq istehlakı kimi çətinliklərə səbəb ola bilər.

Amma! Döngələrdən və ya rekursiyalardan istifadə etmədən funksiya yaza bilərik. Kolleksiyanın hər bir elementinə tətbiq oluna bilən sonsuz mümkün ixtisaslaşmış hərəkətlərin hər biri üçün funksional proqramlaşdırma “ kimi təkrar istifadə edilə bilən iterativ funksiyalardan istifadə edir. xəritə”, “qat”, “". Bu funksiyalar mənbə kodunu refaktorinq etmək üçün faydalıdır. Onlar təkrarlanmanı azaldır və ayrıca funksiyanın yazılmasını tələb etmir. (Oxuyun, bu barədə daha çox məlumatımız var!)

4. İcra qaydası

Deklarativ ifadələr yalnız subifadə funksiyası arqumentlərinin və davamlı vəziyyət əlaqələrinin məntiqi əlaqələrini göstərir. Beləliklə, yan təsirlər olmadıqda, hər bir funksiya çağırışının vəziyyətə keçidi digərlərindən asılı olmayaraq baş verir.

İmperativ ifadələrin funksional icrası uçucu vəziyyətdən asılıdır. Buna görə də, icra qaydası vacibdir və mənbə kodunun təşkili ilə dolayı müəyyən edilir. Bu sualda biz hər iki yanaşmanın qiymətləndirmə strategiyaları arasındakı fərqi qeyd edə bilərik.

Tənbəl və ya ehtiyacdan asılı olaraq qiymətləndirmələr funksional proqramlaşdırma dillərində strategiyalardır. Belə halda, ifadənin qiymətləndirilməsi onun dəyərinə ehtiyac duyulana qədər təxirə salınır və bununla da təkrar qiymətləndirmələrdən qaçırıq. Başqa sözlə, ifadələr yalnız asılı ifadə qiymətləndirildikdə qiymətləndirilir. Əməliyyatların ardıcıllığı qeyri-müəyyən olur.

Bunun əksinə olaraq, imperativ dildə güclü qiymətləndirmə ifadənin dəyişənə bağlanan kimi qiymətləndiriləcəyi deməkdir. Bu, icra qaydasının diktə edilməsini nəzərdə tutur.Beləliklə, alt ifadələrin (o cümlədən funksiyaların) nə vaxt qiymətləndiriləcəyini müəyyən etmək daha asandır, çünki alt ifadələrin digər ifadələrin qiymətləndirilməsinə təsir edən yan təsirləri ola bilər.

5. Kodun sayı

Bu vacibdir, funksional yanaşma imperativdən daha az kod yazmağı tələb edir. Bu, daha az qəza, test üçün daha az kod və daha məhsuldar inkişaf dövrü deməkdir. Sistem daim təkmilləşdiyi və böyüdüyü üçün bu vacibdir.

Reaktiv kakaonun əsas komponentləri

Funksional proqramlaşdırma gələcək (dəyişənin yalnız oxunaqlı təsviri) və vəd (dəyişən gələcəyin yalnız oxunaqlı təsviri) kimi tanınan anlayışlarla məşğul olur. Onlarda nə yaxşıdır? İmperativ proqramlaşdırmada siz artıq mövcud olan dəyərlərlə işləməlisiniz, bu da asinxron kodun sinxronlaşdırılması ehtiyacına və digər çətinliklərə səbəb olur. Lakin fyuçers və vədlər anlayışları hələ yaradılmamış dəyərlərlə işləməyə imkan verir (asinxron kod sinxron şəkildə yazılır).


Siqnal

Gələcək və vəd reaktiv proqramlaşdırmada siqnallar kimi təmsil olunur. - ReactiveCocoa-nın əsas komponenti. Gələcəkdə təqdim olunacaq hadisələrin axınını təqdim etmək imkanı verir. Siz siqnala abunə olursunuz və zamanla baş verəcək hadisələrə giriş əldə edirsiniz. Siqnal təkanla idarə olunan ipdir və düyməyə basmaq, asinxron şəbəkə əməliyyatları, taymerlər, digər UI hadisələri və ya zamanla dəyişən hər hansı bir şey ola bilər. Onlar asinxron əməliyyatların nəticələrini əlaqələndirə və çoxlu hadisə mənbələrini səmərəli şəkildə birləşdirə bilərlər.

Ardıcıllıq

Başqa bir axın növü ardıcıllıqdır. Siqnaldan fərqli olaraq, ardıcıllıq çəkmə ilə idarə olunan axındır. Bu, NSArray ilə oxşar məqsədi olan bir növ kolleksiyadır. RACSequence müəyyən əməliyyatları kolleksiyada olduğu kimi ardıcıl olaraq deyil, ehtiyacınız olduqda yerinə yetirməyə imkan verir. NSArray. Ardıcıllıqdakı dəyərlər yalnız standart olaraq təyin edildikdə qiymətləndirilir. Ardıcıllığın yalnız bir hissəsinin istifadəsi potensial olaraq performansı yaxşılaşdırır. RACSequence kakao kolleksiyalarının ümumi və deklarativ şəkildə idarə olunmasına imkan verir. RAC kakao kolleksiyası siniflərinin əksəriyyətinə -rac_sequence metodunu əlavə edir ki, onlar kimi istifadə olunsun RACSequences.

Komanda

Müəyyən hərəkətlərə cavab olaraq, RACC əmri və siqnala abunə olun. Bu, ilk növbədə UI qarşılıqlı əlaqəsinə aiddir. Kateqoriyalar UIKitəksər idarəetmələr üçün ReactiveCocoa tərəfindən təmin edilir UIKit, bizə UI hadisələrini idarə etmək üçün düzgün yol verin. Təsəvvür edək ki, bir düymənin klikləməsinə cavab olaraq istifadəçini qeydiyyatdan keçirməliyik. Bu halda, komanda şəbəkə sorğusunu təmsil edə bilər. Proses başlayanda düymə öz vəziyyətini "qeyri-aktiv" vəziyyətinə dəyişir və əksinə. Başqa? Biz komandada aktiv siqnal ötürə bilərik (Əlçatanlıq yaxşı bir nümunədir). Buna görə də, əgər server əlçatmazdırsa (bu, bizim "siqnalımızdır"), o zaman əmr əlçatmaz olacaq və əlaqəli idarəetmənin hər əmri bu vəziyyəti əks etdirəcək.

Əsas əməliyyatların nümunələri

RACSignals ilə əsas əməliyyatların necə işlədiyinə dair bəzi diaqramlar:

Birləşdirin

+ (RACSignal *) birləşmə: (id ) siqnallar;


Nəticə axınında hər iki hadisə axını birləşdirilmişdir. Beləliklə, "+birləşdirmə" konkret hadisələr mənbəyinə əhəmiyyət vermədiyiniz, lakin onları bir yerdə idarə etmək istədiyiniz zaman faydalıdır. Bizim nümunəmizdə stateLabel.text 3 müxtəlif siqnaldan istifadə edir: tamamlama, tamamlama, xətalar.

RACCommand *loginCommand = [ initWithSignalBlock:^RACSignal *(id girişi) ( // icazə verin daxil olaq!)]; RACSignal *executionSignal = ; RACSignal *tamamlamaSiqnal = filter:^BOOL(RACEvent *hadisə) ( qaytarın hadisə.eventType == RACEventTypeCompleted; )] xəritə:^id(id dəyəri) (qayıt @"Bitti"; )]; )]; RACSignal *errorSignal = ; RAC(self.stateLabel, mətn) = ];

+ (RACSignal *) birləşdirinSon:(id )siqnallar azaldır:(id (^)())reduceBlock;

Nəticədə, axın ötürülən axınların ən son dəyərlərini ehtiva edir. Əgər axınlardan birinin əhəmiyyəti yoxdursa, nəticə boş olacaq.


Nə vaxt istifadə edə bilərik? Əvvəlki nümunəmizi götürək və ona daha çox məntiq əlavə edək. İstifadəçi düzgün e-poçt və şifrəni daxil etdikdə giriş düyməsini aktivləşdirmək faydalıdır, elə deyilmi? Bu qaydanı belə elan edə bilərik:

ACSignal *enabledSignal = azaldın:^id (NSString *e-poçt, NSString *parol) ( qaytarın @( && password.length > 3); )];

*İndi giriş əmrimizi bir az dəyişdirək və onu faktiki loginButton-a bağlayaq

RACCommand *loginCommand = [ initWithEnabled:enabledSignal signalBlock:^RACSignal *(id girişi) ( // daxil olaq! )]; ;

- (RACSignal *)flattenMap:(RACStream * (^)(id dəyəri))blok;

Siz verilmiş funksiyadan (f) istifadə edərək orijinal axındakı hər bir dəyər üçün yeni axınlar yaradırsınız. Nəticə axını orijinal axınlarda yaradılan dəyərlərə əsaslanaraq yeni siqnalları qaytarır. Beləliklə, asinxron ola bilər.


Təsəvvür edək ki, sistemə icazə sorğunuz iki ayrı hissədən ibarətdir: Facebook-dan məlumat əldə edin (ID və s.) və onu Backend-ə ötürün. Tələblərdən biri də girişi ləğv edə bilməkdir. Buna görə də, müştəri kodu onu ləğv edə bilmək üçün giriş prosesinin vəziyyətini idarə etməlidir. Bu, xüsusilə birdən çox yerdən daxil ola bilsəniz, çoxlu kodlar verir.

ReactiveCocoa sizə necə kömək edir? Bu giriş tətbiqi ola bilər:

- (RACSignal *)Facebook-dan istifadəyə icazə verin ( qaytarın [[ flattenMap:^RACStream *(FBSession *sessiya) ( qayıdış ; )] flattenMap:^RACStream *(NSDictionary *profil) ( qaytar ; )]; )

əfsanə:

+ - açılışa aparan bir siqnal FBSsession. Lazım gələrsə, bu, daxil olmağa səbəb ola bilər Facebook.

- - kimi ötürülən seans vasitəsilə profil məlumatlarını alan siqnal özü.

Bu yanaşmanın üstünlüyü ondan ibarətdir ki, istifadəçi üçün bütün axın qeyri-səlisdir, istənilən “mərhələ”də ləğv edilə bilən tək siqnalla təmsil olunur, istər Facebook-a giriş, istərsə də Backend zəngi.

Filtr

- (RACSignal *) filtri:(BOOL (^)(id dəyəri))blok;

Nəticədə, axın verilmiş funksiyaya uyğun olaraq süzülmüş “a” axınının dəyərlərini ehtiva edir.


RACSequence *ardıcıllıq = @[@"Bəzi", @"nümunə", @"of", @"ardıcıllıq"].rac_sequence; RACSequence *filteredSequence = ; )];

Xəritə

- (RACSignal *)xəritəsi:(id (^)(id dəyəri))blok;

FlattenMap-dən fərqli olaraq, Xəritə sinxron şəkildə işləyir. “a” xassə dəyəri verilmiş f (x + 1) funksiyasından keçir və xəritələnmiş orijinal dəyəri qaytarır.


Tutaq ki, siz modelin adını ona bəzi atributlar tətbiq edərək ekrana daxil etmək istəyirsiniz. Xəritə "Bəzi atributların tətbiqi" müstəqil funksiya kimi təsvir edildikdə işə düşür:

RAC(self.titleLabel, mətn) = initWithString:modelTitle atributları:atributlar]; )];

Necə işləyir: birləşdirir self.titleLabel.text dəyişikliklərlə model.başlıq ona xüsusi atributlar tətbiq etməklə.

Zip

+ (RACSignal *)zip:(id )axınlar azaldır:(id (^)())reduceBlock;

Nəticə axını hadisələri axınların hər biri bərabər sayda hadisələr yaratdıqda yaradılır. O, 3 birləşmiş axının hər birindən bir dəyərdən ibarətdir.


Bəzi praktik nümunələr üçün zip kimi təsvir edilə bilər göndərmə_qrupu_bildir Məsələn, 3 ayrı siqnalınız var və siz onların cavablarını bir nöqtədə birləşdirmək istəyirsiniz:

NSArray *siqnallar = @; qayıtmaq;

- (RACSignal *)boğaz:(NSTimeInterval)interval;

Müəyyən vaxta təyin edilmiş taymerlə "a" axınının ilk dəyəri yalnız taymerin müddəti bitdikdə nəticə axınına ötürülür. Verilmiş zaman intervalında yeni bir dəyər yaranarsa, o, birinci dəyəri saxlayır və nəticə axınına ötürülməsinin qarşısını alır. Bunun əvəzinə nəticə axınında ikinci dəyər görünür.


Təəccüblü hal: istifadəçi searchField-i dəyişdikdə sorğu axtarmalıyıq. Standart məsələ, elə deyilmi? Bununla belə, mətn hər dəfə dəyişəndə ​​şəbəkə sorğusu qurmaq və göndərmək o qədər də səmərəli deyil, çünki textField saniyədə bir çox belə hadisələr yarada bilər və siz şəbəkədən səmərəsiz istifadə etməklə nəticələnirsiniz.
Burada həll yolu gecikmə əlavə etməkdir, bundan sonra biz həqiqətən şəbəkə sorğusunu edirik. Bu adətən NSTimer əlavə etməklə əldə edilir. ReactiveCocoa ilə hər şey daha asandır!

[[ throttle:0.3] subscribeNext:^(NSString *mətn) ( // şəbəkə sorğusunu yerinə yetirin )];

*Burada vacib qeyd odur ki, bütün "əvvəlki" mətn sahələri "sonuncu"lar silinməzdən əvvəl dəyişdirilir.

Gecikmələr

- (RACSignal *)gecikmə:(NSTimeInterval)interval;

“a” axınında alınan dəyər müəyyən vaxt intervalından sonra gecikir və nəticə axınına ötürülür.


Kimi -, gecikmə yalnız "növbəti" və "başa çatmış" hadisələrin göndərilməsini gecikdirəcək.

[ subscribeNext:^(NSString *mətn) ( )];

Reaktiv Kakao haqqında nəyi sevirik

  • iOS-a Kakao Bağlamalarını təqdim edir
  • Gələcək məlumatlar üzərində əməliyyatlar yaratmaq bacarığı. Scala-dan fyuçers və vədlər haqqında bəzi nəzəriyyələr.
  • Asinxron əməliyyatları sinxron şəkildə təmsil etmək bacarığı. Reaktiv Kakao şəbəkə kodu kimi asinxron proqram təminatını sadələşdirir.
  • Rahat parçalanma. İstifadəçi hadisələri və tətbiq vəziyyəti dəyişiklikləri ilə məşğul olan kod çox mürəkkəb və çaşdırıcı ola bilər. Reaktiv Kakao asılı əməliyyat modellərini xüsusilə sadə edir. Əməliyyatları birləşdirilmiş iplər kimi təqdim etdikdə (məsələn, şəbəkə sorğularının işlənməsi, istifadəçi hadisələri və s.), biz yüksək modulluğa və boş birləşməyə nail ola bilərik, nəticədə daha çox kodun təkrar istifadəsi ilə nəticələnir.
  • Davranışlar və xassələr arasındakı əlaqələr deklarativ olaraq müəyyən edilir.
  • Sinxronizasiya problemlərini həll edir - əgər siz bir neçə siqnalı birləşdirsəniz, bütün nəticələri idarə etmək üçün bir yer var (növbəti dəyər, tamamlama və ya səhv siqnalı)

RAC çərçivəsi ilə siz dəyərlər ardıcıllığını daha yaxşı, daha yüksək səviyyəli şəkildə yarada və çevirə bilərsiniz. RAC asinxron əməliyyatın tamamlanmasını gözləyən hər şeyi idarə etməyi asanlaşdırır: şəbəkənin reaksiyası, asılı dəyərin dəyişməsi və sonrakı reaksiya. İlk baxışdan bununla məşğul olmaq çətindir, lakin ReactiveCocoa yoluxucudur!

Məlumatı yoxlayın. Bu yazıda təqdim olunan faktların düzgünlüyünü və məlumatların etibarlılığını yoxlamaq lazımdır. Müzakirə səhifəsində izahatlar olmalıdır ... Vikipediya

İnteraktivlik obyektlər arasında qarşılıqlı əlaqənin xarakterini və dərəcəsini açıqlayan anlayışdır. Sahələrdə istifadə olunur: informasiya nəzəriyyəsi, kompüter elmləri və proqramlaşdırma, telekommunikasiya sistemləri, sosiologiya, sənaye dizaynı və s. ...... Vikipediyada

Bu məqalə vikiləşdirilməlidir. Zəhmət olmasa, məqalələrin formatlaşdırılması qaydalarına uyğun formatlaşdırın. Bu terminin başqa mənaları var, bax Elektromash (mənalar) ... Vikipediya

xarici psixoterapevtik üsullar- DƏRİN TEXNIKALAR Aktiv psixoterapiya (Fromm Reichmann). Varlığın təhlili (Binswanger). Taleyin təhlili (Sondi). Xarakterlərin təhlili (V. Reyx). Təhlil I (H. Kohut, E. Erickson). Analitik oyun terapiyası (M. Klein). Ailə Analitik Terapiyası (Richter).…… Böyük Psixoloji Ensiklopediya

Kitablar

  • C++ dilində reaktiv proqramlaşdırma. Paralel və Asinxron Tətbiqlərin Dizaynı, Pai Praseed, Abraham Peter. RxCpp kitabxanasından və müasir C ++ 17 istifadə edərək paralel və asinxron proqramların dizaynı Dəstəklənən paralel proqramlaşdırma alətləri Birgə…
  • , Nurkevich T., Christensen B.. Proqramların asinxron olduğu və sürətli cavabın ən vacib xüsusiyyət olduğu bu günlərdə reaktiv proqramlaşdırma daha etibarlı, daha yaxşı miqyaslana bilən və daha sürətli kod yazmağa kömək edəcək.…
  • RxJava, Tomas Nurkevich, Ben Christensen ilə Reaktiv Proqramlaşdırma. Proqramların asinxron olduğu və sürətli cavabın ən vacib xüsusiyyət olduğu bu günlərdə reaktiv proqramlaşdırma sizə daha etibarlı, daha yaxşı miqyaslana bilən və daha sürətli kod yazmağa kömək edəcək.

Ümumilikdə OOP inkişafı dünyası və xüsusilə Java dili çox aktiv həyat sürür. Onun öz moda meylləri var və bu gün biz mövsümün əsas tendensiyalarından birini - ReactiveX çərçivəsini təhlil edəcəyik. Əgər siz hələ də bu dalğadan uzaqsınızsa - söz verirəm ki, bəyənəcəksiniz! Bu, mütləq yüksək belli cins şalvardan yaxşıdır :).

Reaktiv proqramlaşdırma

OOP dilləri kütləvi istifadə üçün yetişən kimi, tərtibatçılar C-bənzər dillərin imkanlarının bəzən nə qədər çatışmadığını başa düşdülər. Funksional proqramlaşdırma üslubunda kod yazmaq OOP kodunun keyfiyyətini və buna görə də layihənin davamlılığını ciddi şəkildə pozduğundan, hibrid icad edilmişdir - reaktiv proqramlaşdırma.

Reaktiv inkişaf paradiqması obyektin vəziyyətindəki dəyişiklikləri daim izləmək fikrinə əsaslanır. Əgər belə dəyişikliklər baş veribsə, onda bütün maraqlı obyektlər artıq yenilənmiş məlumatları almalı və köhnələrini unutmaqla yalnız onlarla işləməlidir.

Reaktiv proqramlaşdırma ideyasının yaxşı nümunəsi Excel elektron cədvəlidir. Bir neçə xananı bir düsturla əlaqələndirsəniz, bu xanalardakı məlumatlar hər dəfə dəyişdikdə hesablamanın nəticəsi dəyişəcək. Mühasibat uçotu üçün məlumatların belə dinamik dəyişməsi adi bir şeydir, lakin proqramçılar üçün bu, daha çox istisnadır.

A=3; b=4; c=a+b; F1(c); a=1; F2(c);

Bu misalda F1 və F2 funksiyaları C dəyişəninin müxtəlif qiymətləri ilə işləyəcək. Çox vaxt hər iki funksiyanın yalnız ən son məlumatlara malik olması tələb olunur - reaktiv proqramlaşdırma sizə dərhal F1-ə yeni ilə zəng etməyə imkan verəcək. funksiyaların özlərinin məntiqini dəyişmədən parametrləri. Bu kod strukturu proqrama istənilən dəyişikliyə dərhal cavab vermək imkanı verir ki, bu da onu sürətli, çevik və həssas edir.

ReactiveX

Reaktiv proqramlaşdırma ideyalarını sıfırdan həyata keçirmək olduqca çətin ola bilər - tələlər var və bu, kifayət qədər vaxt aparacaq. Buna görə də, bir çox tərtibatçılar üçün bu paradiqma ReactiveX ortaya çıxana qədər yalnız nəzəri material olaraq qaldı.

ReactiveX çərçivəsi bütün məşhur OOP dilləri ilə işləyən reaktiv proqramlaşdırma vasitəsidir. Yaradıcıların özləri bunu Observer modelinə əsaslanan asinxron inkişaf üçün çox platformalı API adlandırırlar.

Əgər “reaktiv proqramlaşdırma” termini bir növ nəzəri modeldirsə, Müşahidəçi modeli proqramdakı dəyişiklikləri izləmək üçün hazır mexanizmdir. Və onları tez-tez izləməlisiniz: məlumatların yüklənməsi və yenilənməsi, hadisə bildirişləri və s.

Müşahidəçi nümunəsi təxminən OOP-un özü olduğu müddətdə mövcuddur. Vəziyyəti dəyişə bilən obyekt nəşriyyatçı adlanır (Müşahidə edilə bilən terminin məşhur tərcüməsi). Bu dəyişikliklərdə maraqlı olan bütün digər iştirakçılar abunəçilərdir (Müşahidəçi, Abunəçi). Bildirişləri almaq üçün abunəçilər şəxsiyyət vəsiqələrini açıq şəkildə göstərərək nəşriyyatda qeydiyyatdan keçirlər. Nəşriyyatçı vaxtaşırı bildirişlər yaradır və bu bildirişlər naşir tərəfindən qeydiyyatdan keçmiş abunəçilər siyahısına göndərilir.

Əslində, ReactiveX yaradıcıları inqilabi bir şey ortaya qoymadılar, sadəcə nümunəni rahat şəkildə həyata keçirdilər. Bir çox OOP dillərində, xüsusən də Java-da nümunənin hazır tətbiqləri olsa da, bu çərçivədə "Müşahidəçi"ni çox güclü alətə çevirən əlavə "tənzimləmə" var.

RxAndroid

Android dünyası üçün ReactiveX kitabxanasının portu rxAndroid adlanır və həmişə olduğu kimi Gradle vasitəsilə qoşulur.

"io.reactivex:rxandroid:1.1.0" tərtib edin

Bildirişlər yaradan naşir burada Müşahidə olunan sinifdən istifadə etməklə müəyyən edilir. Bir nəşriyyatın bir neçə abunəçisi ola bilər; onları həyata keçirmək üçün biz Abunəçi sinfindən istifadə edəcəyik. Müşahidə olunan üçün standart davranış abunəçilərə bir və ya daha çox mesaj vermək və sonra çıxmaq və ya xəta mesajı verməkdir. Mesajlar həm dəyişənlər, həm də tam ədədlər ola bilər.

Rx.Observable myObserv = rx.Observable.create(yeni rx.Observable.OnSubscribe () ( @İctimai etibarsız çağırışı ləğv edin (Abunəçisubscriber) ( subscriber.onNext("Salam"); ​​subscriber.onNext("dünya"); subscriber.onCompleted(); ) ));

Bu halda, myObserv naşiri əvvəlcə salam və mesaj sətirlərini, sonra isə müvəffəqiyyət mesajını göndərəcək. Nəşriyyatçı onNext() , onCompleted() və onEror() metodlarına zəng edə bilər, ona görə də abunəçilər onları müəyyən etməlidirlər.

Abunəçi mySub = yeni Abunəçi () (... @Override public void onNext(String value) (Log.e("məlumat əldə etdim", " " + dəyər);) );

Hər şey işə hazırdır. Obyektləri bir-birinə bağlamaq qalır - və "Salam, dünya!" reaktiv proqramlaşdırmada hazırdır!

MyObserv.subscribe(mySub);

Deməliyəm ki, bu çox sadə bir nümunə idi. ReactiveX modelin bütün iştirakçılarının davranışı üçün bir çox varianta malikdir: filtrləmə, qruplaşdırma, səhvlərin idarə edilməsi. Reaktiv proqramlaşdırmanın faydaları yalnız onu hərəkətdə sınamaqla hiss edilə bilər. Gəlin daha ciddi şəkildə tapşırığa keçək.

Davamı yalnız üzvlər üçün əlçatandır

Seçim 1. Saytdakı bütün materialları oxumaq üçün "sayt" icmasına qoşulun

Göstərilən müddət ərzində cəmiyyətə üzvlük sizə BÜTÜN Hacker materiallarına giriş imkanı verəcək, şəxsi məcmu endiriminizi artıracaq və peşəkar Xakep Score reytinqi toplamağa imkan verəcək!

Get.

Reaktiv proqramlaşdırma əvvəlcə yaranan paradiqmanın adı kimi səslənir, lakin əslində asinxron məlumat axınları ilə işləmək üçün hadisəyə əsaslanan yanaşmadan istifadə edən proqramlaşdırma metoduna istinad edir. Daim cari məlumatlara əsaslanaraq, reaktiv sistemlər bir sıra hadisələri həyata keçirməklə onlara reaksiya verirlər.
Reaktiv proqramlaşdırma Observer dizayn modelini izləyir, onu aşağıdakı kimi müəyyən etmək olar: əgər bir obyektdə vəziyyət dəyişikliyi baş verərsə, o zaman bütün digər obyektlər xəbərdar edilir və müvafiq olaraq yenilənir. Beləliklə, dəyişikliklər üçün səsvermə hadisələri əvəzinə hadisələr asinxron olaraq itələnir ki, müşahidəçilər onları emal edə bilsinlər. Bu nümunədə müşahidəçilər hadisə göndərildikdə yerinə yetirilən funksiyalardır. Və qeyd olunan məlumat axını faktiki müşahidə edilə biləndir.

Demək olar ki, bütün dillər və çərçivələr öz ekosistemlərində bu yanaşmadan istifadə edirlər və Java-nın ən son versiyaları da istisna deyil. Bu yazıda Java EE 8 və Java 8 funksionallığında JAX-RS-in ən son versiyasından istifadə edərək reaktiv proqramlaşdırmanın necə tətbiq oluna biləcəyini izah edəcəyəm.

Reaktiv Manifest

Reaktiv Manifest dörd əsas aspekti sadalayır ki, bir tətbiq daha çevik, sərbəst birləşdirilməlidir və miqyası asan olmalıdır və buna görə də reaktiv ola bilər. Tətbiqin cavabdeh, çevik (və buna görə də genişlənə bilən), elastik və mesaj yönümlü olmalıdır.

Əsas məqsəd həqiqətən cavab verən bir tətbiqdir. Deyək ki, istifadəçi sorğularını emal edən bir böyük mövzu olan bir tətbiqiniz var və iş tamamlandıqdan sonra həmin ip orijinal sorğuçulara cavablar göndərir. Tətbiq idarə edə biləcəyindən daha çox sorğu qəbul etdikdə bu axın darboğaza çevrilir və proqram əvvəlki cavab qabiliyyətini itirir. Cavab vermək üçün proqram miqyaslana bilən və davamlı olmalıdır. Dayanıqlı proqram avtomatik bərpa funksiyasına malik proqramdır. Əksər tərtibatçıların təcrübəsində yalnız mesaja əsaslanan arxitektura tətbiqin genişləndirilə bilən, möhkəm və həssas olmasına imkan verir.

Reaktiv proqramlaşdırma Java 8 və Java EE 8-də təqdim edildi. Java dili CompletionStage və onun CompletableFuture tətbiqi kimi anlayışları təqdim etdi və Java bu xüsusiyyətləri JAX-RS-də Reactive Client API kimi spesifikasiyalarda istifadə etməyə başladı.

JAX-RS 2.1 Reaktiv Müştəri API

Gəlin Java EE 8 proqramlarında reaktiv proqramlaşdırmanın necə istifadə oluna biləcəyinə baxaq.Prosesi başa düşmək üçün sizə Java EE API haqqında əsas bilik lazımdır.

JAX-RS 2.1 reaktiv REST müştəri yaratmaq üçün yeni bir üsul təqdim etdi. JAX-RS tərəfindən təklif olunan invokerin standart tətbiqi sinxrondur, yəni yaradılan müştəri serverin son nöqtəsinə bloklama zəngi göndərəcək. Tətbiq nümunəsi Siyahı 1-də verilmişdir.

Cavab cavabı = ClientBuilder.newClient() .target("http://localhost:8080/service-url") .request() .get();
2.0 versiyasından başlayaraq JAX-RS, Siyahı 2-də göstərildiyi kimi, async() metoduna sadə çağırışla müştəri API-də asinxron invoker yaratmağa dəstək verir.

Gələcək cavab = ClientBuilder.newClient() .target("http://localhost:8080/service-url") .request() .async() .get();
Müştəridə asinxron invokerdən istifadə javax.ws.rs.core.Response tipli Gələcək nümunəni qaytarır. Bu, cavab sorğusu ilə, future.get() zəngi və ya mövcud HTTP cavabı olduqda çağırılacaq geri zəngin qeydiyyatı ilə nəticələnə bilər. Hər iki tətbiq asinxron proqramlaşdırma üçün uyğundur, lakin geri çağırışları qruplaşdırmaq və ya asinxron icra minimumlarına şərti hallar əlavə etmək istəyirsinizsə, işlər daha da mürəkkəbləşir.

JAX-RS 2.1 müştəri montajı üçün yeni JAX-RS Reaktiv Müştəri API ilə bu problemləri aradan qaldırmaq üçün reaktiv bir yol təqdim edir. Bu, müştəri qurarkən rx() metodunu çağırmaq qədər sadədir. Siyahı 3-də rx() metodu müştərinin icrası zamanı mövcud olan reaktiv invokeri qaytarır və müştəri CompletionStage.rx() tipli cavab qaytarır ki, bu da sinxron çağırıcıdan sadə ilə asinxron invokerə keçid etməyə imkan verir. zəng edin.

Tamamlama Mərhələsi cavab = ClientBuilder.newClient() .target("http://localhost:8080/service-url") .request() .rx() .get();
Tamamlama Mərhələsi<Т>Java 8-də təqdim edilən yeni interfeysdir. O, adından da göründüyü kimi, daha böyük hesablama daxilində bir addım ola bilən hesablamağı təmsil edir. Bu, onu JAX-RS-ə çevirən yeganə Java 8 reaktivliyidir.
Cavab nümunəsini aldıqdan sonra mən AcceptAsync() funksiyasına zəng edə bilərəm, burada siyahı 4-də göstərildiyi kimi cavab əlçatan olduqda asinxron şəkildə icra olunacaq kod parçasını təqdim edə bilərəm.

Response.thenAcceptAsync(res -> ( Temperatur t = res.readEntity(Temperature.class); //t ilə işləri yerinə yetirin));
REST son nöqtəsinə reaktivliyin əlavə edilməsi

Reaktiv yanaşma JAX-RS-də müştəri tərəfi ilə məhdudlaşmır; server tərəfində də istifadə edilə bilər. Nümunə olaraq, əvvəlcə bir təyinat üçün yerlərin siyahısını tələb edə biləcəyim sadə bir skript yaradacağam. Hər mövqe üçün, temperatur dəyərlərini əldə etmək üçün yer məlumatları ilə başqa bir nöqtəyə ayrıca zəng edəcəyəm. Təyinatların qarşılıqlı əlaqəsi Şəkil 1-də göstərildiyi kimi olacaq.

Şəkil 1. Təyinatlar arasında qarşılıqlı əlaqə

Əvvəlcə yalnız domen modelini, sonra isə hər bir model üçün xidmətləri müəyyənləşdirirəm. Siyahı 5, Yer və Temperatur siniflərini əhatə edən Proqnoz sinifinin necə müəyyən edildiyini göstərir.

İctimai sinif Temperatur ( şəxsi İkiqat temperatur; özəl String miqyası; // alıcılar və təyinçilər ) ictimai sinif Yer (Sətrin adı; ictimai Yer () () ictimai Yer (String adı) ( this.name = ad; ) // alıcılar və təyin edənlər ) ictimai sinif Proqnoz ( şəxsi Yer yeri; şəxsi Temperatur temperaturu; ictimai Proqnoz (Yer yeri) ( this.location = yer; ) ictimai Proqnoz setTemperature (son Temperatur temperaturu) ( this.temperature = temperatur; bunu qaytarın; ) // alıcılar )
Proqnozların siyahısını tamamlamaq üçün ServiceResponse sinfi Siyahı 6-da həyata keçirilir.

İctimai sinif ServiceResponse (şəxsi uzun müddət işləmə müddəti; özəl Siyahı proqnozlar = yeni ArrayList<>(); public void setProcessingTime(uzun emal vaxtı) ( this.processingTime = processingTime; ) public ServiceResponse proqnozları(Siyahı) proqnozlar) ( this.forecasts = proqnozlar; bunu qaytarın; ) // alıcılar )
Siyahı 7-də göstərilən LocationResource , /location yolu ilə qaytarılan üç yer nümunəsini müəyyən edir.

@Path("/location") ictimai sinif LocationResource ( @GET @Produces(MediaType.APPLICATION_JSON) ictimai Cavab getLocations() ( Siyahı yerlər = yeni ArrayList<>(); locations.add(yeni Məkan("London")); locations.add(new Location("İstanbul")); locations.add(yeni Məkan("Praqa")); Response.ok (yeni GenericEntity >(yerlər)()).build(); ) )
Siyahı 8-də göstərilən TemperatureResource , verilmiş yer üçün 30 və 50 arasında təsadüfi yaradılmış temperatur dəyərini qaytarır. Sensor oxunmasını simulyasiya etmək üçün tətbiqə 500 ms gecikmə əlavə edildi.

@Path("/temperature") ictimai sinif TemperatureResource ( @GET @Path("/(city)") @Produces(MediaType.APPLICATION_JSON) ictimai Cavab getAverageTemperature(@PathParam("city") String cityName) ( Temperatur temperaturu = yeni Temperature(); temperatur.setTemperature((ikiqat) (yeni Random().nextInt(20) + 30)); temperatur.setScale("Selsi"); cəhd edin ( Thread.sleep(500); ) tut (InterruptedException nəzərə alınmadı) ( ignored.printStackTrace(); ) qaytarın Response.ok(temperatur).build(); ) )
Əvvəlcə bütün yerləri qaytaran sinxron ForecastResource tətbiqini göstərəcəyəm (Siyahı 9-a baxın). Sonra, hər bir mövqe üçün Selsi dərəcələrində dəyərləri əldə etmək üçün temperatur xidmətini çağırır.

@Path("/forecast") ictimai sinif ForecastResource ( @Uri("yer") şəxsi WebTarget locationTarget; @Uri("temperature/(şəhər)") şəxsi WebTarget temperaturHədəf; @GET @Produces(MediaType.APPLICATION_JSON) ictimai Cavab getLocationsWith () ( uzun startTime = System.currentTimeMillis(); ServiceResponse cavab = yeni ServiceResponse(); Siyahı yerlər = locationTarget .request() .get(yeni GenericType >()()); forEach(yer -> ( Temperatur temperaturu = temperaturHədəf .resolveTemplate("şəhər", yer.getName()) .request() .get(Temperature.class); respond.getForecasts().add(yeni Proqnoz(yer) .setTemperature (temperatur)); )); long endTime = System.currentTimeMillis(); cavab.setProcessingTime(endTime - startTime); Response.ok(cavab).build(); ) )
Proqnoz təyinat yeri /forecast kimi tələb edildikdə, siz Siyahı 10-a bənzər nəticə əldə edəcəksiniz. Qeyd edək ki, sorğunun işlənməsi 1,533 ms vaxt aparıb, bu məntiqlidir, çünki üç fərqli yerdən temperatur tələb etmək sinxron olaraq 1,5 ms-ə qədər əlavə edir.

( "proqnozlar": [ ( "yer": ( "ad": "London" ), "temperatur": ( "miqyas": "Selsi", "temperatur": 33 ) ), ( "yer": ( "ad" ": "İstanbul" ), "temperatur": ( "miqyas": "Selsi", "temperatur": 38) ), ( "yer": ( "ad": "Praqa" ), "temperatur": ( "miqyas" ": "Selsi", "temperatur": 46 ) ) ], "processingTime": 1533 )
Hələlik hər şey plan üzrə gedir. Server tərəfində reaktiv proqramlaşdırmanın tətbiqi vaxtıdır, burada bütün yerlər qəbul edildikdən sonra hər yerə paralel olaraq zənglər edilə bilər. Bu, əvvəllər göstərilən sinxron axını aydın şəkildə yaxşılaşdıra bilər. Bu, proqnoz xidmətinin reaktiv versiyasının tərifini göstərən Siyahı 11-də edilir.

@Path("/reactiveForecast") ictimai sinif ForecastReactiveResource ( @Uri("yer") özəl WebTarget locationTarget; @Uri("temperature/(şəhər)") özəl WebTarget temperatureTarget; @GET @Produces(MediaType.APPLICATION_JSON) ictimai etibarsızlıqTemperi (@Suspended final AsyncResponse async) ( long startTime = System.currentTimeMillis(); // CompletionStage yerlərini əldə etmək üçün mərhələ yaradın > locationCS = locationTarget.request() .rx() .get(yeni GenericType >() ()); // Yerlər mərhələsində ayrıca mərhələ yaradaraq, // yuxarıda təsvir olunduğu kimi, proqnozların siyahısını toplayın // bir böyük Tamamlama Mərhələsinin yekun Tamamlama Mərhələsində olduğu kimi > forecastCS = locationCS.thenCompose(yerlər -> ( // Proqnozları əldə etmək üçün mərhələ yaradın // Tamamlama Mərhələ Siyahısı olaraq > forecastList = // Məkanları yayımlayın və hər birini ayrı-ayrılıqda emal edin // locations.stream().map(location -> ( // Yalnız bir şəhərin // temperatur dəyərlərini əldə etmək üçün bir addım yaradın // onun adı ilə yekun Tamamlama Mərhələsi tempCS = temperaturTarget .resolveTemplate("şəhər", yer.getName()) .request() .rx() .get(Temperatur.class); // Sonra // yeri və temperatur dəyərinin qaytarılması ilə proqnoz nümunəsini ehtiva edən CompletableFuture yaradın CompletableFuture.completedFuture(new Forecast(yer)) .thenCombine(tempCS, Forecast::setTemperature); )).toplamaq(Kollektorlar.toList()); // Bütün təqdim olunan tamamlana bilən gələcək obyektlərin // tamamlanmış CompletableFuture.allOf(forecastList.toArray(new CompletableFuture)) olduğu yekun CompletableFuture instansiyasını qaytarın .thenApply(v -> forecastList.stream() .map(CompletionStage::toCompleFuture) ) .map(CompletableFuture::join) .collect(Kollektorlar.toList())); ))) // Proqnozların tam siyahısını // emal vaxtı ilə birlikdə ehtiva edən ServiceResponse nümunəsi yaradın. // Gələcəyini yaradın və proqnozları əldə etmək üçün // forecastCS ilə birləşdirin // və xidmət cavabına daxil edin CompletableFuture.completedFuture(new ServiceResponse()) .thenCombine(forecastCS, ServiceResponse::forecasts) .whenCompleteAsync((cavab, atılan) - > ( answer.setProcessingTime(System.currentTimeMillis() - startTime); async.resume(cavab); )); ) )
Reaktiv tətbiq ilk baxışdan mürəkkəb görünə bilər, lakin yaxından baxdıqdan sonra bunun olduqca sadə olduğunu görəcəksiniz. ForecastReactiveResource tətbiqində mən əvvəlcə JAX-RS Reaktiv Müştəri API-dən istifadə edərək məkan xidmətlərinə müştəri zəngi edirəm. Yuxarıda qeyd etdiyim kimi, bu Java EE 8 üçün əlavədir və sadəcə rx() metodu ilə reaktiv zəng yaratmağa kömək edir.

İndi mən proqnozlar siyahısını toplamaq üçün yerə əsaslanan yeni mərhələ yaradıram. Onlar forecastCS adlı böyük bir tamamlama mərhələsində proqnozların siyahısı kimi saxlanılacaq. Nəhayət, mən yalnız forecastCS istifadə edərək xidmət zənglərinə cavab yaradacağam.

İndi gəlin proqnozları forecastList dəyişənində müəyyən edilmiş tamamlama mərhələlərinin siyahısı kimi toplayaq. Hər bir proqnoz üçün tamamlama mərhələsi yaratmaq üçün mən yer məlumatlarını daxil edirəm və sonra tempCS dəyişənini yaradıram, yenidən JAX-RS Reaktiv Müştəri API-dən istifadə edərək, temperatur xidmətini şəhərin adı ilə çağırıram. Burada müştəri qurmaq üçün solutionTemplate() metodundan istifadə edirəm və bu, mənə şəhərin adını parametr kimi inşaatçıya ötürməyə imkan verir.

Yayımın son addımı olaraq mən CompletableFuture.completedFuture() ünvanına zəng edirəm və parametr kimi yeni Forecast instansiyasına keçirəm. Mən bu gələcəyi tempCS mərhələsi ilə birləşdirirəm ki, təkrarlanan yerlər üçün temperatur dəyərinə malikəm.

Siyahı 11-də CompletableFuture.allOf() metodu tamamlama mərhələlərinin siyahısını forecastCS-ə çevirir. Bu addımı yerinə yetirmək, bütün təchiz edilmiş tamamlana bilən fyuçerslər tamamlandıqda, böyük tamamlana bilən gələcək qaytarır.

Xidmət cavabı ServiceResponse sinifinin nümunəsidir, ona görə də mən tamamlanmış gələcək yaradıram və sonra forecastCS tamamlama mərhələsini proqnozlar siyahısı ilə əlaqələndirirəm və xidmətin cavab müddətini hesablayıram.

Əlbəttə ki, reaktiv proqramlaşdırma yalnız server tərəfini asinxron şəkildə icra etməyə məcbur edir; server sorğuçuya cavab göndərənə qədər müştəri tərəfi blok edəcək. Bu problemi aradan qaldırmaq üçün Server Sent Events (SSEs) mövcud olan kimi qismən cavab göndərmək üçün istifadə edilə bilər ki, hər bir yer üçün temperatur dəyərləri bir-bir müştəriyə göndərilir. ForecastReactiveResource-un çıxışı Siyahı 12-yə bənzəyəcək. Çıxışda göstərildiyi kimi, emal müddəti 515 ms-dir ki, bu da bir yerdən temperatur dəyərlərini əldə etmək üçün ideal icra vaxtıdır.

( "proqnozlar": [ ( "yer": ( "ad": "London" ), "temperatur": ( "miqyas": "Selsi", "temperatur": 49 ) ), ( "yer": ( "ad" ": "İstanbul" ), "temperatur": ( "miqyas": "Selsi", "temperatur": 32 ) ), ( "yer": ( "ad": "Praqa" ), "temperatur": ( "miqyas" ": "Selsi", "temperatur": 45 ) ) ], "processingTime": 515 )
Nəticə

Bu məqalədəki nümunələrdə mən ilk olaraq yer və temperatur xidmətlərindən istifadə edərək proqnozlar əldə etməyin sinxron yolunu göstərdim. Sonra xidmət zəngləri arasında asinxron emal etmək üçün reaktiv yanaşmaya keçdim. Java 8-də mövcud olan CompletionStage və CompletableFuture sinifləri ilə birlikdə Java EE 8-də JAX-RS Reactive Client API-dən istifadə etdikdə, asinxron emal gücü reaktiv proqramlaşdırma vasitəsilə açılır.

Reaktiv proqramlaşdırma sadəcə sinxron modeldən asinxron modeli həyata keçirməkdən daha çox şeydir; yuva qurma mərhələsi kimi anlayışları da sadələşdirir. Nə qədər çox istifadə edilərsə, paralel proqramlaşdırmada mürəkkəb ssenariləri idarə etmək bir o qədər asan olar.

Diqqətinizə görə təşəkkürlər. Həmişə olduğu kimi, şərhlərinizi və suallarınızı salamlayırıq.

Saytın inkişafı üçün bəzi vəsaitləri köçürə və kömək edə bilərsiniz

Sizə miqyaslılıq, nasazlığa dözümlülük və sürətli reaksiya üçün artan tələblərə cavab verən və həm çoxnüvəli mühitlərdə, həm də bulud hesablamalarında əvəzolunmaz olan müasir proqramlaşdırma intizamı haqqında danışmaq, həmçinin bu barədə açıq onlayn kurs təqdim etmək istəyirəm. bir neçə gündən sonra başlayır.

Əgər reaktiv proqramlaşdırma haqqında heç nə eşitməmisinizsə, getməyə hazırsınız. Bu, hadisələrə əsaslanan və asinxron ilə paralelliyi birləşdirən sürətlə inkişaf edən bir intizamdır. Reaktivlik istənilən veb-xidmətə və paylanmış sistemə xasdır və yüksək paralellik dərəcəsinə malik bir çox yüksək performanslı sistemlərin əsasını təşkil edir. Bir sözlə, kursun müəllifləri reaktiv proqramlaşdırmanı funksional proqramlaşdırmanın (daha yüksək səviyyəli funksiyaları olan) aktiv subyektlər tərəfindən mübadilə edilən asinxron məlumat axını ilə əlaqələndirilmiş və təşkil edilmiş paylanmış vəziyyətə malik paralel sistemlərə təbii uzantısı kimi nəzərdən keçirməyi təklif edirlər. aktyorlar.

Daha başa düşülən sözlərlə, bu, Reaktiv Manifestdə təsvir edilmişdir, aşağıda onun əsas müddəalarını yenidən izah edəcəyəm və tam tərcümə Habré-də dərc edilmişdir. Vikipediyada deyildiyi kimi, termin reaktiv proqramlaşdırma uzun müddətdir mövcuddur və müxtəlif dərəcədə ekzotizmin praktik tətbiqinə malikdir, lakin Typesafe Inc.-dən təşəbbüs qrupu olan Reaktiv Manifestin müəlliflərinin səyləri sayəsində bu yaxınlarda inkişaf və yayılması üçün yeni bir təkan aldı. Typesafe funksional proqramlaşdırma cəmiyyətində əla Scala dilinin və inqilabi paralel platforma Akkanın müəllifləri tərəfindən yaradılmış şirkət kimi tanınır. İndi onlar öz şirkətlərini yeni nəsil hazırlamaq üçün nəzərdə tutulmuş dünyanın ilk reaktiv platformasının yaradıcısı kimi yerləşdirirlər. Onların platforması mürəkkəb istifadəçi interfeyslərinin sürətli inkişafına imkan verir və paralel hesablama və çox iş parçacığı üzərində yeni abstraksiya səviyyəsini təmin edir, zəmanətli proqnozlaşdırıla bilən miqyasla onların xas risklərini azaldır. O, Reaktiv Manifestin ideyalarını həyata keçirir və tərtibatçıya bu günün tələblərinə cavab verən proqramları dərk etməyə və yaratmağa imkan verir.

Siz Reaktiv Prinsiplər Kütləvi Açıq Onlayn Kursunda iştirak etməklə bu platforma və reaktiv proqramlaşdırma ilə tanış ola bilərsiniz. Bu kurs Martin Oderskinin "Scala-da Funksional Proqramlaşdırma Prinsipləri" kursunun davamıdır ki, bu kursda 100.000-dən çox iştirakçı iştirak etmiş və dünyada öz iştirakçıları tərəfindən Kütləvi Açıq Onlayn Kurs üçün ən yüksək müvəffəqiyyət dərəcələrindən birini nümayiş etdirmişdir. Scala dilinin yaradıcısı ilə birlikdə yeni kursu .NET altında reaktiv proqramlaşdırma üçün Rx çərçivəsini hazırlamış Erik Meyer və hazırda Typesafe-də Akka inkişaf komandasına rəhbərlik edən Roland Kuhn tədris edir. Kurs reaktiv proqramlaşdırmanın əsas elementlərini əhatə edir və onların miqyaslana bilən və xətalara dözümlü olan hadisəyə əsaslanan sistemlərin dizaynına necə tətbiq olunduğunu göstərir. Təlim materialı qısa proqramlarla təsvir olunur və hər biri proqram layihəsi olan tapşırıqlar toplusu ilə müşayiət olunur. Bütün tapşırıqları uğurla yerinə yetirdikdə iştirakçılar sertifikatlar alırlar (təbii ki, iştirak və sertifikatlar pulsuzdur). Kurs 7 həftə davam edir və bu bazar ertəsi, noyabrın 4-də başlayır. Ətraflı kontur, eləcə də giriş videosu kursun səhifəsində mövcuddur: https://www.coursera.org/course/reactive.

Maraqlanan və ya şübhəsi olanlar üçün Reaktiv Manifestin əsas anlayışlarının qısa xülasəsini təqdim edirəm. Onun müəllifləri son illərdə ərizələrə qoyulan tələblərdə əhəmiyyətli dəyişiklikləri qeyd edirlər. Bu gün proqramlar mobil cihazlardan tutmuş minlərlə çoxnüvəli prosessoru olan bulud qruplarına qədər istənilən mühitdə yerləşdirilir. Bu mühitlər proqram təminatı və texnologiyaya yeni tələblər qoyur. Əvvəlki nəsil arxitekturaları idarə olunan serverlərə və konteynerlərə, əlavə bahalı aparat vasitələri, mülkiyyət həlləri və multithreading vasitəsilə paralel hesablamalar vasitəsilə miqyasına yönəldilmişdir. Hazırda həm istehlakçı, həm də korporativ sənaye mühitlərində getdikcə daha çox yayılmış dörd əsas xüsusiyyətə malik yeni arxitektura hazırlanır. Bu arxitekturaya malik sistemlər bunlardır: hadisələrə əsaslanan, genişlənə bilən, nasazlığa dözümlü (Dayanıqlı) və sürətli reaksiyaya malikdir, yəni. cavab verən (cavab verən). Bu, çox nüvəli və bulud mühitlərində yerləşdirilməyə hazır olan, özünü sağaldan, miqyaslana bilən proqramlar yığını tərəfindən dəstəklənən qüsursuz, real vaxt istifadəçi təcrübəsi təqdim edir. Reaktiv arxitekturanın dörd xarakteristikasının hər biri onları laylı arxitekturalardakı keçidlərdən fərqləndirən bütün texnologiya yığınına aiddir. Onları bir az daha ətraflı nəzərdən keçirək.


Hadisəyə əsaslanan Tətbiqlər asinxron komponent rabitəsini nəzərdə tutur və onların boş birləşmiş dizaynını həyata keçirir: mesajın göndəricisi və qəbuledicisi nə bir-biri haqqında, nə də mesajın ötürülmə metodu haqqında bilməyə ehtiyac duymurlar ki, bu da onlara rabitənin məzmununa diqqət yetirməyə imkan verir. Boş bağlanmış komponentlərin sistemin dayanıqlığını, genişlənməsini və təkamülünü əhəmiyyətli dərəcədə yaxşılaşdırmasına əlavə olaraq, onların qarşılıqlı əlaqəsinin asinxroniyası və bloklanmaması da resursların əhəmiyyətli bir hissəsini azad edə, cavab müddətini azalda və təmin edə bilər. Oənənəvi tətbiqlərdən daha yüksək ötürmə qabiliyyəti. Məhz hadisələrə əsaslanan təbiət sayəsində reaktiv arxitekturanın qalan xüsusiyyətləri mümkündür.

Ölçeklenebilirlik reaktiv proqramlaşdırma kontekstində bu, sistemin yükün dəyişməsinə reaksiyasıdır, yəni. ehtiyac olduqda hesablama qovşaqlarını əlavə etmək və ya buraxmaq qabiliyyəti ilə əldə edilən elastiklik. Aşağı birləşmə, asinxron mesajlaşma və məkan şəffaflığı ilə yerləşdirmə metodu və tətbiq topologiyası yerləşdirmə vaxtı qərarına çevrilir və yükə cavab verən konfiqurasiya və adaptiv alqoritmlərə tabe olur. Beləliklə, kompüter şəbəkəsi ilkin olaraq açıq şəkildə paylanmış təbiətə malik olan tətbiqin bir hissəsinə çevrilir.

səhvlərə dözümlülük reaktiv arxitektura da dizaynın bir hissəsinə çevrilir və bu, onu server ehtiyatı və uğursuzluq vasitəsilə sistemin davamlılığını təmin etmək üçün ənənəvi yanaşmalardan əhəmiyyətli dərəcədə fərqlənir. Belə bir sistemin davamlılığı onun ayrı-ayrı komponentlərin nasazlıqlarına düzgün cavab vermək, bu uğursuzluqları kontekstini onlara səbəb olan mesajlar şəklində saxlamaqla təcrid etmək və bu mesajları başqa bir komponentə ötürmək qabiliyyəti ilə əldə edilir. xətanı idarə edin. Bu yanaşma, sistemin özü vasitəsilə nasazlıqların qeydə alınması, təcrid edilməsi və idarə edilməsi üçün açıq-aydın deklarativ formada tərtib edilmiş uğursuzluqların idarə edilməsi məntiqini ondan ayıraraq, proqramın biznes məntiqini təmiz saxlamağa imkan verir. Bu cür özünü sağaldan sistemləri qurmaq üçün komponentlər iyerarxik qaydada sıralanır və problem onu ​​həll edə biləcək səviyyəyə çatdırılır.

Və nəhayət həssaslıq- sistemin yükündən və nasazlığından asılı olmayaraq istifadəçi daxilinə cavab vermək qabiliyyətidir, belə proqramlar istifadəçini qarşılıqlı əlaqəyə cəlb edir, sistemlə sıx əlaqə hissi yaradır və cari tapşırıqları yerinə yetirmək üçün kifayət qədər avadanlıq yaradır. Həssaslıq təkcə real vaxt sistemlərində deyil, həm də geniş tətbiqlər üçün zəruridir. Üstəlik, uğursuzluq anında belə tez reaksiya verə bilməyən bir sistem xətaya dözümlü hesab edilə bilməz. Cavablılıq müşahidə edilə bilən modellər, hadisə axınları və vəziyyəti bildirən müştərilərdən istifadə etməklə əldə edilir. Müşahidə edilə bilən modellər vəziyyətləri dəyişdikdə hadisələri yayır və istifadəçilər və sistemlər arasında real vaxt rejimində qarşılıqlı əlaqəni təmin edir, hadisə axınları isə bu qarşılıqlı əlaqənin bloklanmayan asinxron çevrilmələr və kommunikasiyalar vasitəsilə qurulduğu abstraksiyanı təmin edir.

Beləliklə, reaktiv tətbiqlər müasir proqram təminatının inkişafının geniş spektrli problemlərinin həllinə balanslaşdırılmış yanaşmanı təmsil edir. Hadisələrə əsaslanan təməl üzərində qurulmuş, onlar miqyaslılığa və nasazlığa dözümlülüyünə zəmanət vermək üçün lazım olan alətləri təmin edir və tam xüsusiyyətli cavab verən istifadəçi təcrübəsini dəstəkləyir. Müəlliflər reaktiv manifestin prinsiplərinə əməl edən sistemlərin sayının getdikcə artacağını gözləyirlər.

Bundan əlavə kurs planını tərcüməsiz verirəm. Bura qədər oxumusunuz və hələ də maraqlanırsınız.

Həftə 1: Funksional proqramlaşdırma prinsiplərinin nəzərdən keçirilməsi: əvəzetmə modeli, ifadələr və onların monadlarla əlaqəsi. For-ifadələrin yeni tətbiqini təqdim edir: təsadüfi dəyər generatorları. Bunun təsadüfi sınaqda necə istifadə oluna biləcəyini göstərir və bu ideyanı həyata keçirən alət olan ScalaCheck haqqında ümumi məlumat verir.

Həftə 2: Funksional proqramlaşdırma və dəyişən vəziyyət. Obyekti dəyişən edən nədir? Bunun əvəzetmə modelinə necə təsir edir. Genişləndirilmiş nümunə: Rəqəmsal dövrə simulyasiyası

Həftə 3: fyuçers. Fyuçersləri başqa monad kimi, for-ifadələri isə konkret sintaksis kimi təqdim edir. Mövzunun bloklanmasının qarşısını almaq üçün fyuçerslərin necə tərtib oluna biləcəyini göstərir. Çarpaz mövzu xətalarının idarə edilməsini müzakirə edir.

4-cü həftə: Reaktiv axın emalı. Axınlar üzərində reaktiv hesablamalar üçün fyuçerslərin ümumiləşdirilməsi. axın operatorları.

5-ci həftə:Aktyorlar. Aktyor Modelini, aktyorları ardıcıllığın əhatə olunmuş vahidləri, asinxron mesaj ötürməsi kimi təqdim edir, müxtəlif mesaj çatdırılma semantikasını (ən çox bir dəfə, ən azı bir dəfə, tam olaraq bir dəfə) və yekun ardıcıllığı müzakirə edir.

Həftə 6: nəzarət. Uğursuzluğun dəqiqləşdirilməsini, iyerarxik nasazlıqların idarə edilməsini, Xəta nüvəsinin nümunəsini, həyat dövrünün monitorinqini təqdim edir, keçici və davamlı vəziyyəti müzakirə edir.

Həftə 7: Söhbət Nümunələri. Aktyorlar arasında danışıq vəziyyətinin idarə edilməsini və axına nəzarət üçün nümunələri, davamlılıq və ya yük balansı üçün mesajların aktyorların hovuzlarına yönləndirilməsini, etibarlı çatdırılmaya nail olmaq üçün qəbulun təsdiqini müzakirə edir.