Al transferir objetos a través de una API, como en el formato JSON sin esquema, ¿cuál es la forma ideal de devolver una propiedad de cadena inexistente? Sé que hay diferentes maneras de hacer esto, como en los ejemplos en los enlaces que figuran a continuación.
Estoy seguro de que he usado nulo en el pasado, pero no tengo una buena razón para hacerlo. Parece sencillo usar nulo cuando se trata con la base de datos. Pero la base de datos parece un detalle de implementación que no debería afectar a la parte del otro lado de la API. Por ejemplo, probablemente usan un almacén de datos sin esquema que solo almacena propiedades con valores (no nulos).
Desde el punto de vista del código, restringir las funciones de cadena para que funcionen solo con un tipo, es decir string
(no nulo), las hace más fáciles de probar; evitar nulo es también una razón para tener Option
objeto. Entonces, si el código que produce la solicitud / respuesta no usa nulo, supongo que el código en el otro lado de la API no se verá obligado a usar nulo también.
Prefiero la idea de usar una cadena vacía como una manera fácil de evitar usar nulo. Un argumento que escuché para usar nulo y contra la cadena vacía es que la cadena vacía significa que la propiedad existe. Aunque entiendo la diferencia, también me pregunto si es solo el detalle de implementación y si usar una cadena nula o vacía hace alguna diferencia en la vida real. También me pregunto si una cadena vacía es análoga a una matriz vacía.
Entonces, ¿cuál es la mejor manera de hacerlo que aborde esas preocupaciones? ¿Depende del formato del objeto que se transfiere (esquema / sin esquema)?
fuente
if( value === null) { use parent value; }
Sin embargo, si establece el valor secundario, incluso en una cadena vacía (por ejemplo, anula el valor primario predeterminado con un espacio en blanco), entonces, ¿cómo "re-hereda" el valor? Para mí, establecerlo como nulo significaría "desarmar este valor para que sepamos usar el valor principal".null
(es cierto quenull
se evita como tal), el interlocutor significa "Devolver no nulo" [Objeto] (es decir: cadena vacía, matriz vacía, etc.) cuando escribe "evitar".Respuestas:
TLDR; Eliminar propiedades nulas
Lo primero a tener en cuenta es que las aplicaciones en sus bordes no están orientadas a objetos (ni funcionales si se programa en ese paradigma). El JSON que recibe no es un objeto y no debe tratarse como tal. Son solo datos estructurados que pueden (o no) convertirse en un objeto. En general, no se debe confiar en ningún JSON entrante como objeto comercial hasta que se valide como tal. El solo hecho de que se deserialice no lo hace válido. Dado que JSON también tiene primitivas limitadas en comparación con los lenguajes de fondo, a menudo vale la pena hacer un DTO alineado con JSON para los datos entrantes. Luego, use el DTO para construir un objeto comercial (o un intento de error) para ejecutar la operación API.
Cuando mira JSON como solo un formato de transmisión, tiene más sentido omitir propiedades que no están establecidas. Es menos para enviar a través del cable. Si su idioma de back-end no utiliza valores nulos de forma predeterminada, probablemente podría configurar su deserializador para dar un error. Por ejemplo, mi configuración común para Newtonsoft.Json traduce propiedades nulas / faltantes solo a / desde
option
tipos F # y, de lo contrario, generará un error. Esto proporciona una representación natural de qué campos son opcionales (aquellos conoption
tipo).Como siempre, las generalizaciones solo te llevan tan lejos. Probablemente hay casos en los que una propiedad nula o predeterminada se ajusta mejor. Pero la clave no es mirar las estructuras de datos en el borde de su sistema como objetos comerciales. Los objetos comerciales deben llevar garantías comerciales (por ejemplo, nombrar al menos 3 caracteres) cuando se crean correctamente. Pero las estructuras de datos extraídas no tienen garantías reales.
fuente
Actualización: he editado un poco la respuesta, porque puede haber generado confusión.
Ir con una cadena vacía es un no definitivo. La cadena vacía sigue siendo un valor, solo está vacía. No valor debe ser indicado el uso de una construcción que no representa nada,
null
.Desde el punto de vista del desarrollador de API, solo existen dos tipos de propiedades:
null
.Esto deja bastante claro que cuando una propiedad es obligatoria, es decir. requerido, nunca puede ser
null
.Por otro lado, si una propiedad opcional de un objeto no se establece y se deja vacía, prefiero mantenerlos en la respuesta de todos modos con el
null
valor. Desde mi experiencia, hace que sea más fácil para los clientes API implementar el análisis, ya que no están obligados a verificar si una propiedad realmente existe o no, porque siempre está ahí, y simplemente pueden convertir la respuesta a su DTO personalizado, tratando losnull
valores como opcionalIncluir / eliminar dinámicamente campos de las fuerzas de respuesta, incluidas condiciones adicionales en los clientes.
De cualquier manera, de cualquier forma que elija, asegúrese de mantenerlo consistente y bien documentado. De esa manera, realmente no importa lo que use para su API, siempre que el comportamiento sea predecible.
fuente
null
para referencias. Mezclar valores con referencias es una de mis preocupaciones. ¿Cómo diferencia los campos opcionales de los camposnull
de cadena no opcionales que tienennull
valor? Volviendo a analizar, ¿no probar la existencia de propiedades hace que el analizador sea más frágil?null
para indicar que el valor es opcional. Entonces, cuando define un objeto que tiene una propiedad de cadena no opcional, y el consumidor no tiene esta propiedad, debe enviar una cadena vacía para esa propiedad. ¿Está bien?null
El uso depende de la aplicación / idiomaEn última instancia, la elección de usar o no
null
un valor de aplicación válido depende en gran medida de su aplicación y lenguaje de programación / interfaz / edge.En un nivel fundamental, recomendaría tratar de usar tipos distintos si hay clases distintas de valores.
null
puede ser una opción si su interfaz lo permite y solo hay dos clases de una propiedad que está tratando de representar. Omitir una propiedad puede ser una opción si su interfaz o formato lo permite. Un nuevo tipo agregado (clase, objeto, tipo de mensaje) puede ser otra opción.Para su ejemplo de cadena, si esto está en el lenguaje de programación, me haría un par de preguntas.
Option
probablemente será mejor para el diseño de su interfaz.Option
probablemente llene este caso mejor si su cadena no es anulable. Sin embargo, es probable que tenga que verificar la entrada del usuario para unnull
valor de cadena de todos modos, por lo que probablemente diferiré de nuevo a la primera línea de preguntas: cuántos tipos de valores quiero / quiero representar.null
indicativo de un error del programador en mi lenguaje de programación? Desafortunadamente, anull
menudo es el valor predeterminado para punteros o referencias no inicializados (o no inicializados explícitamente) en algunos idiomas. ¿Esnull
un valor aceptable como valor predeterminado? ¿Es seguro como valor predeterminado? A vecesnull
es indicativo de valores desasignados. ¿Debo proporcionar a los consumidores de mi interfaz una indicación de estos posibles problemas de administración de memoria o inicialización en su programa? ¿Cuál es el modo de falla de tal llamada ante tales problemas? ¿La persona que llama está en el mismo proceso o hilo que el mío, de modo que tales errores son un riesgo alto para mi aplicación?Dependiendo de sus respuestas a estas preguntas, probablemente podrá centrarse en si es o no
null
adecuado para su interfaz.Ejemplo 1
null
es un posible valor de cadena que se devuelve al no poder asignar espacio para una cadena.Respuesta:
null
probablemente no sea apropiadoJustificación:
null
en este caso, en realidad se usa para indicar dos tipos diferentes de valores. El primero puede ser un valor predeterminado que el usuario de su interfaz puede establecer. Desafortunadamente, el segundo valor es un indicador para indicar que su sistema no funciona correctamente. En tales casos, probablemente desee fallar de la manera más segura posible (lo que sea que eso signifique para su sistema).Ejemplo 2
char *
miembro.NULL
char *
miembro para su API se puede indicar mediante un solo valor deNULL
char *
miembro.Respuesta:
NULL
puede ser apropiadoJustificación: existe una pequeña posibilidad de que su estructura pase la
NULL
verificación pero no se haya inicializado. Sin embargo, es posible que su API no pueda dar cuenta de esto a menos que tenga algún tipo de suma de verificación en el valor de estructura y / o la comprobación de rango de la dirección de la estructura. Las listas MISRA-C pueden ayudar a los usuarios de su API marcando el uso de estructuras antes de su inicialización. Sin embargo, en cuanto alchar *
miembro, si el puntero a estructura apunta a una estructura inicializada,NULL
es el valor predeterminado de un miembro no especificado en un inicializador de estructura. Por lo tanto,NULL
puede servir como un valor predeterminado seguro para elchar *
miembro de estructura en su aplicación.Si está en una interfaz de serialización, me haría las siguientes preguntas sobre si usar o no nulo en una cadena.
null
indicativo de un posible error del lado del cliente? Para JSON en JavaScript, este es probablemente un no, yanull
que no se usa necesariamente como una indicación de falla de asignación. En JavaScript, se utiliza como una indicación explícita de la ausencia de objetos de una referencia que se establece de forma problemática. Sin embargo, existen analizadores y serializadores que no son JavaScript que asignan JSONnull
alnull
tipo nativo . Si este es el caso, se inicia la discusión sobre si elnull
uso nativo es adecuado para su combinación particular de idioma, analizador y serializador.null
realidad indica que tiene un nuevo tipo de mensaje por completo. Puede ser más limpio para sus consumidores el formato de serialización simplemente especificar un tipo de mensaje completamente diferente. Esto garantiza que su validación y lógica de aplicación puedan tener una separación clara entre las dos distinciones de mensajes que proporciona su interfaz web.Consejo general
null
no puede ser un valor en un borde o interfaz que no lo admite. Si está utilizando algo que es extremadamente suelto en la tipificación de valores de propiedades (es decir, JSON), intente introducir alguna forma de esquema o validación en el software de borde de los consumidores (por ejemplo, Esquema JSON ) si puede. Si se trata de una API de lenguaje de programación, valide la entrada del usuario de forma estática si es posible (a través de la escritura) o tan fuerte como sea razonable en tiempo de ejecución (también conocido como practicar la programación defensiva en interfaces orientadas al consumidor). Lo que es más importante, documente o defina el borde para que no haya dudas en cuanto a:fuente
Aquí mi análisis personal de estas preguntas. No está respaldado por ningún libro, trabajo, estudio o lo que sea, solo mi experiencia personal.
Cadenas vacías como
null
Esto es un no-go para mí. No mezcle la semántica de una cadena vacía con la de no definida. En muchos casos, pueden ser perfectamente intercambiables, pero puede encontrarse con casos en los que no definido y definido pero vacío significa algo diferente.
Un tipo de ejemplo estúpido: digamos que hay un atributo que almacena una clave foránea, y ese atributo no está definido o es
null
, eso significaría que no hay una relación definida, mientras que una cadena vacía""
podría entenderse como una relación definida y el La identificación del registro externo es esa cadena vacía.No definido vs
null
Este no es un tema blanco o negro. Hay ventajas y desventajas de ambos enfoques.
A favor de la definición explícita de
null
valores, existen estos pros:A favor de asumir que una clave no existente es igual a la semántica de
null
:En caso de que la API sea de alguna manera estable, y la documente a fondo, creo que está perfectamente bien decir que una clave inexistente equivale al significado de
null
. Pero si es más desordenado y caótico (como suele serlo), creo que puede evitar los dolores de cabeza si define explícitamente cada valor en cada mensaje. Es decir, si tengo dudas, tiendo a seguir el enfoque detallado.Dicho todo esto, lo más importante: declara tus intenciones claramente y sé coherente. No hagas una cosa aquí y la otra allá. El software predecible es un mejor software.
fuente
null
. Otro ejemplo: en un juego, hay un objeto de personaje y tiene un atributo "compañero". Unnull
socio significa claramente que no hay ningún socio, pero""
puede entenderse como un socio cuyo nombre es""
.null
cadena vacía. Tal vez renderizándolo en un formulario, pero nunca en el modelo de datos.name
que estaba hablando, ¿permitiría que el nombre del socio sea nulo?Proporcionaría una cadena vacía en una situación en la que hay una cadena presente, y resulta ser una cadena vacía. Proporcionaría nulo en una situación en la que quiero decir explícitamente "no, estos datos no están allí". Y omita la clave para decir "no hay datos allí, no se moleste".
Usted juzga cuál de estas situaciones puede suceder. ¿Tiene sentido que su aplicación tenga cadenas vacías? ¿Desea distinguir entre decir explícitamente "sin datos" usando nulo e implícitamente sin valor? Solo debe tener ambas posibilidades (nula y sin clave presente) si el cliente necesita distinguir ambas.
Ahora tenga en cuenta que se trata de transmitir datos. Lo que hace el receptor con los datos es su negocio, y harán lo que les sea más conveniente. El receptor debe poder manejar todo lo que le arroje (posiblemente rechazando los datos) sin fallar.
Si no hay otras consideraciones, transmitiría lo que sea más conveniente para el remitente y lo documentaría . Prefiero no enviar valores ausentes porque es probable que esto mejore la velocidad de codificación, transmisión y análisis de JSON.
fuente
Aunque no puedo decir qué es lo mejor , casi con certeza no es un simple detalle de implementación , cambia la estructura de cómo puede interactuar con esa variable.
Si algo puede ser nulo , siempre debe tratarlo como si fuera nulo en algún momento , por lo que siempre tendrá dos flujos de trabajo , uno para nulo y otro para una cadena válida. Un flujo de trabajo dividido no es necesariamente algo malo, ya que hay bastante manejo de errores y usos de casos especiales que podría utilizar, pero ofusca su código.
Si siempre interactúa con la cadena de la misma manera , probablemente será más fácil que la funcionalidad permanezca en su cabeza .
Entonces, como con cualquier pregunta de "qué es lo mejor", me queda la respuesta: depende . Si desea dividir su flujo de trabajo y capturar más explícitamente cuando algo no está configurado, use nulo. Si prefiere que el programa siga haciendo lo que hace, use una cadena vacía. Lo importante es que usted sea consistente , elija un rendimiento común y siga con eso.
Teniendo en cuenta que está creando una API, le recomendaría que se adhiera a una cadena vacía, ya que hay menos para que el usuario compense, porque como usuario de una API no sabré todas las razones por las que su API podría darme un valor nulo a menos que usted ' están muy bien documentados, lo que algunos usuarios no leerán de todos modos.
fuente
string
s, nunca son nulos. Si la API usa nulo, en algún momento el productor necesita crear estonull
para cumplir con la API. Entonces el consumidor necesita manejarnull
también. Pero creo que entendí lo que estás diciendo, solo decide y define la API con autoridad, ¿verdad? ¿Eso significa que no hay nada malo con ninguno de ellos?¡Documento!
TL; DR>
Haz lo que te parezca conveniente: a veces el contexto en el que se usa es importante. Ejemplo, enlazar variables a un Oracle SQL: la cadena vacía se interpreta como NULL.
Simplemente diría: asegúrese de documentar cada escenario mencionado
Su código puede actuar de diferentes maneras: documente cómo reacciona su código:
Luego, además de eso, depende de usted comportarse de manera consistente y posiblemente adoptar algunas de sus mejores prácticas. Documentar ese comportamiento consistente. Ejemplos:
fuente
tl; dr - si lo usa: sea consistente en lo que significa.
Si lo incluyeras
null
, ¿qué significaría? Hay un universo de cosas que podría significar. Un valor simplemente no es suficiente para representar un valor perdido o desconocido (y estas son solo dos de las innumerables posibilidades: por ejemplo, Desaparecido - se midió, pero aún no lo sabemos. Desconocido - no intentamos medir eso.)En un ejemplo que encontré recientemente, un campo podría estar vacío porque no se informó que protegiera la privacidad de alguien, pero se conocía del lado del remitente, no se conocía del lado del remitente, pero se lo conoce al reportero original o se desconoce para ambos. Y todo esto le importaba al receptor. Por lo general, un valor no es suficiente.
Con una suposición de mundo abierto (simplemente no sabes acerca de las cosas no mencionadas), simplemente lo dejarías fuera y podría ser cualquier cosa. Con la suposición de mundo cerrado (las cosas que no se mencionan son falsas, por ejemplo en SQL) es mejor dejar claro qué
null
significa y ser lo más coherente posible con esa definición ...fuente