Code Smells in Magento 2
What Are Code Smells?
Code smells are surface-level indicators of deeper problems. They are not bugs but suggest structural issues.
Common Magento 2 Code Smells
God Classes
// BAD: Class with too many responsibilities
class CatalogProduct implements ProductInterface
{
public function save() { /* 200 lines */ }
public function validate() { /* 150 lines */ }
public function load() { /* 100 lines */ }
public function delete() { /* 80 lines */ }
public function sendEmail() { /* 120 lines */ }
public function generateSku() { /* 90 lines */ }
// ... 30 more methods
}
Long Parameter Lists
// BAD: Constructor with too many dependencies
public function __construct(
LoggerInterface $logger,
Registry $registry,
StoreManagerInterface $storeManager,
ConfigInterface $config,
CacheInterface $cache,
ResourceManager $resourceManager,
EntityManager $entityManager,
EventManager $eventManager,
ComposerInformation $composerInfo,
ProductFactory $productFactory
) {}
Duplicated Code
// Found in multiple classes - copy-paste pattern
public function formatPrice($price)
{
return number_format($price, 2, '.', '');
}
// Magento already has PriceCurrencyInterface for this
Dead Code
// Methods never called anywhere
class LegacyHelper
{
public function oldMethod() { /* unused */ }
public function deprecatedLogic() { /* no callers */ }
private $obsoleteProperty; // never read
}
Feature Envy
// BAD: Method uses more of another class than its own
class OrderProcessor
{
public function process(Order $order)
{
$order->getBillingAddress()->getCity();
$order->getShippingAddress()->getCountryId();
$order->getPayment()->getMethod();
$order->getCustomer()->getEmail();
// ... 20 more $order calls
}
}
Architecture Smells
System-Level Debt Indicators
Circular Dependencies
// Module A depends on Module B
// Module B depends on Module A
// Result: cannot install/remove either independently
// Check with:
php bin/magento dev:module:graph
Over-Coupled Modules
<!-- Module directly depends on specific implementation -->
<type name="Magento\Catalog\Model\Product">
<plugin name="inventory" type="Vendor\Inventory\Plugin\ProductPlugin"/>
</type>
<!-- Better: depend on interface -->
<type name="Magento\Catalog\Api\ProductInterface">
<!-- abstracted dependency -->
</type>
Missing Abstractions
// BAD: Direct instantiation throughout codebase
$order = new \Magento\Sales\Model\Order();
// BETTER: Factory pattern (already in Magento)
$order = $this->orderFactory->create();
// WORST: Direct database calls bypassing models
$db->query('SELECT * FROM sales_order WHERE ...');
Technology Lock-In Symptoms
- Cannot upgrade Magento version due to module conflicts
- Custom code depends on deprecated APIs
- Third-party modules prevent core updates
- Manual processes required for deployments
Database Schema Smells
-- Missing indexes (slow queries)
SELECT * FROM catalog_product_entity WHERE sku = 'X';
-- catalog_product_entity_sku index exists but not used
-- Over-normalization
catalog_product_entity_int → catalog_product_entity_varchar → eav_attribute
-- 4 JOINs to get one attribute value
Configuration Sprawl
- Same setting duplicated across multiple XML files
- Environment-specific values hardcoded in config
- Inconsistent naming conventions across modules
- Deeply nested configuration inheritance
Process Smells
Development Process Debt
Missing Code Review
Symptoms:
- Code merged without review
- Inconsistent coding standards
- Security issues reaching production
- Knowledge concentrated in few developers
Inadequate Testing
// Test coverage gaps
class ProductTest extends TestCase
{
public function testCreateProduct() {
// Only tests happy path
// Missing: edge cases, error handling, performance
}
}
// No integration tests for critical flows
// Missing test data management
// Flaky tests ignored rather than fixed
Documentation Debt
- No README or outdated README
- Missing architecture decision records
- API endpoints undocumented
- Deployment process tribal knowledge
- Onboarding relies on shadowing
CI/CD Debt
# Missing or incomplete pipeline
stages:
- build
- deploy # No testing stage!
# Manual deployment steps
# No rollback procedure
# No monitoring or alerting
Dependency Management Debt
// composer.json with pinned outdated versions
{
"require": {
"magento/framework": "103.0.5",
"php": ">=7.4"
}
}
// Should be >=8.1 for Magento 2.4.6+
Debt Metrics
# Measure with PHPStan/Psalm
vendor/bin/phpstan analyse --level=6 src/
# Count TODO/FIXME/HACK comments
rg -c 'TODO|FIXME|HACK|WORKAROUND' --include='*.php'
# Check code duplication
phpmd src/ text codesize,cleancode
Debt Detection Tools
Static Analysis Tools
PHPStan for Magento
# Install
composer require --dev phpstan/phpstan magento/magento-coding-standard
# Run
vendor/bin/phpstan analyse --level=6 app/code/Vendor/Module/
# phpstan.neon
parameters:
level: 6
paths:
- app/code/Vendor
ignoreErrors:
- '#Call to an undefined method#'
Magento Coding Standard
# Install
composer require --dev magento/magento-coding-standard
# Run
vendor/bin/phpcs --standard=Magento2 app/code/Vendor/Module/
# Auto-fix
vendor/bin/phpcbf --standard=Magento2 app/code/Vendor/Module/
Technical Debt Indicators Dashboard
// Custom CLI command to measure debt
$ php bin/magento debt:report
Module | Complexity | Duplication | TODOs | Rating
Vendor_Catalog | 45 | 12% | 3 | C
Vendor_Checkout | 78 | 23% | 7 | D
Vendor_Inventory | 32 | 5% | 1 | A
Code Complexity Metrics
``n
Cyclomatic Complexity:
- 1-10: Simple, low risk
- 11-20: Moderate, review needed
- 21-50: Complex, refactoring candidate
- 50+: Unmaintainable, immediate action
Lines of Code:
- Methods > 50 lines: likely doing too much
- Classes > 500 lines: consider splitting
- Files > 1000 lines: architectural review needed
### Debt Backlog Management
- Identify debt during code review
- Create ticket with debt type and impact
- Tag with affected module/area
- Estimate remediation effort
- Prioritize with feature work
- Track debt ratio over time
Practice Problems
Given a Magento module with 15 PHP files, identify at least 5 code smells and explain their impact.
Audit a Magento installation for circular dependencies and over-coupling. Document findings.
Quiz
1. What is a 'code smell'?
2. Which tool measures cyclomatic complexity in PHP?
3. What indicates 'architecture smell' in Magento?
4. A class with 30+ constructor dependencies suggests what problem?
Flashcards
Question
What is a code smell?
Click to reveal answer
Answer
A surface-level indicator suggesting deeper structural problems in code
Question
Name 3 common code smells in Magento
Click to reveal answer
Answer
God classes, long parameter lists, duplicated code, feature envy, dead code
Question
What is architecture smell?
Click to reveal answer
Answer
System-level issues like circular dependencies, over-coupling, and missing abstractions
Question
How to detect circular dependencies?
Click to reveal answer
Answer
Run php bin/magento dev:module:graph to visualize module relationships
Question
What PHP tool measures code complexity?
Click to reveal answer
Answer
PHPMD (PHP Mess Detector) measures cyclomatic complexity
Revision Notes
Key Takeaways
- 1. Code smells are indicators, not bugs—address them before they become problems
- 2. God classes, long parameters, and duplication are the most common Magento code smells
- 3. Architecture smells include circular dependencies and over-coupling between modules
- 4. Process smells include missing reviews, inadequate testing, and documentation gaps
- 5. Use PHPStan, PHPMD, and Magento Coding Standard to measure debt quantitatively
- 6. Track debt metrics over time and manage debt like any other backlog item
Interview Tips
- • Explain the difference between a bug and a code smell
- • Describe 3 code smells you have found in real Magento projects
- • How do you measure and track technical debt?
- • When is it acceptable to take on technical debt?
- • Describe a refactoring you performed to address technical debt
Cheat Sheet
Identifying Technical Debt Cheat Sheet
Code Smells: God class, long params, duplication, feature envy, dead code
Architecture Smells: Circular deps, over-coupling, missing abstractions, schema issues
Process Smells: No review, missing tests, no docs, manual deploys
Tools:
- PHPStan: static analysis
- PHPMD: complexity metrics
- Magento Coding Standard: coding standards
- dev:module:graph: dependency visualization
Metrics: Cyclomatic complexity, LOC, duplication %, TODO count