XOOPS Geliştirmede Kod Kokuyor
Genel Bakış
Section titled “Genel Bakış”Kod kokuları koddaki olası sorunların göstergeleridir. Bunlar mutlaka kodun bozuk olduğu anlamına gelmez, ancak yeniden düzenlemeden yararlanabilecek alanlar önerirler.
Yaygın Kod Kokuları
Section titled “Yaygın Kod Kokuları”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]Şişiriciler
Section titled “Şişiriciler”Uzun Yöntem
Section titled “Uzun Yöntem”// 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;}Büyük Sınıf (Tanrı Nesnesi)
Section titled “Büyük Sınıf (Tanrı Nesnesi)”// 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 { ... }Uzun Parametre Listesi
Section titled “Uzun Parametre Listesi”// 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 { ... }Nesne Yönelimini Kötüye Kullananlar
Section titled “Nesne Yönelimini Kötüye Kullananlar”Anahtar İfadeleri
Section titled “Anahtar İfadeleri”// 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; }}Geçici Alan
Section titled “Geçici Alan”// 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); }}Önleyicileri Değiştirin
Section titled “Önleyicileri Değiştirin”Iraksak Değişim
Section titled “Iraksak Değişim”// 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() { ... } }Av Tüfeği Ameliyatı
Section titled “Av Tüfeği Ameliyatı”// 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')); }}Vazgeçilebilenler
Section titled “Vazgeçilebilenler”Ölü Kod
Section titled “Ölü Kod”// 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);}Yinelenen Kod
Section titled “Yinelenen Kod”// 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); }}Bağlayıcılar
Section titled “Bağlayıcılar”Özellik Kıskançlığı
Section titled “Özellik Kıskançlığı”// 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; }}Yeniden Düzenleme Kontrol Listesi
Section titled “Yeniden Düzenleme Kontrol Listesi”Bir kod kokusu fark ettiğinizde:
- Tanımlayın - Ne kokusu?
- Değerlendirin - Etki ne kadar ciddi?
- Plan - Hangi yeniden düzenleme tekniği uygulanır?
- Test - Yeniden düzenlemeden önce testlerin mevcut olduğundan emin olun
- Yeniden Düzenleme - Küçük, artan değişiklikler yapın
- Doğrula - Her değişiklikten sonra testleri çalıştırın
İlgili Belgeler
Section titled “İlgili Belgeler”- Temiz Kod İlkeleri
- Kod Organizasyonu
- En İyi Uygulamaların Test Edilmesi