روائح الكود في تطوير XOOPS
نظرة عامة
Section titled “نظرة عامة”روائح الكود هي مؤشرات على المشاكل المحتملة في الكود. فهي لا تعني بالضرورة أن الكود معطل، لكنها تشير إلى مناطق يمكن أن تستفيد من إعادة الهيكلة.
روائح الكود الشائعة
Section titled “روائح الكود الشائعة”flowchart TD A[تم اكتشاف رائحة الكود] --> B{النوع؟} B --> C[المنتفخون] B --> D[منتهكو الكائن الموجهة] B --> E[محاربو التغيير] B --> F[الغير ضروريين] B --> G[الموصلات]
C --> C1[طريقة طويلة] C --> C2[فئة كبيرة] C --> C3[قائمة معاملات طويلة]
D --> D1[صيغ تبديل] D --> D2[حقل مؤقت]
E --> E1[تغيير متباعد] E --> E2[جراحة رمح]
F --> F1[كود ميت] F --> F2[كود مكرر]
G --> G1[حسد الميزة] G --> G2[حميمية غير مناسبة]المنتفخون
Section titled “المنتفخون”طريقة طويلة
Section titled “طريقة طويلة”// رائحة: الطريقة تفعل الكثيرfunction processArticleSubmission($data) { // أكثر من 100 سطر من التحقق والحفظ والإخطار إلخ}
// الحل: استخرج إلى طرق مركزةfunction processArticleSubmission(array $data): Article{ $this->validateInput($data); $article = $this->createArticle($data); $this->saveArticle($article); $this->notifySubscribers($article); return $article;}فئة كبيرة (كائن الإله)
Section titled “فئة كبيرة (كائن الإله)”// رائحة: الفئة تفعل كل شيءclass ArticleManager { public function create() { ... } public function delete() { ... } public function sendEmail() { ... } public function generatePDF() { ... } public function exportToExcel() { ... } public function validateUser() { ... } public function checkPermissions() { ... } // ... 50 طريقة إضافية}
// الحل: انقسم إلى فئات مركزةclass ArticleService { ... }class ArticleExporter { ... }class ArticleNotifier { ... }class PermissionChecker { ... }قائمة معاملات طويلة
Section titled “قائمة معاملات طويلة”// رائحة: معاملات كثيرة جداًfunction createArticle($title, $content, $author, $category, $tags, $status, $publishDate, $featured, $image) { ... }
// الحل: استخدم كائن معاملclass CreateArticleCommand { public string $title; public string $content; public int $authorId; public int $categoryId; public array $tags; public string $status; public ?DateTime $publishDate; public bool $featured; public ?string $image;}
function createArticle(CreateArticleCommand $command): Article { ... }منتهكو الكائن الموجهة
Section titled “منتهكو الكائن الموجهة”صيغ التبديل
Section titled “صيغ التبديل”// رائحة: التحقق من النوع مع التبديلfunction getDiscount($userType) { switch ($userType) { case 'regular': return 0; case 'premium': return 10; case 'vip': return 20; default: return 0; }}
// الحل: استخدم تعدد الأشكالinterface UserType { public function getDiscount(): int;}
class RegularUser implements UserType { public function getDiscount(): int { return 0; }}
class PremiumUser implements UserType { public function getDiscount(): int { return 10; }}
class VipUser implements UserType { public function getDiscount(): int { return 20; }}حقل مؤقت
Section titled “حقل مؤقت”// رائحة: الحقول تُستخدم فقط في حالات معينةclass Article { private $tempCalculatedScore;
public function search($terms) { $this->tempCalculatedScore = $this->calculateScore($terms); // ... استخدم الدرجة }}
// الحل: مرر كمعامل أو قيمة إرجاعclass Article { public function getSearchScore(array $terms): float { return $this->calculateScore($terms); }}محاربو التغيير
Section titled “محاربو التغيير”تغيير متباعد
Section titled “تغيير متباعد”// رائحة: فئة واحدة تتغير لأسباب عديدة مختلفةclass Article { public function save() { ... } // تغيير قاعدة البيانات public function toJson() { ... } // تغيير صيغة API public function validate() { ... } // تغيير قواعد الأعمال public function render() { ... } // تغيير الواجهة}
// الحل: افصل المسؤولياتclass Article { ... } // كائن المجال فقطclass ArticleRepository { public function save() { ... } }class ArticleSerializer { public function toJson() { ... } }class ArticleValidator { public function validate() { ... } }جراحة رمح
Section titled “جراحة رمح”// رائحة: التغيير الواحد يتطلب عمليات تحرير ملف عديدة// تغيير صيغة التاريخ يتطلب تحرير:// - ArticleController.php// - ArticleView.php// - ArticleAPI.php// - ArticleExport.php
// الحل: مركزيّةclass DateFormatter { public function format(DateTime $date): string { return $date->format($this->config->get('date_format')); }}الغير ضروريين
Section titled “الغير ضروريين”كود ميت
Section titled “كود ميت”// رائحة: كود غير قابل للوصول أو غير مستخدمfunction processData($data) { if (true) { return $this->handleData($data); } // لا يتنفذ أبداً return $this->legacyHandler($data);}
// الطريقة القديمة غير المستخدمة لا تزال في قاعدة الكودfunction oldMethod() { // لم تُستدعَ في أي مكان}
// الحل: احذف الكود الميتfunction processData($data) { return $this->handleData($data);}كود مكرر
Section titled “كود مكرر”// رائحة: نفس المنطق في أماكن متعددةclass ArticleHandler { public function getActive() { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 'active')); return $this->getObjects($criteria); }}
class NewsHandler { public function getActive() { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 'active')); return $this->getObjects($criteria); }}
// الحل: استخرج السلوك المشتركtrait ActiveRecordsTrait { public function getActive(): array { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 'active')); return $this->getObjects($criteria); }}الموصلات
Section titled “الموصلات”حسد الميزة
Section titled “حسد الميزة”// رائحة: الطريقة تستخدم بيانات الكائن الآخر أكثر من بيانات الكائن الخاص بهاclass Invoice { public function calculateTotal(Customer $customer) { $total = 0; foreach ($this->items as $item) { $total += $item->price; } // استخدم بيانات العميل بشكل مكثيف if ($customer->isPremium()) { $total *= (1 - $customer->getDiscountRate()); } if ($customer->getCountry() === 'US') { $total *= 1.08; // الضريبة } return $total; }}
// الحل: انقل السلوك إلى الكائن الذي يحتوي على البياناتclass Customer { public function applyDiscount(float $amount): float { return $this->isPremium() ? $amount * (1 - $this->discountRate) : $amount; }
public function applyTax(float $amount): float { return $this->country === 'US' ? $amount * 1.08 : $amount; }}قائمة التحقق من إعادة الهيكلة
Section titled “قائمة التحقق من إعادة الهيكلة”عند اكتشاف رائحة الكود:
- تحديد - ما نوع رائحة الكود؟
- تقييم - ما مدى تأثير الأثر؟
- خطة - ما تقنية إعادة الهيكلة المطبقة؟
- اختبر - تأكد من وجود الاختبارات قبل إعادة الهيكلة
- أعد الهيكلة - اجعل تغييرات صغيرة وتدريجية
- تحقق - قم بتشغيل الاختبارات بعد كل تغيير
الوثائق ذات الصلة
Section titled “الوثائق ذات الصلة”- Clean Code Principles
- Code Organization
- Testing Best Practices