Kod Bau dalam Pembangunan XOOPS
Gambaran KeseluruhanBau kod ialah penunjuk kemungkinan masalah dalam kod. Mereka tidak semestinya bermaksud kod itu rosak, tetapi mereka mencadangkan kawasan yang boleh mendapat manfaat daripada pemfaktoran semula.## Bau Kod Biasa
Section titled “Gambaran KeseluruhanBau kod ialah penunjuk kemungkinan masalah dalam kod. Mereka tidak semestinya bermaksud kod itu rosak, tetapi mereka mencadangkan kawasan yang boleh mendapat manfaat daripada pemfaktoran semula.## Bau Kod Biasa”mermaidflowchart 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]Kembung perut### Kaedah Panjang
Section titled “Kembung perut### Kaedah Panjang”php// 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;}Kelas Besar (Objek Tuhan)
Section titled “Kelas Besar (Objek Tuhan)”php// 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 { ... }Senarai Parameter Panjang
Section titled “Senarai Parameter Panjang”php// 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 { ... }Penyalahguna Orientasi Objek### Pernyataan Tukar
Section titled “Penyalahguna Orientasi Objek### Pernyataan Tukar”php// 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; }}Medan Sementara
Section titled “Medan Sementara”php// 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); }}Pencegah Perubahan### Perubahan Bercapah
Section titled “Pencegah Perubahan### Perubahan Bercapah”php// 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() { ... } }Pembedahan Senapang patah
Section titled “Pembedahan Senapang patah”php// 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')); }}Dispensable### Kod Mati
Section titled “Dispensable### Kod Mati”php// 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);}Kod Pendua
Section titled “Kod Pendua”php// 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); }}Pasangan### Ciri Dengki
Section titled “Pasangan### Ciri Dengki”php// 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; }}Senarai Semak Pemfaktoran SemulaApabila anda melihat bau kod:1. Kenal pasti - Apakah bau itu?
Section titled “Senarai Semak Pemfaktoran SemulaApabila anda melihat bau kod:1. Kenal pasti - Apakah bau itu?”- Menilai - Sejauh manakah kesannya?
- Pelan - Apakah teknik pemfaktoran semula yang digunakan?
- Ujian - Pastikan ujian wujud sebelum pemfaktoran semula
- Refactor - Buat perubahan kecil dan berperingkat
- Sahkan - Jalankan ujian selepas setiap perubahan## Dokumentasi Berkaitan- Prinsip Kod Bersih
- Organisasi Kod
- Menguji Amalan Terbaik