# Especificacion de Nomenclatura - ROI Theme ## Purpose Define las convenciones de nomenclatura para carpetas, archivos, clases, metodos, propiedades y variables en el tema ROI Theme (PHP 8.x / WordPress). > **NOTA**: Para principios SOLID y estandares de codigo, ver `_openspec/specs/estandares-codigo.md` > **NOTA**: Para arquitectura y modularidad, ver `_openspec/specs/arquitectura-limpia.md` --- ## Resumen de Nomenclaturas | Elemento | Nomenclatura | Ejemplo | |----------|-------------|---------| | **Carpetas principales** | PascalCase | `Admin/`, `Public/`, `Shared/` | | **Carpetas de contexto** | PascalCase | `Admin/`, `Public/` | | **Carpetas de modulo** | PascalCase | `ContactForm/`, `FeaturedImage/` | | **Carpetas de capa** | PascalCase | `Domain/`, `Application/`, `Infrastructure/` | | **Carpetas auxiliares** | _minusculas | `_planificacion/`, `_arquitectura/` | | **Archivos PHP de clase** | PascalCase.php | `ContactFormRenderer.php` | | **Archivos PHP de interface** | PascalCaseInterface.php | `RendererInterface.php` | | **Archivos JSON schema** | kebab-case.json | `contact-form.json` | | **Namespaces** | PascalCase | `ROITheme\Public\ContactForm\Infrastructure\Ui` | | **Clases** | PascalCase | `ContactFormRenderer` | | **Interfaces** | PascalCase + Interface | `RendererInterface`, `CSSGeneratorInterface` | | **Metodos** | camelCase | `render()`, `getVisibilityClass()` | | **Propiedades** | camelCase | `$cssGenerator`, `$componentName` | | **Variables locales** | $camelCase | `$showDesktop`, `$visibilityClass` | | **Parametros** | $camelCase | `$component`, `$data` | | **Campos privados** | $camelCase | `$cssGenerator` (con private) | | **Constantes clase** | UPPER_SNAKE_CASE | `COMPONENT_NAME`, `MAX_ITEMS` | | **Constantes globales** | UPPER_SNAKE_CASE | `ROI_THEME_VERSION` | | **component_name** | kebab-case | `"contact-form"`, `"featured-image"` | | **Hooks WordPress** | snake_case con prefijo | `roi_theme_after_render` | --- ## Requirements ### Requirement: Nomenclatura de Carpetas Los nombres de carpetas siguen convenciones basadas en su proposito. #### Scenario: Carpetas principales del tema - **WHEN** se nombra una carpeta principal de codigo - **THEN** DEBE usar PascalCase - **AND** ejemplos correctos: `Admin/`, `Public/`, `Shared/`, `Schemas/` - **AND** ejemplos incorrectos: `admin/`, `ADMIN/`, `shared_code/` #### Scenario: Carpetas de contexto - **WHEN** se nombra una carpeta que representa un contexto de la aplicacion - **THEN** DEBE usar PascalCase - **AND** carpetas permitidas: - `Admin/` - Componentes del panel de administracion - `Public/` - Componentes del frontend publico - `Shared/` - Codigo compartido entre contextos - **AND** ejemplos incorrectos: `backend/`, `frontend/`, `common/` #### Scenario: Carpetas de modulo (componente) - **WHEN** se nombra una carpeta que representa un modulo/componente - **THEN** DEBE seguir PascalCase - **AND** DEBE coincidir con component_name convertido de kebab-case - **AND** ejemplos correctos: - `ContactForm/` (de `contact-form`) - `FeaturedImage/` (de `featured-image`) - `TopNotificationBar/` (de `top-notification-bar`) - `CtaBoxSidebar/` (de `cta-box-sidebar`) - **AND** ejemplos incorrectos: - `contact-form/` (kebab-case) - `contactForm/` (camelCase) - `CONTACT_FORM/` (UPPER_SNAKE) #### Scenario: Carpetas de capa (Clean Architecture) - **WHEN** se nombra una carpeta que representa una capa de arquitectura - **THEN** DEBE usar PascalCase - **AND** carpetas permitidas dentro de cada modulo: - `Domain/` - Entidades, interfaces, value objects - `Application/` - Casos de uso - `Infrastructure/` - Implementaciones (Ui, Api, Persistence, Services) - **AND** subcarpetas de Infrastructure permitidas: - `Ui/` - Renderers, FormBuilders - `Api/` - Handlers AJAX, REST endpoints - `Persistence/` - Repositorios - `Services/` - Servicios de infraestructura - `WordPress/` - Integraciones especificas de WordPress - **AND** ejemplos correctos: `Infrastructure/Ui/`, `Infrastructure/Api/WordPress/` - **AND** ejemplos incorrectos: `infrastructure/`, `UI/`, `api/` #### Scenario: Carpetas auxiliares (no codigo) - **WHEN** se nombra una carpeta de documentacion, planificacion o configuracion - **THEN** DEBE usar prefijo guion bajo + minusculas - **AND** ejemplos correctos: - `_planificacion/` - Documentos de planificacion - `_arquitectura/` - Documentos de arquitectura - **AND** nombres compuestos usan guion medio: `_pruebas-regresion/` - **AND** el guion bajo indica carpetas auxiliares/no-codigo #### Scenario: Carpetas de cambios (OpenSpec) - **WHEN** se crea una carpeta para un cambio/feature en `_openspec/changes/` - **THEN** DEBE usar nombre en kebab-case descriptivo - **AND** maximo 1 nivel de carpeta despues de `changes/` - **AND** ejemplos correctos: - `anti-spam-validator/` - `lazy-loading-images/` - `improved-caching/` - **AND** ejemplos incorrectos: - `AntiSpam/` (PascalCase) - `anti_spam/` (snake_case) - `anti-spam/subfolder/` (anidamiento prohibido) #### Scenario: Excepciones permitidas - **WHEN** existen carpetas especiales del sistema - **THEN** se permiten las siguientes excepciones: - `.git/` - Control de versiones - `.serena/` - Configuracion de Serena MCP - `.claude/` - Configuracion de Claude Code - `node_modules/` - Dependencias npm (si aplica) - `vendor/` - Dependencias Composer (si aplica) - `_openspec/` - Sistema de especificaciones (carpeta auxiliar) --- ### Requirement: Nomenclatura de Archivos PHP Los archivos PHP DEBEN seguir convencion PascalCase. #### Scenario: Archivos de clase - **WHEN** se nombra un archivo que contiene una clase PHP - **THEN** DEBE seguir PascalCase - **AND** el nombre DEBE coincidir EXACTAMENTE con el nombre de la clase - **AND** extension `.php` - **AND** ejemplos correctos: - `ContactFormRenderer.php` (contiene `class ContactFormRenderer`) - `NewsletterAjaxHandler.php` (contiene `class NewsletterAjaxHandler`) - `CSSGeneratorService.php` (contiene `class CSSGeneratorService`) - **AND** ejemplos incorrectos: - `contact-form-renderer.php` (kebab-case) - `contactFormRenderer.php` (camelCase) - `class_contact_form.php` (snake_case con prefijo) #### Scenario: Archivos de interface - **WHEN** se nombra un archivo que contiene una interface - **THEN** DEBE seguir PascalCase con sufijo Interface - **AND** extension `.php` - **AND** ejemplos correctos: - `RendererInterface.php` - `CSSGeneratorInterface.php` - `ComponentRepositoryInterface.php` - **AND** ejemplos incorrectos: - `IRenderer.php` (prefijo I estilo C#) - `Renderer.php` (sin sufijo) #### Scenario: Archivos de trait - **WHEN** se nombra un archivo que contiene un trait PHP - **THEN** DEBE seguir PascalCase con sufijo Trait - **AND** extension `.php` - **AND** ejemplos correctos: - `VisibilityTrait.php` - `CSSGeneratorTrait.php` --- ### Requirement: Nomenclatura de Archivos JSON (Schemas) Los schemas JSON DEBEN usar kebab-case. #### Scenario: Archivos de schema de componente - **WHEN** se nombra un archivo JSON schema - **THEN** DEBE usar kebab-case - **AND** extension `.json` - **AND** el nombre DEBE coincidir con el component_name - **AND** ejemplos correctos: - `contact-form.json` (component_name: "contact-form") - `featured-image.json` (component_name: "featured-image") - `top-notification-bar.json` (component_name: "top-notification-bar") - `cta-box-sidebar.json` (component_name: "cta-box-sidebar") - **AND** ejemplos incorrectos: - `ContactForm.json` (PascalCase) - `contact_form.json` (snake_case) - `contactForm.json` (camelCase) --- ### Requirement: Nomenclatura de Namespaces Los namespaces PHP DEBEN seguir convencion PascalCase jerarquica. #### Scenario: Namespace raiz - **WHEN** se define el namespace principal del tema - **THEN** DEBE ser `ROITheme` - **AND** ejemplo: `namespace ROITheme;` #### Scenario: Namespaces de modulo publico - **WHEN** se define un namespace para un componente en Public/ - **THEN** DEBE seguir `ROITheme\Public\[Componente]\[Capa][\Subcapa]` - **AND** ejemplos correctos: ```php // Renderers namespace ROITheme\Public\ContactForm\Infrastructure\Ui; namespace ROITheme\Public\FeaturedImage\Infrastructure\Ui; namespace ROITheme\Public\TopNotificationBar\Infrastructure\Ui; // AJAX Handlers namespace ROITheme\Public\Footer\Infrastructure\Api\WordPress; namespace ROITheme\Public\ContactForm\Infrastructure\Api\WordPress; // Domain (si existe) namespace ROITheme\Public\AdsensePlacement\Domain\ValueObjects; namespace ROITheme\Public\AdsensePlacement\Domain\Contracts; // Application (si existe) namespace ROITheme\Public\CustomCSSManager\Application\UseCases; ``` #### Scenario: Namespaces de modulo admin - **WHEN** se define un namespace para un componente en Admin/ - **THEN** DEBE seguir `ROITheme\Admin\[Componente]\[Capa][\Subcapa]` - **AND** ejemplos correctos: ```php // FormBuilders namespace ROITheme\Admin\ContactForm\Infrastructure\Ui; namespace ROITheme\Admin\FeaturedImage\Infrastructure\Ui; // Shared de Admin namespace ROITheme\Admin\Shared\Infrastructure\Ui; ``` #### Scenario: Namespaces de Shared - **WHEN** se define un namespace para codigo compartido - **THEN** DEBE seguir `ROITheme\Shared\[Capa][\Subcapa]` - **AND** ejemplos correctos: ```php // Domain namespace ROITheme\Shared\Domain\Contracts; namespace ROITheme\Shared\Domain\Entities; namespace ROITheme\Shared\Domain\ValueObjects; // Application namespace ROITheme\Shared\Application\UseCases; // Infrastructure namespace ROITheme\Shared\Infrastructure\Services; namespace ROITheme\Shared\Infrastructure\Persistence\WordPress; ``` --- ### Requirement: Nomenclatura de Clases Los nombres de clase DEBEN seguir convencion PascalCase. #### Scenario: Clases regulares - **WHEN** se define una clase en PHP - **THEN** el nombre DEBE seguir PascalCase - **AND** DEBE ser un sustantivo o frase sustantiva - **AND** DEBE ser descriptivo de su responsabilidad - **AND** ejemplos correctos: ```php final class ContactFormRenderer final class ComponentSettings final class VisibilityChecker ``` - **AND** ejemplos incorrectos: ```php final class contactFormRenderer // camelCase final class contact_form_renderer // snake_case final class Render // verbo, no sustantivo ``` #### Scenario: Clases Renderer - **WHEN** se define una clase que renderiza HTML de un componente - **THEN** DEBE usar sufijo `Renderer` - **AND** DEBE implementar `RendererInterface` - **AND** DEBE ser `final` - **AND** ejemplos correctos: ```php final class ContactFormRenderer implements RendererInterface final class FeaturedImageRenderer implements RendererInterface final class TopNotificationBarRenderer implements RendererInterface ``` #### Scenario: Clases FormBuilder - **WHEN** se define una clase que genera formularios admin - **THEN** DEBE usar sufijo `FormBuilder` - **AND** DEBE ser `final` - **AND** ejemplos correctos: ```php final class ContactFormFormBuilder final class FeaturedImageFormBuilder final class TopNotificationBarFormBuilder ``` #### Scenario: Clases de caso de uso - **WHEN** se define una clase UseCase en Application/ - **THEN** DEBE usar sufijo `UseCase` - **AND** el nombre DEBE describir la accion - **AND** ejemplos correctos: ```php final class GetCriticalCSSUseCase final class CheckAdsenseVisibilityUseCase final class GetDeferredSnippetsUseCase ``` #### Scenario: Clases de servicio - **WHEN** se define una clase que provee servicios en Infrastructure/ - **THEN** DEBE usar sufijo `Service` - **AND** ejemplos correctos: ```php final class CSSGeneratorService final class AntiSpamValidatorService final class CacheService ``` #### Scenario: Clases de repositorio - **WHEN** se define una clase de acceso a datos - **THEN** DEBE usar sufijo `Repository` - **AND** ejemplos correctos: ```php final class ComponentSettingsRepository final class PageVisibilityRepository ``` #### Scenario: Clases Handler (AJAX/API) - **WHEN** se define una clase que maneja peticiones AJAX o API - **THEN** DEBE usar sufijo `Handler` o `Controller` - **AND** ejemplos correctos: ```php final class NewsletterAjaxHandler final class ContactFormAjaxHandler final class AdsenseVisibilityController ``` --- ### Requirement: Nomenclatura de Interfaces Los nombres de interface DEBEN seguir convencion PascalCase con sufijo. #### Scenario: Interfaces - **WHEN** se define una interface en PHP - **THEN** el nombre DEBE terminar con `Interface` - **AND** DEBE seguir PascalCase - **AND** DEBE describir la capacidad o contrato - **AND** ejemplos correctos: ```php interface RendererInterface interface CSSGeneratorInterface interface ComponentRepositoryInterface interface AjaxControllerInterface ``` - **AND** ejemplos incorrectos: ```php interface IRenderer // prefijo I estilo C# interface Renderer // sin sufijo interface renderer_interface // snake_case ``` --- ### Requirement: Nomenclatura de Metodos Los nombres de metodo DEBEN seguir convencion camelCase. #### Scenario: Metodos publicos - **WHEN** se define un metodo publico - **THEN** el nombre DEBE seguir camelCase - **AND** DEBE comenzar con verbo que describe la accion - **AND** ejemplos correctos: ```php public function render(Component $component): string public function getVisibilityClass(array $data): ?string public function validateInput(string $input): bool public function buildForm(string $componentId): string ``` - **AND** ejemplos incorrectos: ```php public function Render() // PascalCase public function get_visibility_class() // snake_case public function visibility() // sin verbo ``` #### Scenario: Metodos privados - **WHEN** se define un metodo privado - **THEN** DEBE seguir camelCase (igual que publicos) - **AND** ejemplos correctos: ```php private function parseResponse(): array private function validateInternal(): bool private function generateCSS(array $data): string ``` #### Scenario: Metodos booleanos - **WHEN** un metodo retorna un valor booleano - **THEN** DEBE usar prefijo `is`, `has`, `can`, `should` - **AND** ejemplos correctos: ```php public function isEnabled(array $data): bool public function hasPermission(string $capability): bool public function canProcess(): bool public function shouldShow(string $component): bool ``` - **AND** ejemplos incorrectos: ```php public function enabled(): bool // sin prefijo public function checkEnabled(): bool // check no es booleano public function getIsEnabled(): bool // get redundante ``` #### Scenario: Metodos getter/setter - **WHEN** se define un metodo de acceso - **THEN** getters DEBEN usar prefijo `get` - **AND** setters DEBEN usar prefijo `set` - **AND** ejemplos correctos: ```php public function getData(): array public function setData(array $data): void public function getComponentName(): string ``` --- ### Requirement: Nomenclatura de Propiedades y Variables Las propiedades y variables DEBEN seguir convencion camelCase. #### Scenario: Propiedades de clase - **WHEN** se declara una propiedad de clase - **THEN** DEBE seguir camelCase - **AND** DEBE tener visibilidad explicita (private, protected, public) - **AND** ejemplos correctos: ```php private CSSGeneratorInterface $cssGenerator; private string $componentName; protected array $settings; ``` - **AND** ejemplos incorrectos: ```php private $CssGenerator; // PascalCase private $css_generator; // snake_case private $_cssGenerator; // prefijo _ (no necesario en PHP moderno) ``` #### Scenario: Propiedades booleanas - **WHEN** se define una propiedad booleana - **THEN** DEBE usar prefijo `is`, `has`, `can` - **AND** ejemplos correctos: ```php private bool $isEnabled; private bool $hasChanges; private bool $canEdit; ``` #### Scenario: Variables locales - **WHEN** se declara una variable local - **THEN** DEBE seguir $camelCase - **AND** DEBE ser descriptiva - **AND** ejemplos correctos: ```php $showDesktop = $data['visibility']['show_on_desktop'] ?? true; $visibilityClass = $this->getVisibilityClass($data); $componentSettings = $this->repository->get($componentName); ``` - **AND** ejemplos incorrectos: ```php $ShowDesktop // PascalCase $show_desktop // snake_case $sd // abreviatura $strShowDesktop // notacion hungara ``` #### Scenario: Parametros de metodo - **WHEN** se declara un parametro de metodo - **THEN** DEBE seguir $camelCase - **AND** ejemplos correctos: ```php public function render(Component $component): string public function validateField(string $fieldName, mixed $value): bool ``` #### Scenario: Variables de iteracion - **WHEN** se usa una variable de iteracion en bucle - **THEN** se permiten nombres cortos para indices: `$i`, `$j`, `$k` - **AND** se prefiere nombre descriptivo para elementos - **AND** ejemplos correctos: ```php for ($i = 0; $i < count($items); $i++) foreach ($components as $component) foreach ($settings as $key => $value) ``` --- ### Requirement: Nomenclatura de Constantes Las constantes DEBEN seguir convencion UPPER_SNAKE_CASE. #### Scenario: Constantes de clase - **WHEN** se define una constante de clase - **THEN** DEBE seguir UPPER_SNAKE_CASE - **AND** ejemplos correctos: ```php private const COMPONENT_NAME = 'contact-form'; public const MAX_RETRY_COUNT = 3; protected const DEFAULT_TIMEOUT = 5000; ``` - **AND** ejemplos incorrectos: ```php private const componentName = 'contact-form'; // camelCase private const ComponentName = 'contact-form'; // PascalCase ``` #### Scenario: Constantes globales - **WHEN** se define una constante global del tema - **THEN** DEBE usar prefijo `ROI_THEME_` - **AND** DEBE seguir UPPER_SNAKE_CASE - **AND** ejemplos correctos: ```php define('ROI_THEME_VERSION', '1.0.0'); define('ROI_THEME_PATH', get_template_directory()); ``` --- ### Requirement: Nomenclatura de component_name El identificador de componente DEBE usar kebab-case. #### Scenario: component_name en JSON - **WHEN** se define component_name en un schema JSON - **THEN** DEBE usar kebab-case - **AND** DEBE coincidir con el nombre del archivo JSON - **AND** ejemplos correctos: ```json { "component_name": "contact-form", "component_name": "featured-image", "component_name": "top-notification-bar", "component_name": "cta-box-sidebar" } ``` #### Scenario: component_name en BD - **WHEN** se guarda component_name en base de datos - **THEN** DEBE mantener kebab-case - **AND** tabla: `wp_roi_theme_component_settings` - **AND** columna: `component_name` #### Scenario: component_name en codigo PHP - **WHEN** se usa component_name en codigo PHP - **THEN** DEBE mantenerse en kebab-case - **AND** ejemplos correctos: ```php private const COMPONENT_NAME = 'contact-form'; public function supports(string $componentType): bool { return $componentType === 'contact-form'; } // En data-attribute $html .= 'data-component="contact-form"'; ``` #### Scenario: Conversion kebab-case a PascalCase - **WHEN** se necesita convertir component_name a nombre de carpeta/clase - **THEN** eliminar guiones y capitalizar cada palabra - **AND** ejemplos de conversion: | kebab-case | PascalCase | |------------|------------| | `contact-form` | `ContactForm` | | `featured-image` | `FeaturedImage` | | `top-notification-bar` | `TopNotificationBar` | | `cta-box-sidebar` | `CtaBoxSidebar` | | `cta-lets-talk` | `CtaLetsTalk` | --- ### Requirement: Nomenclatura de Hooks WordPress Los hooks DEBEN usar snake_case con prefijo del tema. #### Scenario: Actions del tema - **WHEN** se define un action hook del tema - **THEN** DEBE usar prefijo `roi_theme_` - **AND** DEBE seguir snake_case - **AND** ejemplos correctos: ```php do_action('roi_theme_after_render', $component); do_action('roi_theme_before_form_submit'); do_action('roi_theme_component_loaded', $componentName); ``` #### Scenario: Filters del tema - **WHEN** se define un filter hook del tema - **THEN** DEBE usar prefijo `roi_theme_filter_` - **AND** DEBE seguir snake_case - **AND** ejemplos correctos: ```php $css = apply_filters('roi_theme_filter_component_css', $css, $component); $html = apply_filters('roi_theme_filter_render_output', $html); ``` #### Scenario: Acciones AJAX - **WHEN** se registra una accion AJAX - **THEN** DEBE usar prefijo `roi_` - **AND** DEBE seguir snake_case - **AND** ejemplos correctos: ```php add_action('wp_ajax_roi_newsletter_subscribe', [$this, 'handle']); add_action('wp_ajax_nopriv_roi_contact_form_submit', [$this, 'handle']); ``` --- ### Requirement: Prohibicion de Notacion Hungara La notacion hungara esta PROHIBIDA. #### Scenario: Prefijos de tipo prohibidos - **WHEN** se nombra una variable, propiedad o parametro - **THEN** NO DEBE usar prefijos de tipo - **AND** prefijos prohibidos: | Prefijo | Significado | Ejemplo Incorrecto | |---------|-------------|-------------------| | `str` | String | `$strNombre` | | `int`, `i` | Integer | `$intContador`, `$iTotal` | | `b`, `bln` | Boolean | `$bActivo`, `$blnValido` | | `arr` | Array | `$arrItems` | | `obj` | Object | `$objRenderer` | #### Scenario: Nombres correctos sin notacion hungara - **WHEN** se reemplaza notacion hungara - **THEN** usar nombres descriptivos | Incorrecto | Correcto | |------------|----------| | `$strNombre` | `$name` o `$customerName` | | `$bActivo` | `$isActive` | | `$arrItems` | `$items` | | `$objRenderer` | `$renderer` | | `$intCount` | `$count` o `$itemCount` | --- ### Requirement: Validacion Pre-Commit de Nomenclatura Las convenciones DEBEN validarse antes del commit. #### Scenario: Checklist de nomenclatura - **WHEN** el codigo esta listo para commit - **THEN** verificar: - [ ] Carpetas de modulo en PascalCase - [ ] Archivos PHP en PascalCase.php - [ ] Archivos JSON schema en kebab-case.json - [ ] Namespaces en PascalCase jerarquico - [ ] Clases en PascalCase - [ ] Interfaces con sufijo Interface - [ ] Metodos en camelCase - [ ] Propiedades en camelCase - [ ] Variables locales en $camelCase - [ ] Constantes en UPPER_SNAKE_CASE - [ ] component_name en kebab-case - [ ] Hooks con prefijo roi_theme_ - [ ] SIN notacion hungara - [ ] Metodos booleanos con is/has/can/should - [ ] Renderers con sufijo Renderer - [ ] FormBuilders con sufijo FormBuilder - [ ] UseCases con sufijo UseCase - [ ] Services con sufijo Service --- ## Tabla de Conversion Rapida | De | A | Ejemplo | |----|---|---------| | kebab-case | PascalCase | `contact-form` → `ContactForm` | | PascalCase | kebab-case | `ContactForm` → `contact-form` | | PascalCase | camelCase | `ContactForm` → `contactForm` | | snake_case | PascalCase | `contact_form` → `ContactForm` | | snake_case | camelCase | `contact_form` → `contactForm` | --- **Última actualización:** 2026-01-08