کد در توسعه XOOPS بو می دهد
بررسی اجمالی
Section titled “بررسی اجمالی”بوهای کد نشانگر مشکلات احتمالی در کد هستند. آنها لزوماً به این معنی نیستند که کد شکسته شده است، اما مناطقی را پیشنهاد می کنند که می توانند از refactoring سود ببرند.
کد رایج بو می دهد
Section titled “کد رایج بو می دهد”flowchart TD A[Code Smell Detected] --> B{Type?} B --> C[Bloaters] B --> D[Object-Orientation Abusers] B --> E[Change Preventers] B --> F[Dispensables] B --> G[Couplers]
C --> C1[Long Method] C --> C2[Large Class] C --> C3[Long Parameter List]
D --> D1[Switch Statements] D --> D2[Temporary Field]
E --> E1[Divergent Change] E --> E2[Shotgun Surgery]
F --> F1[Dead Code] F --> F2[Duplicate Code]
G --> G1[Feature Envy] G --> G2[Inappropriate Intimacy]نفخ کشان
Section titled “نفخ کشان”روش طولانی
Section titled “روش طولانی”// Smell: Method does too muchfunction processArticleSubmission($data) { // 100+ lines of validation, saving, notification, etc.}
// Solution: Extract into focused methodsfunction processArticleSubmission(array $data): Article{ $this->validateInput($data); $article = $this->createArticle($data); $this->saveArticle($article); $this->notifySubscribers($article); return $article;}کلاس بزرگ (شیء خدا)
Section titled “کلاس بزرگ (شیء خدا)”// Smell: Class does everythingclass ArticleManager { public function create() { ... } public function delete() { ... } public function sendEmail() { ... } public function generatePDF() { ... } public function exportToExcel() { ... } public function validateUser() { ... } public function checkPermissions() { ... } // ... 50 more methods}
// Solution: Split into focused classesclass ArticleService { ... }class ArticleExporter { ... }class ArticleNotifier { ... }class PermissionChecker { ... }لیست پارامترهای طولانی
Section titled “لیست پارامترهای طولانی”// Smell: Too many parametersfunction createArticle($title, $content, $author, $category, $tags, $status, $publishDate, $featured, $image) { ... }
// Solution: Use parameter objectclass 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 “تغییر بیانیه ها”// Smell: Type checking with switchfunction getDiscount($userType) { switch ($userType) { case 'regular': return 0; case 'premium': return 10; case 'vip': return 20; default: return 0; }}
// Solution: Use polymorphisminterface 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 “فیلد موقت”// Smell: Fields only used in certain situationsclass Article { private $tempCalculatedScore;
public function search($terms) { $this->tempCalculatedScore = $this->calculateScore($terms); // ... use score }}
// Solution: Pass as parameter or return valueclass Article { public function getSearchScore(array $terms): float { return $this->calculateScore($terms); }}جلوگیری کننده های تغییر
Section titled “جلوگیری کننده های تغییر”تغییر واگرا
Section titled “تغییر واگرا”// Smell: One class changed for many different reasonsclass Article { public function save() { ... } // Database change public function toJson() { ... } // API format change public function validate() { ... } // Business rule change public function render() { ... } // UI change}
// Solution: Separate responsibilitiesclass Article { ... } // Domain object onlyclass ArticleRepository { public function save() { ... } }class ArticleSerializer { public function toJson() { ... } }class ArticleValidator { public function validate() { ... } }جراحی با تفنگ ساچمه ای
Section titled “جراحی با تفنگ ساچمه ای”// Smell: One change requires many file edits// Changing date format requires editing:// - ArticleController.php// - ArticleView.php// - ArticleAPI.php// - ArticleExport.php
// Solution: Centralizeclass DateFormatter { public function format(DateTime $date): string { return $date->format($this->config->get('date_format')); }}غیر قابل مصرف
Section titled “غیر قابل مصرف”کد مرده
Section titled “کد مرده”// Smell: Unreachable or unused codefunction processData($data) { if (true) { return $this->handleData($data); } // This never executes return $this->legacyHandler($data);}
// Old unused method still in codebasefunction oldMethod() { // Not called anywhere}
// Solution: Remove dead codefunction processData($data) { return $this->handleData($data);}کد تکراری
Section titled “کد تکراری”// Smell: Same logic in multiple placesclass 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); }}
// Solution: Extract common behaviortrait ActiveRecordsTrait { public function getActive(): array { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 'active')); return $this->getObjects($criteria); }}ویژگی حسادت
Section titled “ویژگی حسادت”// Smell: Method uses another object's data more than its ownclass Invoice { public function calculateTotal(Customer $customer) { $total = 0; foreach ($this->items as $item) { $total += $item->price; } // Uses customer data extensively if ($customer->isPremium()) { $total *= (1 - $customer->getDiscountRate()); } if ($customer->getCountry() === 'US') { $total *= 1.08; // Tax } return $total; }}
// Solution: Move behavior to the object with the dataclass 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; }}چک لیست Refactoring
Section titled “چک لیست Refactoring”وقتی بوی کد را تشخیص دادید:
- شناسایی - چه بویی دارد؟
- **ارزیابی ** - تاثیر چقدر شدید است؟
- طرح - چه تکنیک بازسازی مجدد اعمال می شود؟
- آزمایش - از وجود تستها قبل از بازسازی مجدد اطمینان حاصل کنید
- Refactor - تغییرات کوچک و افزایشی ایجاد کنید
- **تأیید ** - تست ها را بعد از هر تغییر اجرا کنید
مستندات مرتبط
Section titled “مستندات مرتبط”- اصول کد پاک
- سازمان کد
- تست بهترین شیوه ها