- renombrar openspec/ a _openspec/ (carpeta auxiliar) - mover specs de features a changes/ - crear specs base: arquitectura-limpia, estandares-codigo, nomenclatura - migrar _planificacion/ con design-system y roi-theme-template - agregar especificacion recaptcha anti-spam (proposal, tasks, spec) - corregir rutas y referencias en todas las specs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
22 KiB
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.mdNOTA: 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 administracionPublic/- Componentes del frontend publicoShared/- 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/(decontact-form)FeaturedImage/(defeatured-image)TopNotificationBar/(detop-notification-bar)CtaBoxSidebar/(decta-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 objectsApplication/- Casos de usoInfrastructure/- Implementaciones (Ui, Api, Persistence, Services)
- AND subcarpetas de Infrastructure permitidas:
Ui/- Renderers, FormBuildersApi/- Handlers AJAX, REST endpointsPersistence/- RepositoriosServices/- Servicios de infraestructuraWordPress/- 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 Codenode_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(contieneclass ContactFormRenderer)NewsletterAjaxHandler.php(contieneclass NewsletterAjaxHandler)CSSGeneratorService.php(contieneclass 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.phpCSSGeneratorInterface.phpComponentRepositoryInterface.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.phpCSSGeneratorTrait.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:
// 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:
// 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:
// 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:
final class ContactFormRenderer final class ComponentSettings final class VisibilityChecker - AND ejemplos incorrectos:
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:
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:
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:
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:
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:
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
HandleroController - AND ejemplos correctos:
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:
interface RendererInterface interface CSSGeneratorInterface interface ComponentRepositoryInterface interface AjaxControllerInterface - AND ejemplos incorrectos:
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:
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:
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:
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:
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:
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:
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:
private CSSGeneratorInterface $cssGenerator; private string $componentName; protected array $settings; - AND ejemplos incorrectos:
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:
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:
$showDesktop = $data['visibility']['show_on_desktop'] ?? true; $visibilityClass = $this->getVisibilityClass($data); $componentSettings = $this->repository->get($componentName); - AND ejemplos incorrectos:
$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:
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:
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:
private const COMPONENT_NAME = 'contact-form'; public const MAX_RETRY_COUNT = 3; protected const DEFAULT_TIMEOUT = 5000; - AND ejemplos incorrectos:
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:
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:
{ "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:
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-formContactFormfeatured-imageFeaturedImagetop-notification-barTopNotificationBarcta-box-sidebarCtaBoxSidebarcta-lets-talkCtaLetsTalk
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:
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:
$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:
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