una sirve servicios seguridad qué para estandares ejemplo diseñar como arquitectura rest design api-design

sirve - Diseño RESTful: ¿cuándo usar los recursos secundarios?



qué es una api rest y para qué sirve (6)

Esto es problemático porque ya no es obvio que un usuario pertenece a una empresa en particular.

A veces, esto puede resaltar un problema con su modelo de dominio. ¿Por qué un usuario pertenece a una empresa? Si cambio de compañía, ¿soy una persona completamente nueva? ¿Qué sucede si trabajo para dos compañías? ¿Soy dos personas diferentes?

Si la respuesta es sí, ¿por qué no tomar algún identificador único de la compañía para acceder a un usuario?

por ejemplo, nombre de usuario

company/foo/user/bar

(donde la bar es mi nombre de usuario que es único dentro del espacio de nombres de la compañía específica)

Si la respuesta es no, entonces ¿por qué no soy un usuario (persona) solo, y la colección de company/users me señala simplemente: <link rel="user" uri="/user/1" /> (nota: empleado parece ser más apropiado)

Ahora, fuera de su ejemplo específico, creo que las relaciones de recursos y recursos son más apropiadas cuando se trata de uso en lugar de propiedad (y es por eso que está luchando con la redundancia de identificar una empresa para un usuario que identifica implícitamente a una empresa).

Lo que quiero decir con esto es que los users son en realidad un recurso secundario de un recurso de la empresa, porque el uso es definir la relación entre una empresa y sus empleados, otra forma de decir que es: debe definir una empresa antes de poder comience a contratar empleados Del mismo modo, un usuario (persona) debe definirse (nacer) antes de poder reclutarlos.

Al diseñar las jerarquías de recursos, ¿cuándo se deben usar los sub-recursos?

Solía ​​creer que cuando un recurso no podría existir sin otro, debería representarse como su sub-recurso. Recientemente me encontré con este contraejemplo:

  • Un empleado es identificable de manera única en todas las compañías.
  • El control de acceso y el ciclo de vida de un empleado dependen de la compañía.

Lo /companies/{companyName}/employee/{employeeId} como: /companies/{companyName}/employee/{employeeId}

Aviso, no necesito buscar a la compañía para localizar al empleado, ¿por qué debería hacerlo? Si lo hago, estoy pagando un precio para buscar información que no necesito. Si no lo hago, esta URL devuelve HTTP 200 por error:

/companies/{nonExistingName}/employee/{existingId}

  1. ¿Cómo debería representar el hecho de que un recurso pertenece a otro?
  2. ¿Cómo debería representar el hecho de que un recurso no puede ser identificado sin otro?
  3. ¿Qué relaciones significan sub-recursos y no están destinados a modelar?

El problema parece ser cuando no hay una empresa específica , pero un empleado técnicamente pertenece a alguna empresa u organización; de lo contrario, podrían llamarse vagos o políticos. Ser empleado implica una relación empresa / organización en algún lugar, pero no específica. Además, los empleados pueden trabajar para más de una compañía / organización. Cuando se requiere el contexto específico de la empresa, entonces sus trabajos originales /companies/{companyName}/users/{id}

Digamos que quiere saber la contribución del EmployerContribution para su ira / rsp / pensión que usaría: /companies/enron/users/fred/EmployerContribution Obtiene la cantidad específica aportada por enron (o $ 0).

¿Qué sucede si quiere que EmployerContribution de alguna o todas las compañías trabaja para Fred (ed)?
No necesita una empresa concreta para que tenga sentido. /companies/any/employee/fred/EmployerContribution

Donde "cualquiera" es obviamente una abstracción o un marcador de posición cuando la compañía del empleado no importa, pero sí lo es un empleado. Debe interceptar el controlador de "empresa" para evitar una búsqueda de db (aunque no está seguro de por qué la empresa no se almacenará en la memoria caché, ¿cuántos pueden existir?)

Incluso puede cambiar la abstracción para representar algo así como todas las empresas para las que Fred estuvo empleado en los últimos 10 años. /companies/last10years/employee/fred/EmployerContribution


Esta es una manera de resolver esta situación:

/ companies / {companyName} / employee / {employeeId} -> devuelve datos sobre un empleado, también debe incluir los datos de la persona

/ person / {peopleId} -> devuelve datos sobre la persona

Hablar de empleado no tiene sentido sin hablar también de la empresa, pero hablar de la persona tiene sentido incluso sin una empresa e incluso si es contratado por varias empresas. La existencia de una persona es independiente de si es contratado por alguna empresa, pero la existencia de un empleo depende de la compañía.


Su regla para decidir si un recurso debe modelarse como un recurso secundario es válido. Su problema no surge de un modelo conceptual incorrecto sino que permite filtrar su modelo de base de datos en su modelo REST.

Desde un punto de vista conceptual, un employee si solo puede existir dentro de una relación de company se modela como una composition . El employee puede ser identificado a través de la company . Ahora las bases de datos entran en juego y todas employee filas de employee obtienen un identificador único.

Mi consejo es que no permita que el modelo de la base de datos se filtre en su modelo conceptual porque está exponiendo las preocupaciones de infraestructura a su API. Por ejemplo, ¿qué sucede cuando decides cambiar a una base de datos orientada a documentos como MongoDB donde puedes modelar a tus empleados como parte del documento de la empresa y ya no tiene esta identificación única artificial? ¿Te gustaría cambiar tu API?

Para responder a sus preguntas adicionales

¿Cómo debería representar el hecho de que un recurso pertenece a otro?

Composición a través de sub recursos, otras asociaciones a través de enlaces URL.

¿Cómo debería representar el hecho de que un recurso no puede ser identificado sin otro?

Use ambos valores de id en su URL de recurso y asegúrese de no permitir que su base de datos se filtre en su API comprobando si existe la "combinación".

¿Qué relaciones significan sub-recursos y no están destinados a modelar?

Los recursos secundarios se adaptan bien a las composiciones pero, en términos más generales, se explica al modelo que un recurso no puede existir sin el recurso principal y siempre pertenece a un recurso principal. Su regla when a resource could not exist without another, it should be represented as its sub-resource es una buena guía para esta decisión.


Un año después, terminé con el siguiente compromiso (para las filas de la base de datos que contienen un identificador único):

  1. Asigne todos los recursos a un URI canónico en la raíz (p /companies/{id} Ej., /companies/{id} y /employees/{id} ).
  2. Si un recurso no puede existir sin otro, debe representarse como su sub-recurso; sin embargo, trate la operación como una consulta de motor de búsqueda. Lo que significa que, en lugar de llevar a cabo la operación de inmediato, simplemente devuelve HTTP 307 ("Temporary redirect") apuntando al URI canónico. Esto hará que los clientes repitan la operación contra el URI canónico.
  3. Su documento de especificación solo debe exponer los recursos raíz que coincidan con su modelo conceptual (no depende de los detalles de implementación). Los detalles de la implementación pueden cambiar (sus filas podrían no ser identificables de manera única) pero su modelo conceptual permanecerá intacto. En el ejemplo anterior, le dirías a los clientes sobre /companies pero no /employees .

Este enfoque tiene los siguientes beneficios:

  1. Elimina la necesidad de realizar búsquedas innecesarias en la base de datos.
  2. Reduce la cantidad de verificaciones de cordura a una por solicitud. A lo sumo, debo verificar si un empleado pertenece a una empresa, pero ya no tengo que hacer dos comprobaciones de validación para /companies/{companyId}/employees/{employeeId}/computers/{computerId} .
  3. Tiene un impacto mixto en la escalabilidad de la base de datos. Por un lado, está reduciendo la contención de bloqueo al bloquear menos tablas, por un período de tiempo más corto. Pero, por otro lado, está aumentando la posibilidad de interbloqueos porque cada recurso raíz debe usar un orden de bloqueo diferente. No tengo idea de si esto es una ganancia o pérdida neta, pero me reconforta el hecho de que los bloqueos de la base de datos no pueden evitarse de ninguna manera y las reglas de bloqueo resultantes son más fáciles de comprender e implementar. En caso de duda, opte por la simplicidad.
  4. Nuestro modelo conceptual permanece intacto. Al asegurarnos de que el documento de especificación solo expone nuestro modelo conceptual, somos libres de colocar URI que contengan detalles de implementación en el futuro sin romper los clientes existentes. Recuerde, nada le impide exponer detalles de implementación en URI intermedios siempre que su especificación declare su estructura como indefinida.

si un subrecurso es identificable de manera única sin su entidad propietaria, no es un subrecurso y debe tener su propio espacio de nombre (es decir, / users / {user} en lugar de / companies / {*} / users / {user}). Lo más importante: nunca más everer usa la clave primaria de la base de datos de su entidad como el identificador del recurso. ese es el error más común donde los detalles de implementación se filtran al mundo exterior. siempre debe tener una clave comercial natural (como nombre de usuario o número de empresa, en lugar de identificación de usuario o identificación de la empresa). la singularidad de dicha clave puede imponerse mediante una restricción única, si así lo desea, pero la clave principal de una entidad nunca debe dejar nunca la capa de persistencia de su aplicación, o al menos nunca debe ser un argumento para ningún servicio. método. Si sigue esta regla, no debería tener problemas para distinguir entre composiciones (/ empresas / {empresa} / usuarios / {usuario}) y asociaciones (/ usuarios / {usuario}), porque si su subrecurso no tiene una clave comercial natural, que la identifica en un contexto global, puede estar muy seguro de que realmente es un subrecurso dependiente (o primero debe crear una clave comercial para que sea identificable globalmente).