¿Comprueba la validez de los datos en cada constructor, o simplemente asume que los datos son correctos y arroja excepciones en la función específica que tiene un problema con el parámetro?¿Debería verificar los valores incorrectos de los parámetros en el constructor?
Respuesta
Un constructor es una función también, ¿por qué diferenciar?
La creación de un objeto implica que se han realizado todas las comprobaciones de integridad. Es perfectamente razonable comprobar los parámetros en un constructor y lanzar una excepción una vez que se ha detectado un valor ilegal.
Entre todo esto, simplifica la depuración. Cuando su programa arroja una excepción en un constructor, puede observar un seguimiento de la pila y, a menudo, ver de inmediato la causa. Si retrasa el cheque, tendrá que investigar más para detectar qué evento anterior causa el error actual.
Siempre es mejor tener un objeto totalmente construido con todas las invariantes "satisfechas" desde el principio. Tenga cuidado, sin embargo, de arrojar excepciones desde el constructor en lenguajes no administrados ya que eso puede provocar una pérdida de memoria.
Si arroja el constructor, es más probable que la traza de pila muestre de dónde provienen los valores incorrectos.
Estoy de acuerdo con sharptooth en el caso general, pero a veces hay objetos que pueden tener estados en los que algunas funciones son válidas y otras no. En estas situaciones, es mejor posponer los controles a las funciones con estas dependencias particulares.
Por lo general, querrá validar en un constructor, aunque solo sea porque eso significa que sus objetos siempre estarán en un estado válido. Pero algunos tipos de objetos necesitan verificaciones específicas de funciones, y eso también está bien.
Siempre forzar valores en constructores. Si los usuarios no pueden molestarse en seguir las reglas, simplemente los hago cumplir silenciosamente sin decírselos.
Por lo tanto, si pasan un valor de 107%, lo estableceré en 100%. Solo dejo en claro en la documentación que eso es lo que sucede.
Solo si no hay una coacción lógica evidente, les devuelvo una excepción. Me gusta llamar a esto el "principal de la mayor sorpresa para los demasiado perezosos o estúpidos para leer la documentación".
suena interesante, pero ¿esto no conduce a un código que se comporta inesperadamente algunas veces? – Homes2001
Sí, pero solo para aquellos que no han leído el doco :-) – paxdiablo
uhm ... Creo que esto puede llevar a un código difícil de usar/comprender: hay muchos casos en los que me sería difícil detectar el "obvia coerción lógica" –
Esta es una pregunta difícil. He cambiado mis hábitos relacionados a esta pregunta varias veces en los últimos años, así que aquí están algunas ideas que vienen a la mente:
- Comprobación de los argumentos en el constructor es como la comprobación de los argumentos a favor de un método tradicional ... entonces no me gustaría diferenciar aquí ...
- Verificar los argumentos de un método por supuesto ayuda a asegurar que los parámetros pasados sean correctos, pero también introduce mucho más código que tiene que escribir, lo que no siempre vale la pena en mi opinión ... Especialmente cuando escribes métodos cortos que delegan con bastante frecuencia a otros métodos, supongo que terminarías con el 50% de tu código simplemente haciendo verificaciones de parámetros ...
- Furthermor Considero que muy a menudo cuando escribe una prueba unitaria para su clase, no quiere tener que pasar parámetros válidos para todos los métodos ... Muy a menudo tiene sentido pasar solo aquellos parámetros importantes para el caso de prueba actual. , por lo que tener cheques lo retrasaría en la escritura de pruebas unitarias ...
Creo que esto realmente depende de la situación ...Lo que terminé es solo escribir comprobaciones de parámetros cuando sé que los parámetros provienen de un sistema externo (como entradas de usuario, bases de datos, servicios web, o algo así ...). Si los datos provienen de mi propio sistema, no escribo pruebas la mayor parte del tiempo.
Acerca de su tercer punto: ¿por qué le gustaría probar algo que nunca sucederá? Si comprueba los parámetros en el constructor, los valores nunca serán el valor incorrecto. Entonces no tienes que probar allí. Solo prueba el constructor con los parámetros incorrectos. –
En teoría, el código de llamada siempre debe garantizar que se cumplan las condiciones previas antes de llamar a una función. Lo mismo vale para los constructores.
En la práctica, los programadores son flojos y, para estar seguros, es mejor seguir controlando las condiciones previas. Las aseveraciones son útiles allí.
Ejemplo. Disculpen mi sintaxis aparato ortopédico no rizado:
// precondition b<>0
function divide(a,b:double):double;
begin
assert(b<>0); // in case of a programming error.
result := a/b;
end;
// calling code should be:
if foo<>0 then
bar := divide(1,0)
else
// do whatever you need to do when foo equals 0
Por otra parte, siempre se puede cambiar las condiciones previas. En el caso de un constructor esto no es realmente útil.
// no preconditions.. still need to check the result
function divide(a,b:double; out hasResult:boolean):double;
begin
hasResult := b<>0;
if not hasResult then
Exit;
result := a/b;
end;
// calling code:
bar := divide(1,0,result);
if not result then
// do whatever you need to do when the division failed
Espera un minuto, eso no es solo C sin llaves. ¡Es Pascal! Cuidado chicos, tiene un compilador de Pascal. Corran por sus vidas. – paxdiablo
Falla siempre tan pronto como sea posible. Un buen ejemplo de esta práctica se muestra en el tiempo de ejecución. * si intenta utilizar un índice no válido para una matriz, obtendrá una excepción. * la fundición falla inmediatamente cuando no se intenta en una etapa posterior.
Imagínese qué es un código de desastre si un molde dañado permanece en una referencia y cada vez que intente utilizarlo obtendrá una excepción. El único enfoque sensato es fallar lo antes posible y tratar de evitar el estado malo/inválido lo antes posible.
- 1. ¿Debería codificar para proteger su aplicación de los codificadores incorrectos?
- 2. copiar los parámetros del constructor
- 3. ¿Cuándo debería usar los parámetros?
- 4. Modificar los valores de los parámetros antes de enviarlos al constructor Base
- 5. Imprime los valores de los parámetros en la pila
- 6. Parámetros de asInncTask doInBackground frente a los parámetros del constructor
- 7. constructor uml classdiagram con los parámetros
- 8. Uso de Verificar para confirmar los valores de los parámetros esperados en la clase simulada de Moq
- 9. ¿Es posible verificar los valores en la compilación?
- 10. Prácticas de Python: ¿hay una mejor manera de verificar los parámetros del constructor?
- 11. ¿Cuándo salen los parámetros temporales de los valores?
- 12. Cómo obtener el constructor predeterminado cuando los parámetros son opcionales
- 13. Reemplazar los caracteres incorrectos de una Cadena con caracteres incorrectos
- 14. ¿Log.isLoggable devuelve valores incorrectos?
- 15. ¿Cómo se pueden establecer los valores tipados de valores C# en NHibernate con los parámetros IQuery?
- 16. Castle Windsor que pasa los parámetros del constructor
- 17. ¿Puede Mockito verificar los parámetros en función de sus valores en el momento de la llamada al método?
- 18. ¿Debería Backbone.js obtener los parámetros GET de la URL?
- 19. ¿Una forma más sencilla de verificar los parámetros?
- 20. Ninject que pasa en los valores del constructor
- 21. Automapper: cómo asignar a los parámetros del constructor en lugar de los generadores de propiedades
- 22. Excepción con múltiples parámetros en el constructor
- 23. Los cálculos de Cython son incorrectos
- 24. ¿Cómo establecer los valores predeterminados para los parámetros de los métodos de url helper?
- 25. Parámetros nombrados con los parámetros
- 26. Reordenando los parámetros variables
- 27. Python constructor hace cosas raras con los parámetros opcionales
- 28. evitando el tedio de los parámetros opcionales
- 29. ¿Debería oscurecer los valores de las claves primarias?
- 30. UIActionSheet button ¿Los valores de índice son incorrectos cuando se utilizan más de 6 botones personalizados?
Es lo mismo. Es cierto que no todos los métodos pueden invocarse legalmente en cualquier estado de objeto. Pero también a menudo se pueden identificar las combinaciones de valores de parámetros que pueden unirse en el constructor y arrojar excepciones si se presentan otras combinaciones. – sharptooth
Además, si su objeto tiene algunos métodos que siempre son válidos y otros que no, puede considerar si su objeto es demasiado grande. ¿Tal vez debería dividirse? – sleske