Adobe Commerce Architecture and Customization
Where logic belongs
Adobe Commerce is a layered PHP application: the framework (Magento\Framework) provides object management, configuration, events, and caching; modules (Magento* and app/code) supply business features; themes and layouts handle presentation. A candidate must know the module anatomy: registration.php, etc/module.xml (with setup_version and sequence), etc/di.xml, etc/frontend|adminhtml|webapi routes, and Setup/Patch classes. Know the difference between declarative schema (db_schema.xml, the modern default) and imperative install/upgrade scripts, and when each applies.
Interfaces, preferences, and scope
Configuration is layered and scoped: global, website, store, and store view. etc/config.xml declares defaults; etc/adminhtml/system.xml exposes fields; scope config values are read through \Magento\Framework\App\Config. Dependency injection is configured in di.xml with type, virtualType, preference, and argument nodes. Preferences map an interface to a concrete class globally, while plugins (interceptors) modify public method behavior without editing the original class.
Traps to watch
- Confusing area-specific di.xml (etc/frontend/di.xml) with global di.xml; area config merges only for that area.
- Forgetting that a preference affects every injection of that interface, whereas an argument type override is narrower.
- Mixing up events/observers (one-to-many, no return value influence) with plugins (around/after can alter results).
- Assuming setup_version alone runs patches; data patches are declared in etc/di.xml under Setup\Patch\Data.
Rule of thumb
Prefer plugins over preferences, preferences over class rewrites, and declarative schema over install scripts. Worked example: to add a field to a quote, declare it in db_schema.xml, add a plugin on the repository save, and expose it via an extension attribute in etc/extension_attributes.xml so the REST API returns it without touching core code.