مقدمة
يعد تصميم نظام مصرفي حديث عبر الإنترنت مهمة معقدة إلى حد ما. في الوقت نفسه ، يرتبط عدد من المهام لتطوير جزء العميل من التطبيق بعملية معالجة كمية كبيرة من البيانات التي تأتي في وقت واحد تقريبًا من عدة مصادر للمعلومات. يجب تلقي البيانات من النظام المصرفي عن بعد (RBS) وخدمات المراسلة الفورية وخدمات المعلومات المختلفة ومعالجتها في الوقت الفعلي هنا والآن. لحل مشاكل من هذا النوع ، يتم استخدام طرق البرمجة التفاعلية على نطاق واسع اليوم.
يعني مصطلح "البرمجة التفاعلية" بالمعنى الواسع مثل هذه المنظمة للتطبيق ، والتي يحدث فيها نشر التغييرات في النظام نتيجة لمعالجة حالات تدفقات البيانات. تتمثل المشكلات المهمة في هذه الطريقة في بساطة عرض تدفقات المعلومات وإمكانية الاستجابة للأخطاء التي تحدث أثناء المعالجة غير المتزامنة لنتائج العروض التقديمية.
بالمعنى الضيق ، يمكن أن تعني برمجة واجهة الويب التفاعلية رد الفعل استخدام أدوات مطورة جاهزة ، مثل مكتبة RxJs. توفر هذه المكتبة تمثيلاً منفصلاً لتسلسل البيانات باستخدام الكائن القابل للرصد ، والذي يعمل كمصدر للمعلومات التي تدخل التطبيق في فترات معينة.
ضع في اعتبارك ميزات استخدام المكتبة في مثال تصميم واجهة الويب لمصرف عبر الإنترنت للشركات الصغيرة. عند تطوير واجهة المستخدم ، استخدمنا منصة Google Angular 6 مع إصدار مكتبة RxJs المدمج 6.
مهام تصميم واجهة المستخدم التفاعلية
بالنسبة للمستخدم ، غالبًا ما تنخفض معظم العمليات في بنك الإنترنت إلى ثلاث مراحل:
- اختيار العملية اللازمة من القائمة ، على سبيل المثال ، سداد قرض أو تجديد حساب ؛
- إكمال جزئي للنموذج المقابل (يتم ملء تفاصيل الدفع تلقائيًا باسم المؤسسة أو اسم المدفوع لأمره الذي أدخله المستخدم) ؛
- تأكيد آلي للعمليات باستخدام الرسائل النصية القصيرة أو التوقيعات الإلكترونية.
من وجهة نظر المطور ، يتضمن تنفيذ هذه المراحل حل المهام التالية:
- التحقق من حالة نظام المكتب الإقليمي ، وضمان صلة البيانات بالعمليات في القائمة ؛
- معالجة غير متزامنة لتدفقات البيانات عند ملء نموذج ، بما في ذلك البيانات التي أدخلها المستخدم وتلقيها من خدمات رسائل المعلومات (الاسم ورقم التعريف الضريبي و BIC للبنك ، على سبيل المثال) ؛
- التحقق من صحة النموذج المكتمل ؛
- الحفظ التلقائي للبيانات في النموذج.
التحقق من حالة نظام المكتب الإقليمي
تتضمن عملية الحصول على البيانات ذات الصلة من نظام المكتب الإقليمي ، على سبيل المثال ، معلومات حول حد الائتمان أو حالة أمر الدفع ، مرحلتين:
- التحقق من حالة توفر البيانات ؛
- تلقي بيانات محدثة.
للتحقق من الحالة الحالية للبيانات ، يتم تقديم الطلبات إلى واجهة برمجة التطبيقات الخاصة بالنظام خلال فترة زمنية معينة وحتى يتم تلقي رد حول جاهزية البيانات
هناك عدة إجابات محتملة لنظام المكتب الإقليمي:
- {فارغ: صحيح} - البيانات ليست جاهزة بعد ؛
- يمكن للعميل استلام البيانات المحدثة ؛
{ empty: false
ونتيجة لذلك ، يتم استلام البيانات ذات الصلة في شكل:
const MIN_TIME = 2000; const MAX_TIME = 60000; const EXP_BASE = 1.4; request()
دعونا نحلل خطوة بخطوة:
- نرسل طلب. طلب ()
- يذهب الجواب للتوسع. Expand عبارة RxJS التي تكرر الرمز بشكل متكرر داخل الكتلة الخاصة بها لكل تنبيه لاحق للملاحظة الداخلية والخارجية ، حتى يعلن مؤشر الترابط عن اكتماله بنجاح. لذلك ، من أجل استكمال الدفق ، من الضروري إرجاع مثل هذا المرصد بحيث لا يوجد تالي واحد - EMPTY.
- إذا جاء الرد {فارغ: صحيح} ، فإننا نقوم بتقديم طلب ثان بعد تأخير زمني معين (delayTime). حتى لا نفرط في تحميل الخادم بالطلبات ، نقوم بزيادة الفاصل الزمني لـ ping مع كل طلب جديد.
- إذا جاء شيئ آخر خلال الطلب التالي كرد فعل ، فقم بإيقاف ping (إرجاع EMPTY) وإرجاع نتيجة الطلب الأخير إلى المشغل (last ()) المشترك.
- بعد تلقي الإجابة ، نأخذ النتيجة ونعالجها. سيتم إدخال كائن من النموذج في الاشتراك:
{ empty: false
أشكال رد الفعل
ضع في اعتبارك مهمة تصميم نموذج ويب تفاعلي لمستند دفع باستخدام مكتبة ReactiveForms من الإطار الزاوي.
تسمح لك ثلاث فئات أساسية للمكتبة FormControl و FormGroup و FormArray باستخدام وصف تعريفي لحقول النموذج وتعيين القيم الأولية للحقول وتعيين قواعد التحقق لكل حقل:
this.myForm = new FormGroup({ name: new FormControl('', Validators.required),
بالنسبة للنماذج التي تحتوي على عدد كبير من الحقول ، من المعتاد استخدام خدمة FormBuilder ، والتي تسمح لك بإنشائها باستخدام رمز مضغوط أكثر
this.myForm = this.fb.group({ name: ['', Validators.required], surname: '' });
بعد إنشاء النموذج في قالب صفحة أمر الدفع ، يكفي تحديد ارتباط إلى نموذج myForm ، بالإضافة إلى أسماء الحقول واللقب
<form [formGroup]="myForm"> <label>Name: <input formControlName="name"> </label> <label>Surname: <input formControlName="surname"> </label> </form>
يتيح لك التصميم الناتج إنشاء وتتبع أي تدفق للمعلومات يمر عبر حقول النموذج نتيجة لإدخال المستخدم ، واستنادًا إلى منطق الأعمال الخاص بالتطبيق. للقيام بذلك ، ما عليك سوى الاشتراك في الأحداث التي تم إنشاؤها بواسطة المراقب غير المتزامن لنموذج ValueChanges
this.myForm.valueChanges .subscribe(value => { …
افترض أن منطق الأعمال يحدد متطلبات ملء تفاصيل وجهة الدفع تلقائيًا عندما يدخل المستخدم رقم التعريف الضريبي للمستلم أو اسم المؤسسة. سيبدو رمز معالجة البيانات التي أدخلها المستخدم في رقم التعريف الضريبي / اسم المؤسسة كما يلي:
this.payForm.valueChanges .pipe( mergeMap(value => this.getRequisites(value))
التحقق
يأتي المصدقون في شكلين:
نواجه مدققين متزامنين بانتظام - هذه هي الوظائف التي تتحقق من البيانات المدخلة عند العمل مع الحقل. من حيث الأشكال التفاعلية:
"المدقق المتزامن هو وظيفة تأخذ أشكال التحكم وتعيد قيمة صادقة إذا كان هناك خطأ وخطأ بخلاف ذلك."
function customValidator(control) { return isInvalid(control.value) ? { code: "mistake", message: "smth wents wrong" } : null; }
سنقوم بتطبيق مدقق للتحقق مما إذا كان المستخدم قد أشار في النموذج إلى سلسلة من الوثائق ، إذا كان جواز السفر موضحًا مسبقًا كنوع مستند التعريف:
function requredSeria(control) { const docType = control.parent.get("docType"); let error = null; if (docType && docType.value === "passport" && !control.value) { error = { code: "wrongSeria", message: " " } } return error; }
هنا نشير أيضًا إلى النموذج الأصلي ونستخدمه نحصل على قيمة حقل آخر. كان من الممكن العودة فقط كخطأ ، ولكن في هذه الحالة تقرر أن تفعل خلاف ذلك. يمكنك التقاط رسائل الخطأ هذه في حقل الأخطاء لعنصر تحكم أو نموذج. إذا كان الحقل يحتوي على العديد من أدوات التحقق ، فيمكنك تحديد أي من أدوات التحقق التي فشلت في عرض رسالة الخطأ المطلوبة أو ضبط التحقق من صحة الحقول الأخرى.
ستتم إضافة المصدق إلى النموذج كما يلي:
this.documentForm = this.fb.group({ docType: ['', Validators.required], seria: ['', requredSeria], number: '' });
خارج الصندوق ، يتوفر أيضًا العديد من أدوات التحقق الشائعة. يتم تمثيلهم جميعًا بطرق ثابتة من فئة Validators. هناك أيضًا طرق لإنشاء المدققين.
يؤدي عدم صحة حقل واحد على الفور إلى بطلان النموذج بأكمله. يمكن استخدام هذا عندما تحتاج إلى إلغاء تنشيط زر موافق معين ، إذا كان النموذج يحتوي على حقل واحد غير صالح على الأقل. ثم يأتي كل شيء للتحقق من شرط واحد "myform.invalid" ، والذي سيظهر صحيحًا إذا كان النموذج غير صالح.
المدقق غير المتزامن له فرق واحد - نوع القيمة المرتجعة. يجب أن يتم تمرير القيمة الصادقة أو الزائفة في الوعد أو في الملاحظة.
كل عنصر تحكم أو كل نموذج له حالة (mySuperForm.status) ، والتي يمكن أن تكون "VALID" ، "INVALID" ، "DISABLED". نظرًا لأنه عند استخدام أدوات التحقق غير المتزامنة ، فقد لا يكون واضحًا في حالة النموذج في الوقت الحالي ، فهناك حالة خاصة "معلقة". بفضل هذا الشرط (mySuperForm.status === "PENDING") ، يمكنك عرض أداة التحميل المسبق أو عمل أي نمط آخر.
حفظ تلقائي
يتضمن تطوير البرامج المصرفية (البرمجيات) العمل مع وثائق قياسية مختلفة. على سبيل المثال ، هذه نماذج طلبات أو استبيانات ، والتي يمكن أن تتكون من عشرات الحقول المطلوبة. عند العمل مع مثل هذه المستندات الضخمة ، يلزم دعم الحفظ التلقائي لراحة المستخدم الإضافية ، بحيث إذا فقدت اتصالك بالإنترنت أو مشاكل فنية أخرى ، فإن البيانات التي أدخلها المستخدم في وقت سابق تظل في إصدار المسودة على الخادم.
فيما يلي الجوانب الرئيسية لإجراء الحفظ التلقائي لبنية خادم العميل:
- يجب أن يعالج الخادم طلبات الحفظ بالترتيب الذي أجريت به التغييرات. إذا أرسلت طلبًا فورًا إلى كل تغيير ، فلا يمكنك ضمان أن الطلب السابق لن يأتي بعد ذلك ولن يستبدل التغييرات الجديدة.
- ليس من الضروري إرسال عدد كبير من الطلبات إلى الخادم حتى ينتهي المستخدم من الدخول ، ويكفي القيام بذلك عن طريق التوقيت.
- إذا تم إجراء العديد من التغييرات بتأخير كبير نسبيًا ، ولم يتم إرجاع طلب التغييرات الأولى بعد ، فلا داعي لإرسال الطلبات لكل تغيير لاحق فور إرجاع الطلب الأول. يمكنك فقط أخذ الأخيرة ، حتى لا ترسل بيانات غير ذات صلة.
يمكن التعامل مع الحالة الأولى بسهولة باستخدام عامل
concatMap . سيتم حل الحالة الثانية دون أي مشاكل باستخدام
debounceTime . يمكن وصف منطق الثالث على النحو التالي:
const lastRequest$ = new BehaviorSubject(null);
يبقى في saveQueue $ لارسال طلب. لاحظ وجود عامل
exaustMap بدلاً من concatMap. هذا العامل ضروري لتجاهل جميع الإخطارات الخاصة بالملاحظة الخارجية حتى الانتهاء من الملاحظة الداخلية ("المترجمة"). ولكن في حالتنا ، إذا كان هناك قائمة انتظار للإشعارات الجديدة أثناء الطلب ، فيجب أن نتلقى آخر إشعار وأن نتجاهل الباقي. سوف يسقط exaustMap كل شيء ، بما في ذلك الأخير. لذلك ، نقوم بحفظ آخر إشعار في BehaviorSubject ، وفي الاشتراك ، إذا كان الطلب الحالي المكتمل مختلفًا عن آخر طلب ، فسوف نلقي آخر طلب في قائمة الانتظار مرة أخرى.
تجدر الإشارة أيضًا إلى تجاهل الأخطاء أثناء الاستعلامات ، التي يتم تنفيذها باستخدام
عبارة catchError . يمكنك كتابة معالجة خطأ أكثر تعقيدًا مع إشعار للمستخدم بحدوث خطأ أثناء الحفظ. لكن جوهرها هو أنه عند حدوث خطأ في الدفق ، لا ينبغي إغلاق الدفق ، كما هو الحال مع الخطأ والإشعارات الكاملة.
الخلاصة
يسمح لك مستوى تطوير تقنيات البرمجة التفاعلية اليوم باستخدام مكتبة RxJS بإنشاء تطبيقات عملاء كاملة للأنظمة المصرفية عبر الإنترنت دون تكاليف عمل إضافية لتنظيم التفاعل مع واجهات محملة للغاية للأنظمة المصرفية البعيدة.
يمكن للتعارف الأول مع RxJS أن يخيف حتى مطورًا متمرسًا يواجه "تعقيدات" المكتبة التي تطبق نمط التصميم "Observer". ولكن ، ربما للتغلب على هذه الصعوبات ، في المستقبل ، ستصبح RxJS أداة لا غنى عنها في حل مشاكل المعالجة غير المتزامنة لتدفقات البيانات غير المتجانسة في الوقت الحقيقي.