تطوير BPM ليس بالأمر السهل. هذا يرجع إلى حقيقة أن العملية يجب أن تكون قابلة للقراءة ومفهومة للعميل ، وليس صحيحة من الناحية الفنية فقط.
لا تسمح لك كل أدوات تطوير العمليات التجارية بإيجاد حل وسط بين الوصف الواضح والوظائف الفنية. غالبًا ما يكون للعديد من أدوات التطوير المتقدمة وأوصاف العملية عيب واحد آخر: فهي قوية وقوية ومعقدة إلى حد كبير ، في حين تم صنعها ، اتخذت التقنيات خطوة كبيرة إلى الأمام وأصبح التطوير باستخدام هذه الأداة غير ذي صلة.
2018 غيرت بشكل جذري نهجنا في تطوير العمليات التجارية. فيما يلي حول كيفية تطور هذا النهج وكيف تغيرنا.
بدلا من مقدمة
يشارك قسمنا في تطوير العمليات التجارية - من الأصغر والأصغر إلى الكبير والمربح للغاية. حتى وقت قريب ، استخدمنا منتجًا من شركة IBM للتطوير ، مما يسمح لنا بإطلاق عملية أعمال في الإنتاج بسرعة.
يعد IBM BPM نظامًا أساسيًا قويًا يشتمل على مجموعة غنية من الميزات ، مثل وصف العمليات نفسها ونماذج واجهة المستخدم ووحدات التكامل. بالإضافة إلى ذلك ، يحتوي هذا النظام الأساسي على عتبة دخول منخفضة إلى حد ما ، مما يتيح للمطورين المبتدئين الانغماس على الفور في المشروع. لكن لهذا المنتج أيضًا عيوب ، إذا لم تمنع التطوير ، فلا تسهم بالتأكيد في السرعة والجودة:
- لا يوجد تحكم عاقل في الإصدار. لا يوفر IBM BPM ببساطة القدرة على تخزين العمليات (الكود) بشكل صحيح في المستودع ويستخدم مستودع التخزين الخاص به ، والذي لا يعرف عن مفهوم مثل الدمج ، على سبيل المثال.
- التطوير في Java 6. ربما في وقت كتابة هذا التقرير ، من الممكن بالفعل تطويره في Java 7 ، لكن في عام 2019 كان هذا مريحًا إلى حد ما.
- يقوم IBM BPM بالدوران على WebSphere ، ونتيجة لذلك ، يحتاج المطورون إلى التحلي بالصبر مع كل تحديث لوحدتهم. بالإضافة إلى ذلك ، يعد هذا صداعًا إضافيًا للمسؤولين الذين يضطرون بشكل دوري إلى إعادة هذا الوحش إلى الحياة في حالة تعليقه.
- تطوير وحدات التكامل في بيئة Integration Designer ، والتي في الواقع غير محجوبة ليس من أجل Eclipse الأفضل.
- لا توجد قدرة طبيعية على اختبار الوحدة.
- التكلفة العالية للمنصة.
خلقت هذه العيوب ، بالإضافة إلى الإزعاج التقني البحت للتنمية ، مشكلة أخرى ، والتي ربما تكون أكثر خطورة من كل ما سبق. في أيام Java 12 و Kotlin و microservices وغيرها من اتجاهات الموضة والقطع ، كل هذه الفروق الدقيقة تقلل من أهمية الفريق. من الصعب تجربة فرحة التطوير في Integration Designer المتواصل باستمرار لـ Java 6 في 2019.

مع كل هذه القيود ، من الصعب البقاء واقفا على قدميه. قبل أقل من عام بقليل ، كان هناك عرض لتجربة محرك Camunda لوصف العمليات التجارية. بادئ ذي بدء ، تم اختيار عملية ليست كبيرة جدًا ولكنها مهمة لتسجيل المحطات الطرفية للكيانات القانونية.
نظرًا لأننا أعادنا صياغتها بالكامل ، لم يكن هناك أي كود قديم تقريبًا ، لم نكن نستطيع عملياً تقييد أنفسنا بأي شيء ، وبالتالي اخترنا Kotlin كلغة تطوير. كان من المثير للاهتمام تجربة هذه اللغة الجديدة ، والتي كان يسمع معظمها عن المراجعات الإيجابية. في بعض المشاريع الأخرى في قسمنا ، كانت هناك تجربة تنفيذ ناجحة. تحول المكدس النهائي إلى مثل هذا: Camunda، Spring Boot 2، Kotlin، Postgre.
ما هو كاموندا؟

Camunda هي عبارة عن منصة لنمذجة العمليات التجارية مفتوحة المصدر ومكتوبة بلغة Java وتستخدم Java كلغة تطوير. إنها مجموعة من المكتبات التي تسمح لك بإجراء العمليات الموصوفة. لدمج Camunda في المشروع ، ما عليك سوى إضافة بعض التبعيات. لتخزين العمليات ، يمكنك اختيار الذاكرة في نظام إدارة قواعد البيانات أو المستمر - حسب المهام. اخترنا Postgre ، لأن القصة مهمة بالنسبة لنا "لاستخلاص المعلومات". افتراضيًا ، يتم نشر النظام الأساسي إلى H2.
يتكون التطوير من جزأين: إنشاء عملية تدفق في أداة Camunda Modeler خاصة وكتابة تعليمات برمجية java تعالج خطوات العملية الموضحة في الرسم التخطيطي. من أجل استدعاء رمز java من العملية ، يكفي تنفيذ واجهة JavaDelegate ، ورفع Bean (يمكنك تحديد delagate بالاسم الكامل ، ولكن من خلال Bean يكون أكثر ملاءمة ومرونة) في السياق وتحديد معرفه في خطوة العملية المطلوبة. في Kotlin ، يبدو المندوب أكثر إيجازًا. منطق المندوبين بسيط للغاية: لقد طرحوا شيئًا ما من السياق ، وقاموا ببعض الإجراءات وأعادوه إلى السياق.
نافذة منبثقة Camunda Modelerمثال على تفويض Java:
import org.camunda.bpm.engine.delegate.DelegateExecution; import org.camunda.bpm.engine.delegate.JavaDelegate; public class JavaExampleDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { String someVar = (String) execution.getVariable("someVariable");
مثال مندوب Kotlin:
import org.camunda.bpm.engine.delegate.DelegateExecution import org.camunda.bpm.engine.delegate.JavaDelegate class KotlinExampleDelegate: JavaDelegate { override fun execute(execution: DelegateExecution) { val someVar = execution.getVariable("someVariable")
في المفوض ، يمكنك وصف منطق العمل والتكامل وكل ما يرغب به قلبك.
نحاول إنشاء طبقة في شكل مكون أعمال مع المنطق ، واستخدام المفوض فقط كرابط لتدفق العملية ، وذلك لخلط الكود والعملية بأقل قدر ممكن.
في معظم الحالات ، هذا النهج مناسب ويعمل بنجاح. يحدث التفاعل مع العملية من خلال DelegateExecution ، والذي يسمح ، على سبيل المثال ، بالعمل مع السياق والحوادث وما إلى ذلك.
هل هذا ما أردنا؟
في البداية ، عند اختيار أداة ، كنا نبحث عن حل مع الميزات التالية:
- استعادة العملية بالضبط من المكان الذي حدث فيه الفشل ، ومن المستحسن أن يكون خارج الصندوق.
- بعض واجهة المستخدم الرسومية حيث يمكنك رؤية ما يحدث لهذه العملية بشكل عام.
- تختبر القدرة على كتابة الوحدة ليس فقط للمنطق والتكامل ، ولكن أيضًا للعملية نفسها.
- جافا 8 وما فوق.
- المجتمع المتطور.
كاموندا على ما يرام مع استرداد الخطأ والتحليل.
تتبع يمكن قراءته جيدًا ، والقدرة على تعيين عدد محاولات اتخاذ خطوة قبل السقوط ، معالج مخصص عند السقوط - على سبيل المثال ، إذا كنا نريد خلال حالة السقوط تغيير حالة بعض الكيان إلى خطأ. هذا الأخير من السهل القيام به فقط عن طريق تطبيق DefaultIncidentHandler. صحيح ، هناك لحظة مضحكة عندما يعمل هذا المعالج: يتم تشغيل رمز استرداد الأخطاء في كل مرة تدخل فيها خطوة العملية. لا أستطيع أن أقول أن هذا خلل أو مشكلة. بدلا من ذلك ، تحتاج فقط إلى تذكر هذا والنظر في ذلك عند تطوير.
نحن حلها مثل هذا:
override fun resolveIncident(context: IncidentContext) { val incidentList = Context.getCommandContext().incidentManager.findIncidentByConfiguration(context.configuration) if (incidentList.isNotEmpty()) {
Camunda لديه واجهة المستخدم الرسومية وليس سيئا.
ولكن إذا كنت تريد أكثر من ذلك بقليل ، على سبيل المثال ، ترحيل الحالات بين إصدارات العمليات ، فسيتعين عليك العمل بجد. لا تحتوي واجهة المستخدم الافتراضية إلا على الحد الأدنى من الوظائف ، ولكن هناك واجهة برمجة تطبيقات Rest API قوية جدًا تتيح لك إنشاء لوحة المشرف الخاصة بك - رائعة ومتطورة.
لقد ذهبنا على طريق لوحة المشرف الخاصة بنا. لقد رأى مهندس العمليات التجارية لدينا في وقت قصير إلى حد ما ، بما في ذلك وظائف عرض تاريخ العمليات المنجزة بالفعل ، والانتقال بين الإصدارات ، وهلم جرا.
تعتبر Camunda's Rest قوية حقًا وتتيح لك القيام بأي شيء يتعلق بالعمليات. على سبيل المثال ، يمكنك بدء عملية باستخدام
/ process-definition / key / aProcessDefinitionKey / start بمثل هذا الطلب البسيط:
{ "variables": { "aVariable" : { "value" : "aStringValue", "type": "String" }, "anotherVariable" : { "value" : true, "type": "Boolean" } }, "businessKey" : "myBusinessKey" }
المثال مأخوذ من الوثائق الرسمية التي تحتوي على وصف شامل للحالات المختلفة لاستخدام واجهة برمجة التطبيقات هذه.
لاختبار وحدة ، نستخدم Junit المعتادة. بالإضافة إلى وجود مكتبة مثيرة للاهتمام إلى حد ما لاختبار العملية نفسها - 'org.camunda.bpm.extension' ، الاسم: 'camunda-bpm-assert'. مع ذلك ، يمكنك وصف الاختبارات للتحقق من عملية التدفق.
هذا مناسب تمامًا ، لأنه غالبًا ما يكون من الصعب البحث عن مشاكل الأخطاء في التدفق مقارنةً بالكود. يحمي هذا الاختبار ، على سبيل المثال ، من إعادة البناء غير الدقيق وساعدنا حقًا عدة مرات.
اختفت الحاجة إلى Java 8 جزئيًا ، لأن استخدام Kotlin في العديد من العمليات أدى إلى إلغاء الحاجة إلى G8. يتوافق Kotlin بشكل جيد مع المشروع ويسمح لك بالتركيز فقط على كتابة منطق العمل. من الصعب تصديق ذلك ، لكن كل ما تقوله Kotlin عن البرودة حقيقي. لا تبدو الكيانات التي تحتوي على عدد كبير من الحقول ، والتي تُعرف بجميع التطبيقات تقريبًا تقريبًا ، مخيفة جدًا ، وأصبحت التعيينات بين الكيانات أكثر قابلية للقراءة. في كثير من الأحيان انتقد سلامة فارغة لا يعمل حقا ويساعد في معظم الحالات.
تم تطوير المجتمع في Camunda تمامًا. يتضح هذا من خلال حقيقة أن المكتبات الجديدة على جيثب تظهر باستمرار للاختبار والمقاييس.
من الجميل أن تتكامل Camunda بشكل مثالي مع Spring. أضف التبعيات اللازمة ، واثنين من التعليقات التوضيحية واثنين من فاصوليا التكوين - في الواقع ، هذا هو كل التكامل! نتيجة لذلك ، نكتب تطبيقًا ربيعيًا معتادًا عليه ، مضيفًا تدفق عملية تجارية. يحدث التفاعل من خلال Java API ، والذي يسمح لك بمعالجة العمليات من كود java.
على سبيل المثال ، يمكنك بدء العملية بأمر واحد فقط:
runtimeService.startProcessInstanceByKey( "MyTestProcess", "MyBusinessKey", mapOf( "key1" to "value1", "key2" to "value2", ) )
هنا MyTestProcess هو معرف shnik العملية ، وليس المثيل. MyBusinessKey هو مفتاح فريد لمثيل عملية التشغيل. نستخدم عادةً بعض قيمة الأعمال لهذا الحقل - للتنقل بشكل أسرع بين المثيلات والبحث.
بنفس الطريقة تقريبًا ، يمكنك أن تستيقظ من عملية "نعسان".
السلبيات الملحوظة أو أي مشاكل واجهناها ، خاصة لا يمكن التذكير بها. نتيجة لذلك ، لفترة قصيرة إلى حد ما ، اتضح أنها عملية تعمل بالكامل وتنتجها بأمان. يتم تنفيذ عمليات أخرى على النظام الأساسي بنجاح كبير. الآن على Camunda أطلقنا حوالي 15 تطبيقًا تدور حولها حوالي 100 ألف عملية في وقت واحد.

بدلا من خاتمة
فيما يلي بعض الموارد التي ساعدت في تنفيذ المكدس الموضح أعلاه. أوصي بأن تقرأها إذا كنت مهتمًا بمعلومات إضافية حول الموضوع.