تاريخ إعادة هيكلة تطبيق Citimobil



قبل أكثر من عام بقليل ، انضممت إلى فريق CityMobil كمطور Android. اعتدت على مشروع جديد لنفسي ، وأساليب وتقنيات جديدة. في ذلك الوقت ، كان لدى Citimobil بالفعل تاريخ طويل إلى حد ما ، مثل المشروع الذي اعتمدته ، وهو تطبيق Android لطلب سيارة أجرة. ومع ذلك ، كما يحدث غالبًا في مثل هذه الحالات ، حمل الرمز الآثار المميزة للحلول القديمة. والآن ، بعد إعادة هيكلة المدونة بنجاح ، أريد مشاركة الأفكار التي ، في رأيي ، يمكن أن تكون مفيدة لأولئك الذين يضطرون إلى إعادة صياغة مشروع قائم. وقبل كل شيء ، يمكن أن يكون مفيدًا للشركات الصغيرة ذات فرق التطوير الصغيرة.

غالبًا ما يختبر النشاط التجاري أفكاره ، ويوجه الموارد المحدودة إليه ، ويحاول الحصول على التعليقات ، واختبار فرضياته في أسرع وقت ممكن. في مثل هذه اللحظات ، كقاعدة ، فإن التفكير عالي الجودة وتنفيذ بنية المشروع ، مع مراعاة المستقبل ، يتلاشى في الخلفية. تدريجيا ، يكتسب المشروع وظائف جديدة ، تظهر متطلبات العمل الجديدة ، وكل هذا يؤثر على قاعدة الكود. "CityMobil" في هذا الصدد لم يكن استثناء. تم تطوير المشروع بشكل تسلسلي من قبل العديد من الفرق في المكتب القديم ، وبعد ذلك ، خلال هذه الخطوة ، تم دعمه وتوافق جزئيًا مع الاستعانة بمصادر خارجية. ثم شرعوا في تشكيل فريق جديد وسلموني العمل في المشروع.

في ذلك الوقت ، انتقلت "التنمية" إلى مكتب موسكو ، وكان العمل على قدم وساق - ظهرت مهام جديدة مثيرة للاهتمام وطموحة باستمرار. ومع ذلك ، وضع الإرث العصي أكثر وأكثر في العجلات ، وبمجرد أن أدركنا أن الوقت قد حان للتغييرات الكبيرة. لسوء الحظ ، لم يتم العثور على الكثير من المؤلفات المفيدة في ذلك الوقت. إنه أمر مفهوم ، ومعروف من الخبرة ، أنه من الصعب إيجاد أو إيجاد الوصفة المثالية التي تعمل في 100٪ من الحالات.

أول شيء يجب فعله هو فهم ما إذا كنت حقًا بحاجة إلى إعادة بيع ديون؟ ينبغي مراعاة ذلك إذا:

  1. سرعة تقديم ميزات جديدة منخفضة بشكل غير معقول ، على الرغم من المستوى العالي من المتخصصين في الفريق.
  2. قد تؤدي التغييرات في التعليمات البرمجية في جزء من البرنامج إلى سلوك غير متوقع في جزء آخر.
  3. تأخر التكيف مع أعضاء الفريق الجدد.
  4. تعرقل عملية اختبار الرمز بواسطة الاتصال القوي.

بعد إدراك وجود مشكلة ، يجب على المرء أن يجد إجابات على الأسئلة التالية:

  1. ما هو الخطأ في الواقع؟
  2. ما الذي أدى إلى ذلك؟
  3. ما الذي يجب فعله لمنع حدوث ذلك مرة أخرى؟
  4. كيف تصلح الوضع؟

يكاد يكون من المستحيل بناء مشروع جيد طويل الأمد دون وضع بنية معينة. في مشروعنا ، قررنا تقديم بنية "الطبقات" ، التي أثبتت نفسها بشكل جيد بالفعل.

في البداية ، تمت كتابة المشروع بشكل أساسي بمساعدة الأدوات التي توفرها Android SDK نفسها. يعمل هذا النهج بلا شك ، لكنه يجبرك على كتابة الكثير من التعليمات البرمجية المتداخلة ، مما يعيق التطور إلى حد كبير. وبالنظر إلى أن الكثير منهم اعتادوا اليوم على بعض مكدسات التكنولوجيا ، فقد استغرق تكييف المطورين الجدد وقتًا أطول. تدريجيا ، توصلنا إلى تقنيات أكثر ملاءمة يعرفها الكثيرون ويقدرونها ، والتي أثبتت موثوقيتها واتساقها:

  • MVP - نمط تصميم واجهة المستخدم (Model-View-Presenter).
  • Dagger 2 هو إطار عمل لتطبيق التبعيات.
  • RxJava2 هو تطبيق ReactiveX - مكتبة لإنشاء برامج غير متزامنة وقائمة على الأحداث باستخدام نمط Observer لـ JVM.
  • Cicerone هي مكتبة تسمح لك بتبسيط التنقل في التطبيق.
  • عدد من المكتبات المحددة للعمل مع الخرائط والمواقع.

من المهم جدًا اعتماد أسلوب رمز مشترك للفريق ، لتطوير مجموعة من أفضل الممارسات. يجب عليك أيضًا الاهتمام بالبنية التحتية والعمليات. من الأفضل كتابة اختبارات للرمز الجديد على الفور ، نظرًا لوجود الكثير من المعلومات حول هذا الموضوع.

داخل الفريق ، بدأنا في إجراء مراجعة الكود بدون فشل ، ولا يستغرق الأمر الكثير من الوقت ، ولكن جودة الكود أصبحت أعلى بكثير. حتى إذا كنت وحيدًا في الفريق ، أوصي بالعمل على Git Flow ، وإنشاء طلبات الدمج والتحقق منها على الأقل.

يمكن تفويض جميع الأعمال "القذرة" إلى CI - في حالتنا ، هذا هو TeamCity باستخدام fastlane. قمنا بتكوينه لبناء فروع الميزات ، وإجراء الاختبارات ، ووضع الاختبار الداخلي. في مكاننا ، قمنا بتكوين التجميعات بشكل منفصل لبيئة الإنتاج / المرحلة ، والميزة - (نطلق عليها اسم رقم المهمة مع القالب TASK # task_number) وفروع الإصدار. وهذا يجعل الاختبار أسهل ، وإذا حدث خطأ ، فنحن نعرف على الفور ما يلزم إصلاحه وأين.

بعد تنفيذ جميع الإجراءات الأولية ، نبدأ العمل. بدأنا حياة جديدة في مشروع قديم من خلال إنشاء حزمة (العمارة النظيفة). من المهم عدم نسيان الاسم المستعار للنشاط عند نقل نقاط الدخول إلى التطبيق (a-la ActivitySplash). إذا أهملت ذلك ، في أفضل الأحوال ، ستفقد الرمز في المشغل ، وفي أسوأ الحالات ، سيتم انتهاك التوافق مع التطبيقات الأخرى.

<!-- android:name=".SplashActivity" - old launcher activity --> <!-- android:targetActivity=".cleanarchitecture.presentation.SplashActivity" - new launcher activity --> <activity-alias android:name=".SplashActivity" android:targetActivity=".cleanarchitecture.presentation.SplashActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity-alias> 

كما تقترح التجربة ، من الأفضل البدء في إعادة الهيكلة بشاشات صغيرة وأجزاء من التطبيق. وبحلول الوقت الذي يحين فيه الوقت لمعالجة الجزء الأكثر تعقيدًا وضخامة من البرنامج ، سيتم كتابة جزء كبير من الشفرة بالفعل للوحدات الأخرى ويمكن إعادة استخدامه.

أيضًا ، كانت لدينا مهمة كبيرة لإعادة تصميم التطبيق بالكامل ، مما أدى في بعض الأحيان إلى إعادة كتابة كاملة للشاشات. بدأنا من خلال تحسين الشاشات المساعدة ، والاستعداد للمضي قدما في الشيء الرئيسي.

بعد إعادة كتابة الجزء التالي من التطبيق ، بحثنا عن أقسام من التعليمات البرمجية في الجزء القديم من التطبيق وقمنا بتمييزها ب @ تعليقات توضيحية ونظائر مماثلة: https://github.com/VitalyNikonorov/UsefulAnnotation . أشرنا فيها إلى ما يجب القيام به عند إعادة كتابة هذا الجزء من البرنامج ، وما هي الوظيفة وأين يتم تنفيذه.

 /** * This class deprecated, you have to use * com.project.company.cleanarchitecture.utils.ResourceUtils * for new refactored classes */ @Deprecated public class ResourceHelper {...} 

بعد أن أصبح كل شيء جاهزًا للعمل على الشاشة الرئيسية ، قرروا عدم إصدار ميزات جديدة لمدة 6-8 أسابيع. قمنا بإعادة الكتابة العالمية في فرعنا ، ثم أضفنا إليها طلبات الدمج. في نهاية إعادة الهيكلة ، تلقوا طلب سحب مطمئن وتطبيق محدث بالكامل تقريبًا.

بعد إعادة الهيكلة ، أصبحت التغييرات في وظائف التطبيق أسهل بكثير. لذلك ، انخرطنا مؤخرًا مرة أخرى في معالجة شاشات الترخيص.

في البداية ، بدوا كما يلي:



بعد المعالجة الأولى وإعادة البناء ، بدأوا في الظهور بهذا الشكل:



الآن يبدون مثل هذا:



ونتيجة لذلك ، استغرق التكرار الأول أكثر من ضعف الوقت الذي استغرقه التكرار الثاني. نظرًا لأنه بالإضافة إلى معالجة واجهة المستخدم ، كان علي أيضًا أن أفهم رمز منطق الأعمال الموجود في نفس المكان ، على الرغم من أن هذا لم يكن ضروريًا ، ولكن تم التخلص من الخلل ، مما قلل من الوقت المستغرق في المهمة في التكرار الثاني.

ماذا لدينا في الوقت الحالي؟

لجعل الكود ملائمًا للاستخدام والتطوير في المستقبل ، نلتزم بمبدأ "العمارة النظيفة". لن أقول أن لدينا تنظيف قانوني ، لكننا اعتمدنا العديد من الأساليب. تتم كتابة طبقة العرض التقديمي باستخدام نمط MVP (Model-View-Presenter).

  • في السابق ، كان علينا مناقشة كل خطوة إلى ما لا نهاية مع بعضنا البعض ، لتوضيح ما إذا كان التغيير في وحدة واحدة يؤثر على وظيفة أخرى. والآن انخفضت النفقات العامة بالمراسلة بشكل ملحوظ.
  • بسبب توحيد المكونات الفردية والشظايا ، انخفض حجم قاعدة التعليمات البرمجية بشكل كبير.
  • نتيجة لنفس التوحيد ومعالجة الهندسة المعمارية ، هناك الكثير من الفئات ، ولكن الآن هناك تقسيم واضح للمسؤوليات فيها ، مما يبسط فهم المشروع.
  • تنقسم قاعدة الكود إلى طبقات ، لفصلها وتفاعلها ، يتم استخدام إطار حقن التبعية Dagger 2. وهذا يقلل من تماسك الكود ويزيد من سرعة الاختبار.

هناك العديد من النقاط الأكثر إثارة للاهتمام المتعلقة بإعادة هيكلة الكود القديم. إذا كان القراء مهتمين ، فسأكتب المزيد عنها في المرة القادمة. سأكون سعيدًا أيضًا إذا شاركت أيضًا تجربتك.

Source: https://habr.com/ru/post/ar416331/


All Articles