¡Felicidades! Acaba de dar la vuelta al mundo del lenguaje de programación / sistema de tipos, llegando al otro lado del mundo desde donde partió. ¡Acabas de aterrizar en el borde del lenguaje dinámico / tierra de objetos basados en prototipos!
Muchos lenguajes dinámicos (por ejemplo, JavaScript, PHP, Python) permiten ampliar o cambiar las propiedades de los objetos en tiempo de ejecución.
La forma extrema de esto es un lenguaje basado en prototipos como Self o JavaScript. No tienen clases, estrictamente hablando. Puede hacer cosas que parecen una programación orientada a objetos basada en clases con herencia, pero las reglas son mucho más relajadas en comparación con lenguajes más definidos y basados en clases como Java y C #.
Langauges como PHP y Python viven en el medio. Tienen sistemas regulares, idiomáticos basados en clases. Pero los atributos de objeto se pueden agregar, cambiar o eliminar en tiempo de ejecución, aunque con algunas restricciones (como "excepto para los tipos integrados") que no se encuentran en JavaScript.
La gran compensación para este dinamismo es el rendimiento. Olvídese de cuán fuerte o débilmente tipeado es el idioma, o qué tan bien puede compilarse en código máquina. Los objetos dinámicos deben representarse como mapas / diccionarios flexibles, en lugar de estructuras simples. Esto agrega sobrecarga a cada acceso a objetos. Algunos programas hacen todo lo posible para reducir esta sobrecarga (por ejemplo, con la asignación fantasma kwarg y las clases basadas en slots en Python), pero la sobrecarga adicional generalmente es igual al curso y al precio de admisión.
Volviendo a su diseño, está injertando la capacidad de tener propiedades dinámicas en un subconjunto de sus clases. A Productpuede tener atributos variables; presumiblemente un Invoiceo un Orderpodría y no podría. No es un mal camino a seguir. Le brinda la flexibilidad de tener variaciones donde las necesite, mientras se mantiene en un lenguaje estricto y disciplinado y un sistema de tipos. En el lado negativo, usted es responsable de administrar esas propiedades flexibles, y probablemente tendrá que hacerlo a través de mecanismos que se ven ligeramente diferentes de los atributos más nativos. p.prop('tensile_strength')en lugar de p.tensile_strength, por ejemplo, y en p.set_prop('tensile_strength', 104.4)lugar dep.tensile_strength = 104.4. Pero trabajé y construí muchos programas en Pascal, Ada, C, Java e incluso en lenguajes dinámicos que usaban exactamente ese acceso getter-setter para tipos de atributos no estándar; El enfoque es claramente viable.
Por cierto, esta tensión entre los tipos estáticos y un mundo muy variado es extremadamente común. A menudo se ve un problema análogo al diseñar el esquema de la base de datos, especialmente para los almacenes de datos relacionales y pre-relacionales. A veces se trata creando "super filas" que contienen suficiente flexibilidad para contener o definir la unión de todas las variaciones imaginadas, y luego rellenar cualquier dato que ingrese en esos campos. El WordPress wp_postsmesa , por ejemplo, tiene campos como comment_count, ping_status, post_parenty post_date_gmtque sólo son interesantes en algunas circunstancias, y que en la práctica a menudo queda en blanco. Otro enfoque es una tabla normalizada , muy libre, wp_optionscomo suPropertyclase. Si bien requiere una administración más explícita, los elementos en él rara vez están en blanco. Las bases de datos orientadas a objetos y documentos (por ejemplo, MongoDB) a menudo tienen más facilidad para manejar las opciones cambiantes, porque pueden crear y establecer atributos prácticamente a voluntad.