Soy un gran fanático de la verificación de tipos estáticos. Le impide cometer errores estúpidos como este:
// java code
Adult a = new Adult();
a.setAge("Roger"); //static type checker would complain
a.setName(42); //and here too
Pero no te impide cometer errores estúpidos como este:
Adult a = new Adult();
// obviously you've mixed up these fields, but type checker won't complain
a.setAge(150); // nobody's ever lived this old
a.setWeight(42); // a 42lb adult would have serious health issues
El problema surge cuando usa el mismo tipo para representar evidentemente diferentes tipos de información. Estaba pensando que una buena solución para esto sería extender la Integer
clase, solo para evitar errores de lógica de negocios, pero no para agregar funcionalidad. Por ejemplo:
class Age extends Integer{};
class Pounds extends Integer{};
class Adult{
...
public void setAge(Age age){..}
public void setWeight(Pounds pounds){...}
}
Adult a = new Adult();
a.setAge(new Age(42));
a.setWeight(new Pounds(150));
¿Se considera esto una buena práctica? ¿O hay problemas de ingeniería imprevistos en el futuro con un diseño tan restrictivo?
a.SetAge( new Age(150) )
Todavía no se compilará?new Age(...)
objeto, no puede asignarlo incorrectamente a una variable de tipoWeight
en ningún otro lugar. Reduce la cantidad de lugares donde pueden ocurrir errores.Respuestas:
Básicamente está solicitando un sistema de unidad (no, no pruebas de unidad, "unidad" como en "unidad física", como metros, voltios, etc.).
En su código
Age
representa el tiempo yPounds
representa la masa. Esto lleva a cosas como la conversión de unidades, unidades base, precisión, etc.Hubo / hay intentos de introducir algo así en Java, por ejemplo:
Los dos posteriores parecen estar viviendo en esta cosa github: https://github.com/unitsofmeasurement
C ++ tiene unidades a través de Boost
LabView viene con un montón de unidades .
Hay otros ejemplos en otros idiomas. (las ediciones son bienvenidas)
Como puede ver arriba, cuanto más probable es que se use un lenguaje para manejar valores con unidades, más nativamente admite unidades. LabView se usa a menudo para interactuar con dispositivos de medición. Como tal, tiene sentido tener una característica de este tipo en el lenguaje y usarlo sin duda se consideraría una buena práctica.
Pero en cualquier lenguaje de alto nivel de propósito general, donde la demanda es baja para tal cantidad de rigor, probablemente sea inesperado.
Mi conjetura sería: rendimiento / memoria. Si maneja muchos valores, la sobrecarga de un objeto por valor puede convertirse en un problema. Pero como siempre: la optimización prematura es la raíz de todo mal .
Creo que el "problema" más grande es hacer que la gente se acostumbre, ya que la unidad generalmente se define implícitamente así:
Las personas se confundirán cuando tengan que pasar un objeto como valor de algo que aparentemente podría describirse con un simple
int
, cuando no estén familiarizados con los sistemas de unidades.fuente
int
..." --- para lo cual tenemos al Director de Menos Sorpresa como guía aquí. Buena atrapada.En contraste con la respuesta nula, definir un tipo para una "unidad" puede ser beneficioso si un entero no es suficiente para describir la medición. Por ejemplo, el peso a menudo se mide en múltiples unidades dentro del mismo sistema de medición. Piense en "libras" y "onzas" o "kilogramos" y "gramos".
Si necesita un nivel de medición más granular, es beneficioso definir un tipo para la unidad:
Para algo como "edad", recomiendo calcular eso en tiempo de ejecución en función de la fecha de nacimiento de la persona:
fuente
Lo que parece estar buscando se conoce como tipos etiquetados . Son una forma de decir "este es un número entero que representa la edad", mientras que "también es un número entero pero representa el peso" y "no se puede asignar uno al otro". Tenga en cuenta que esto va más allá de las unidades físicas, como metros o kilogramos: es posible que tenga en mi programa "alturas de personas" y "distancias entre puntos en un mapa", ambas medidas en metros, pero no son compatibles entre sí desde que asigné una a el otro no tiene sentido desde la perspectiva de la lógica empresarial.
Algunos idiomas, como Scala, admiten tipos etiquetados con bastante facilidad (consulte el enlace anterior). En otros, puede crear sus propias clases de contenedor, pero esto es menos conveniente.
La validación, por ejemplo, verificar que la altura de una persona sea "razonable" es otro problema. Puede poner dicho código en su
Adult
clase (constructor o establecedores), o dentro de sus clases de tipo / contenedor etiquetados. En cierto modo, las clases integradas tales comoURL
oUUID
cumplen tal función (entre otras, por ejemplo, proporcionar métodos de utilidad).Si usar tipos etiquetados o clases de envoltura realmente ayudará a mejorar su código, dependerá de varios factores. Si sus objetos son simples y tienen pocos campos, el riesgo de asignarlos incorrectamente es bajo y el código adicional necesario para usar tipos etiquetados puede no valer la pena. En sistemas complejos con estructuras complejas y muchos campos (especialmente si muchos de ellos comparten el mismo tipo primitivo), en realidad puede ser útil.
En el código que escribo, a menudo creo clases de contenedor si paso mapas. Los tipos como
Map<String, String>
son muy opacos por sí mismos, por lo que es muy útil incluirlos en clases con nombres significativos comoNameToAddress
. Por supuesto, con los tipos etiquetados, podría escribirMap<Name, Address>
y no necesitar el contenedor para todo el mapa.Sin embargo, para tipos simples como Strings o Integers, he encontrado que las clases de contenedor (en Java) son demasiado molestas. La lógica comercial regular no era tan mala, pero surgieron una serie de problemas al serializar estos tipos a JSON, asignarlos a objetos de base de datos, etc. Puede escribir mapeadores y ganchos para todos los grandes marcos (por ejemplo, Jackson y Spring Data), pero el trabajo y el mantenimiento adicionales relacionados con este código compensarán lo que gane al usar estos contenedores. Por supuesto, YMMV y en otro sistema, el balance puede ser diferente.
fuente