أفضل طريقة التحويل من قالب الفوضى لتنظيف الطبقات المعمارية (C++)?

StackOverflow https://stackoverflow.com/questions/324043

  •  11-07-2019
  •  | 
  •  

سؤال

على افتراض كبير قليلا مكتبة قالب مع حوالي 100 الملفات تحتوي على حوالي 100 قوالب مع العام أكثر من 200 ، 000 خطوط من التعليمات البرمجية.بعض من القوالب استخدام وراثة متعددة لجعل استخدام المكتبة نفسها بسيطة نوعا ما (أيترث من بعض قوالب قاعدة فقط الحاجة إلى تنفيذ بعض الأعمال القواعد).

كل ما هو موجود (نمت على مدى عدة سنوات) ، "الأشغال" و هي المستخدمة في المشاريع.

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

الآن, أود حقا أن تبسيط العمارة إلى استخدام كميات أقل من قوالب وأكثر تخصصا أصغر دروس.

هل هناك أي طريقة مؤكدة أن تذهب عن تلك المهمة ؟ ماذا سيكون مكانا جيدا للبدء ؟

هل كانت مفيدة؟

المحلول

وأنا لست متأكدا من أنني أرى كيف / لماذا القوالب هي المشكلة، والسبب في ذلك الطبقات غير قالب سهل سيكون تحسنا. لا يعني ذلك فقط حتى أكثر الطبقات، وأقل سلامة نوع وحتى أكبر احتمال الخلل؟

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

وانا اقول ان القوالب <م> يحتمل تسمح لك لبناء بنية أنظف بكثير مما كنت تحصل بدونها. ببساطة لأنك يمكن أن تجعل فصول منفصلة <م> تماما مستقلة. دون قوالب، يجب فئات الوظائف التي تدعو إلى فئة أخرى تعرف عن الطبقة، أو واجهة فإنه يرث، مقدما. مع قوالب، وهذا الاقتران ليست ضرورية.

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

وبطبيعة الحال، فإن وأضاف وقت الترجمة قد يكون سببا وجيها لتجنب القوالب في بعض الحالات، وإذا كان لديك فقط مجموعة من المبرمجين جافا، الذين تعودوا على التفكير من حيث OOP "التقليدية"، قوالب قد يربكهم ، التي يمكن أن تكون سببا وجيها آخر لتجنب القوالب.

ولكن من الناحية المعمارية للعرض، وأعتقد أن تجنب القوالب هو خطوة في الاتجاه الخاطئ.

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

نصائح أخرى

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

وبخلاف ذلك، "فرق conqueor"

وحدة كتابة الاختبارات.

وأين القانون الجديد يجب أن تفعل نفس القانون القديم.

وهذا غيض واحد على الأقل.

وتحرير:

إذا انتقص القانون القديم التي قمت استبدال وظائف جديدة لك يمكن التخلص أكثر من القانون الجديد شيئا فشيئا.

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

وبطبيعة الحال، قد يكون هناك طريقة بسيطة لقضية معينة. لا يمكننا أن نقول دون معرفة المزيد حول ما لديك.

والحقيقة أن الحل قالب صعب للغاية للحفاظ على ومؤشرا على سوء التصميم على أي حال.

بعض النقاط (ولكن لاحظ:هذه هي لا الشر في الواقع.إذا كنت ترغب في تغيير غير قالب مدونة, على الرغم من أن هذا يمكن أن تساعد بها):


البحث الخاص بك ثابت واجهات.أين قوالب تعتمد على ما هي الوظائف موجودة ؟ حيث أنها لا تحتاج typedefs?

وضع الأجزاء المشتركة في قاعدة مجردة الدرجة.وخير مثال هو عندما كنت يحدث أن تتعثر CRTP لغة.يمكنك استبدال فقط مع قاعدة مجردة من الدرجة وجود وظائف افتراضية.

بحث عدد صحيح قوائم.إذا كان يمكنك العثور على التعليمات البرمجية يستخدم جزءا لا يتجزأ من القوائم مثل list<1, 3, 3, 1, 3>, يمكنك استبدالها std::vector, لو كل رموز استخدامها يمكن أن يعيش مع العمل مع وقت التشغيل القيم بدلا من المستمر التعبيرات.

البحث نوع السمات.هناك الكثير من التعليمات البرمجية تشارك التحقق من ما إذا كانت بعض الرموز المميزة ل typedef موجود ، أو ما إذا كانت بعض الأسلوب موجود في نموذجي قالب المدونة.مجردة baseclasses حل هذه المسألتين باستخدام نقية طرق افتراضية ، وراثة typedefs إلى القاعدة.في كثير من الأحيان ، typedefs مطلوبة فقط لتحريك البشعة الميزات مثل SFINAE, ثم تكون زائدة أيضا.

البحث قوالب التعبير.إذا كان لديك رمز يستخدم قوالب التعبير لتجنب خلق المؤقتات, سيكون لديك للقضاء عليها و استخدام الطريقة التقليدية العودة / يمر المؤقتات إلى المشغلين المعنيين.

البحث عن وظيفة الكائنات.إذا كان يمكنك العثور على التعليمات البرمجية يستخدم وظيفة الكائنات ، يمكنك تغييرها إلى استخدام مجردة قاعدة الطبقات أيضا ، و يكون شيئا مثل void run(); أن ندعو لهم (أو إذا كنت ترغب في الاستمرار في استخدام operator(), أفضل حتى!ويمكن الظاهري أيضا).

كما أفهم ، كنت أكثر قلقا مع بناء مرات و الصيانة من مكتبتك ؟

أولا, لا محاولة "إصلاح" في كل مرة.

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

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

هو مكتبة حسنا موثق ؟ هذا هو أفضل فرصة في جعل الأمور تبدو في أدوات مثل doxygen أن تساعدك على إنشاء مثل هذه الوثائق.

كل النظر فيها ؟ حسنا, الآن بعض الاقتراحات من أجل بناء مرات؛)


فهم C++ بناء نموذج:كل .cpp يتم تجميعها بشكل فردي.وهذا يعني الكثير .cpp الملفات مع العديد من رؤوس = بناء ضخمة.هذا ليس المشورة لوضع كل شيء في واحد .الملف cpp, على الرغم من!ومع ذلك, خدعة واحدة (!) التي يمكن تسريع بناء هائلة إنشاء واحد .الملف cpp يتضمن مجموعة من .cpp الملفات فقط إطعام أن "سيد" إلى مترجم.لا يمكنك أن تفعل ذلك على نحو أعمى ، على الرغم - تحتاج إلى فهم أنواع الأخطاء وهذا يمكن أن أعرض.

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

استخدام رؤوس precompiled.(المقاييس أفضل مع آلات سريع ، انظر أعلاه)

التحقق من رأس إدراج السياسة.في حين أن كل ملف يجب أن تكون "مستقلة" (أيتشمل كل ما يحتاج إلى تدرج من قبل شخص آخر) لا تشمل تحرري.للأسف, لم يتم العثور حتى الآن على أداة البحث لا لزوم لها #incldue البيانات ، ولكن ذلك قد يساعد على قضاء بعض الوقت في إزالة غير المستخدمة الرؤوس في "نقطة ساخنة" الملفات.

إنشاء واستخدام الإعلانات إلى الأمام القوالب التي يمكنك استخدامها.في كثير من الأحيان ، يمكنك incldue رأس مع forwad الإعلانات في العديد من الأماكن ، واستخدام رأس الكامل إلا في عدد قليل منها محددة.هذا يمكن أن يساعد كثيرا في تجميع الوقت.التحقق <iosfwd> رأس كيفية المكتبة القياسية يفعل ذلك بالنسبة i/o تيارات.

الزائدة عن قوالب عدة أنواع:إذا كان لديك وظيفة معقدة القالب يمكن أن يكون مفيدا فقط لعدد قليل جدا من أنواع مثل هذا:

// .h
template <typename FLOAT> // float or double only
FLOAT CalcIt(int len, FLOAT * values) { ... }

يمكنك أن تعلن الزائدة في الرأس ، نقل القالب إلى الجسم:

// .h
float CalcIt(int len, float * values);
double CalcIt(int len, double * values);

// .cpp
template <typename FLOAT> // float or double only
FLOAT CalcItT(int len, FLOAT * values) { ... }

float CalcIt(int len, float * values) { return CalcItT(len, values); }
double CalcIt(int len, double * values) { return CalcItT(len, values); }

هذه التحركات الطويلة قالب واحد تجميع وحدة.
للأسف, هذا هو فقط من الاستخدام المحدود والطبقات.

تحقق مما إذا كان على PIMPL لغة يمكن أن تتحرك رمز من رؤوس في .cpp الملفات.

القاعدة العامة أن يخفي وراء ذلك هو فصل واجهة المكتبة من تنفيذ.استخدام التعليقات ، detail namesapces منفصلة .impl.h رؤوس عقليا وجسديا عزل ما يجب أن تكون معروفة خارج عن كيفية إنجازه.وهذا يكشف القيمة الحقيقية من المكتبة الخاصة بك (هل فعلا لتغليف التعقيد؟), و يتيح لك فرصة استبدال "أهدافا سهلة" الأولى.


أكثر تحديدا المشورة مدى فائدة واحد معين هو - يعتمد إلى حد كبير على الفعلية المكتبة.

حظا سعيدا!

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

وأبعد من ذلك، أود أن أقترح تطوير الأدوات الخاصة بك، إذا أمكن، للمساعدة في المشاكل المتعلقة قالب التصحيح.

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

وآخر شيء قد ترغب في النظر هو عدد المرات التي تنظيف الهرمية الميراث بجعل القوالب "mixin" أسلوب بدلا من تجمعات من وراثة متعددة. ترى كم عدد الأماكن التي يمكن أن تفلت من صنع واحدة من الحجج قالب اسم الفئة الأساسية التي يجب أن تستمد من (الطريقة التي يعمل boost::enable_shared_from_this). بالطبع هذه عادة لا تعمل إلا بشكل جيد إذا تأخذ منشئات بدون وسائط، كما لم يكن لديك ما يدعو للقلق تهيئة أي شيء بشكل صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top