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

كيفية تجنب مثل هذه الحالات ، ولماذا لا يكون التنفيذ أقل إثارة للاهتمام من تطوير البنية ، وأحيانًا أكثر ، سيتم مناقشته في هذه المقالة.
مقدمة
يمكن استخدام بنية مدروسة بعناية كأساس لمهام التعطل : يصبح تنفيذ كل مكون منفصل بما فيه الكفاية مهمة فرعية منفصلة.
على سبيل المثال ، إذا كان هناك خط أنابيب لمعالجة الطلبات مصمم على نمط الأنابيب والمرشحات ، فستكون المهام الفرعية هي تنفيذ خطوات المعالجة الفردية (لكل خطوة مهمة فرعية خاصة بها) ومهمة فرعية أخرى لربط جميع الخطوات معًا.
على الرغم من أن البنية المدروسة جيدًا والتقسيم إلى مهام فرعية تعطي فكرة عامة عن كيفية إنشاء نظام وتتيح لك تقييم تكاليف العمالة ، فإنها لا تكفي لتنفيذ الخطة. سيوضح وصف المهمة الفرعية ما الذي يجب أن يقوم به المكون ، فقد يحتوي على متطلبات للسرعة واستهلاك الذاكرة ، لكنه لن يقدم إرشادات شاملة حول كيفية القيام بذلك.
الحقيقة هي أن هناك العديد من الخيارات لعمل مكون يلبي المتطلبات المحددة. يعتمد الكثير على كيفية تنفيذه: مرونة الكود ، القابلية للتوسعة ، سهولة الدعم ، إلخ. نقترب من مفهوم تصميم الكود .
مفهوم تصميم الكود
في بعض الأحيان ، يُطلق على تصميم الكود هندسة أو كود منظمة ، وأحيانًا مجرد هندسة. أنا متمسك بمصطلح تصميم الكود لأنه يتناقض مع بنية النظام ويرسم خطًا واضحًا بينهما. لتكون أكثر تحديدا ، والنظر في مثال.
دعنا نقول إننا نعمل على تطوير الواجهة الخلفية للموقع الذي يكتسب شعبية. تجاوز عدد الخوادم بالفعل عدة عشرات ، يتزايد عدد الجمهور ، ونقرر أننا نرغب في جمع تحليلات حول سلوك المستخدم على الموقع: شعبية صفحات الزيارة ، وتيرة استخدام الميزات وفقًا لملف تعريف المستخدم ، إلخ.
ينشأ عدد من المشكلات المعمارية والتكنولوجية: من أين تخزن المقاييس ، وكيفية نقلها عبر الشبكة ، وماذا تفعل إذا كان مخزن المقاييس غير متاح ، وكيف ستسجل خدمة الواجهة الخلفية المقاييس ، إلخ. العمارة تحتاج فقط للإجابة على هذه الأسئلة ، وتحديد مكونات الحل وتعيين المتطلبات لهم.
لنفترض أننا قمنا بتطوير بنية: سوف نستخدم InfluxDB كمقاييس تخزين ونقل عبر الشبكة باستخدام UDP إلى telegraf ، وللتغلب على عدم إمكانية الوصول إلى التخزين ، سنقوم بتخزين المقاييس في كافكا متكررة عبر عدة خوادم. ستذهب جميع المقاييس إلى الخدمة الخلفية -> telegraf -> Kafka -> InfluxDB. لكتابة المقاييس ، قرر الواجهة الخلفية كتابة وحدة نمطية تنفذ وظيفة النقل المتري في telegraf باستخدام UDP.
الوحدة النمطية لتسجيل المقاييس هي مكون منفصل في النظام ، وكتابته هي مهمة فرعية منفصلة يمكن تكليفها للمطور. تحتوي هذه المهمة الفرعية على العديد من الحلول والأسئلة التي يجب الإجابة عليها: سيتم إرسال المقاييس بشكل متزامن أو غير متزامن. كيف سيتم مزامنة الوصول المتزامن لعدة مؤشرات ترابط الخلفية ، ماذا ستكون الفئات / الوظائف الرئيسية.
هذه الأسئلة تتجاوز وصف بنية الحلول ، لكن الإجابات عليها لها عواقب بعيدة المدى. على سبيل المثال ، إذا كان من الواضح أثناء تشغيل أحد الحلول أن حزمة التقنية ليست الأمثل وتحتاج إلى استبدال telegraf بحل بديل ، فلن يسمح التقسيم غير الصحيح للوحدة النمطية إلى فئات بذلك دون إعادة كتابة الوحدة النمطية بالكامل. الإجابات على هذه الأسئلة هي مجال تصميم الكود .
تطوير تصميم الكود هو مرحلة تصميم منفصلة ، تقع بين تطوير بنية النظام والترميز. يتيح لك رسم خط بين الهندسة المعمارية وتصميم الكود تصميم نظام دون مراعاة جميع التفاصيل وتقييم تكاليف العمالة في وقت محدود. من ناحية أخرى ، فإن إبراز تطوير تصميم الكود كمرحلة تنفيذ منفصلة يتيح لك زيادة جودة تنفيذ النظام ، وتخفيض تكلفة التحسينات الإضافية ، وزيادة سهولة الدعم.
إن الحاجة إلى التفكير في تصميم الكود في مرحلة التنفيذ قبل الترميز يجعل التنفيذ مثيرًا للاهتمام : لا يمكن أن تكون مهام تصميم تصميم الكود أقل إثارة للاهتمام من تصميم نظام كامل على مستوى الهندسة المعمارية. وقد عبر بروكس عن هذه الفكرة في الشهر الأسطوري .
بالطبع ، قد لا يكون رسم خط بين الهندسة المعمارية وتصميم الكود أمرًا سهلاً ، دعنا نلقي نظرة فاحصة على هذه المشكلة.
الحدود بين الهندسة المعمارية وتصميم الكود
من الناحية الأيديولوجية ، يكون التصميم المعماري ورموز التصميم على مستويات مختلفة من التصميم: يتم التفكير في الهندسة المعمارية في المرحلة الأولية ، عندما يكون هناك القليل من اليقين ، ويضيف التفكير في تصميم الشفرة التفاصيل. وفقا لذلك ، يتم تنفيذها في نقاط مختلفة في الوقت المناسب: الهندسة المعمارية هي أقرب إلى البداية ، وتصميم الكود أثناء تنفيذ المهام الفرعية.
يعتمد رسم الحدود بين هاتين المرحلتين من التصميم على عدد من العوامل ، وهنا أهمها:
- درجة تأثير المكون على النظام. في بعض الأحيان ، يمكن لجهاز النظام بأكمله أن يعتمد بشكل كبير على جهاز مكونه الفردي. في هذه الحالة ، تحتاج إلى تصميم المكون في مرحلة التطوير المعماري ، وليس في مرحلة التنفيذ.
- وجود واجهة واضحة للمكون. من الممكن عزل تصميم أحد المكونات كمهمة فرعية فقط إذا كان محددًا بوضوح ما يجب أن يفعله هذا المكون وكيف سيتفاعل مع بقية النظام.
- تقديرات واقعية للجهود المبذولة لإكمال المهمة الفرعية. قد تكون المهمة أكبر من أن تتمكن من تقييم تكاليف العمالة بدقة كافية. في هذه الحالة ، من الأفضل تصميم المهمة بمزيد من التفصيل وتقسيمها إلى مهامها الفرعية من أجل تقديم تقييم أكثر ملاءمة لتكاليف اليد العاملة.
هناك العديد من الحالات الخاصة التي يمكنك فيها رسم خط جيد بين التصميم المعماري وتصميم الكود.
المكون لديه API صارمة.
على سبيل المثال ، في ممارستي ، كانت هناك مهمة: تنفيذ واجهة برمجة تطبيقات مأخذ توصيل UNIX لالتقاط / تحرير موارد نظام التشغيل المستخدمة بواسطة البرنامج الخفي الحالي. نشأت هذه المهمة في إطار البنية المختارة للميزة الملحمية الجديدة. ضمن إطار الهيكل ، كان وصف واجهة برمجة التطبيقات (API) رفيع المستوى إلى حدٍ ما ، وتم تصميمه بالتفصيل لاحقًا ، أثناء التنفيذ.
وحدة / فئة مع واجهة معينة
أسهل طريقة لتفويض تصميم جزء من نظام مترابط هي تسليط الضوء على وحدة نمطية أو فئة ، ووصف واجهة والمهام. يجب ألا تكون الوحدة النمطية المخصصة كمهمة فرعية منفصلة كبيرة جدًا. على سبيل المثال ، لا شك أن مكتبة العميل للوصول إلى قاعدة بيانات shard هي وحدة منفصلة ، ولكن سيكون من الصعب تقييم مهمة تنفيذ هذه المكتبة من خلال تكاليف العمالة دون تصميم أكثر تفصيلاً. من ناحية أخرى ، فإن مهمة تنفيذ فئة صغيرة جدًا ستكون تافهة. على سبيل المثال ، إذا نشأت المهمة الفرعية "لتنفيذ وظيفة تتحقق من وجود مجلد معين من خلال مسار محدد" ، عندئذٍ يتم التفكير بوضوح في الهندسة المعمارية بتفاصيل أكثر من اللازم.
مكون صغير ذو متطلبات ثابتة
إذا كان المكون صغيرًا بدرجة كافية وتم تعريف المشكلة التي يحلها بدقة ، فيمكن تقدير تكاليف العمالة للتنفيذ بدقة كافية ، وسيترك تنفيذ المكون نفسه مساحة للتصميم. مثال: عملية تعمل على التاج وحذف الملفات والأدلة القديمة بشكل متكرر في مسار معين.
مضادات
هناك سيناريوهات عندما يكون التوزيع بين التفكير في العمارة والتنفيذ غير صحيح ، حيث تتم مناقشة بعضها أدناه.
كل شيء مصمم بأدق التفاصيل.
تم تصميم المخططات التفصيلية UML ، وتم تحديد توقيع كل طريقة من كل فئة ، تم وصف الخوارزميات لتنفيذ الأساليب الفردية ... وفقًا لهذا الوصف التفصيلي ، يمكنك تنفيذ النظام بشكل أسرع ، حقًا ، لأن كل شيء مُخطط لهذه التفاصيل بحيث لا يوجد مجال للإبداع على الإطلاق ، خذها والقيام بها مكتوب. إذا كان الهدف هو أن يقوم المطور بتشفير ما يقوله له في أسرع وقت ممكن ، إذن ، يمكنك ذلك.
ومع ذلك ، إذا قمت بحفر أعمق قليلاً ، فسيصبح من الواضح عدد من أوجه القصور في تنظيم العمل في هذا السياق. أولاً ، من أجل تصميم كل شيء في مثل هذه التفاصيل ، سيكون عليك قضاء الكثير من الوقت على التصميم نفسه. ما يفكر فيه المطور عادة قبل التنفيذ ، سوف يفكر المهندس المعماري في هذا المخطط: كل التصميم يتحول أقرب إلى بداية المشروع ، مما قد يزيد من مدته. بعد كل شيء ، إذا لم تقسم أعمال التصميم إلى أجزاء ، فلن تكون قادرًا على موازنتها. ثانياً ، إن نقص أعمال التصميم أثناء التنفيذ سيقلل إلى حد كبير من دوافع المطورين: إن القيام بما يقولونه بالضبط يمكن أن يكون مفيدًا للمبتدئين ، ولكن سيشعر المطورون المتمرسون بالملل. ثالثًا ، يمكن لهذا النهج أن يقلل بشكل عام من جودة المخرجات: سيكون النظام ، الذي لا ينقسم إلى مكونات مستقلة بما فيه الكفاية ، أكثر صعوبة في الصيانة والتوسع.
تم تصميم العمارة دائمًا بواسطة مطور واحد ، والباقي الدخان جانبا ندرك فقط
بادئ ذي بدء ، يجب ملاحظة العديد من الحالات عندما يكون ذلك مفيدًا. أولاً ، إنه فريق يضم العديد من المبتدئين والمبرمجين ذوي الخبرة فقط. في هذه الحالة ، لا يتمتع المبتدئون بخبرة كافية لتصميم الهيكل للقيام بهذه المهمة بجودة كافية ، بينما في نفس الوقت ، فإن تنفيذ بنية مدروسة جيدًا سيساعدهم على رفع مستواهم. ثانياً ، هذه مشاريع كبيرة يشارك فيها العديد من الفرق. ثم ينقسم تصميم بنية المشروع إلى مستويين: يفكر المعماري من خلاله ككل ، وكل فريق - بنية المكونات داخل منطقة مسؤوليته.
ولكن النظر في فريق واحد يتكون من المتخصصين ذوي الخبرة الكافية. إذا تم تعيين المهام المعمارية دائمًا لمطوّر واحد فقط ، على سبيل المثال ، المطور الأكثر خبرة ، فلن يتمكن المطورين الآخرون من الكشف عن قدراتهم بشكل كامل. ستكون بنية النظام من جانب واحد ، لأن كل شخص لديه مجموعة من التقنيات التي يطبقها. إذا فكر مطورو مختلفون في بنية المكونات / النظم الفرعية المختلفة ، فسيسهل ذلك تبادل الخبرات وتطوير أعضاء الفريق. في بعض الأحيان ، يجب عدم تكليف أعضاء الفريق من ذوي الخبرة بالمهام المعمارية: سيؤدي ذلك إلى رفع مستواهم وزيادة مشاركتهم في المشروع.
الخاتمة
يعد وجود مرحلة التصميم في التنفيذ هو العامل الرئيسي الذي يجعل مهام التنفيذ ممتعة. بالطبع ، هناك طرق أخرى: استخدام التقنيات الجديدة ، ومهام البحث ، لكنها ، كقاعدة عامة ، أقل شيوعًا. إذا كانت مهام التنفيذ لا تتطلب تصميمًا وستتضمن ترميزًا بسيطًا ، فسيؤثر ذلك إلى حد كبير على تحفيز المطورين ولن يسمح باستخدام مهاراتهم.
يتيح لك تصميم تصميم الكود في مرحلة التنفيذ إجراء تقديرات كافية لتكاليف العمالة بسرعة ، وموازنة العمل بشكل أكثر كفاءة ، وتحسين جودة النظام بشكل عام.
إن الحاجة إلى تصميم رمز تصميم أثناء التنفيذ هو بالضبط ما يجعل التنفيذ مثيرًا للاهتمام في نظر المطورين.
لا يستحق ارتكاب الأخطاء ، باستثناء أعمال التصميم من تنفيذ المهام الفرعية ، تمامًا كما يجب ألا تكلف دائمًا بالمهام المعمارية للمطور الأكثر خبرة فقط.