Duda estructura DTO

Ranthas

#30 Ahora el mal diseño es el que he planteado yo.

En este supuesto, Portatil y Sobremesa no pueden ser atributos del ordenador. Son ordenadores, por tanto, deberían ser subclases, y no atributos.

1 respuesta
desu

#31 Si bueno, no era el mejor ejemplo porque es una relacion "es" yo quiero una relacion "tiene".

Un Ordenador tiene RAM, si es portatil tiene un tipo de RAM si es sobremesa tiene otro tipo especifico con características distintas.

Yo envio Ordenadores y el cliente quiere acceder a su ram y tratarla dependiendo de si es sobremesa o portatil.

edit: igualmente el tema de la subclase es interesante, imagino que al evaluar el cliente debe conocer la estructura y el json prueba las interficies hasta que una tira. por lo tanto tampoco funcionaria dos subclases con la misma estructura de tipado.

1 respuesta
MisKo

Por lo que se (que tampoco es mucho) Json no hace lo q quieres y angular tampoco. Eres tu quien le indicas manualmente a que modelo corresponde los datos q devuelve la request

En tu ejemplo, si quieres acceder a la ram deberías asegurarte de que la interfaz incluye el método getRam(), de que las clases sobremesa y portátil lo implementen y acceder a la información a través de dicho método.

Eso o no he entendido una mierda de lo que quieres hacer, que también es lo normal.

PD: estoy desde el.mvl por si algo aparece raro

Interface Foo {
  uid: number,
  first_name: string,
  last_name: string,
  token: string
}

this.httpClient.get<Foo>(
    'http://api.example.com/api/get_user'
).pipe(
    tap((receivedData: Foo) => console.log(receivedData)),
    map((receivedData: Foo) => {
        return new RegularUser(
            receivedData.uid, 
            receivedData.first_name, 
            receivedData.last_name, 
            receivedData.token);
    })
);

He hecho copy paste de algo de inet, pero ahí se ve que al final, eres tu quien indica a que lo mapeas.

Korvael

#15 No te preocupes, él tampoco.

brew

#32 No te vale con comparar si el objeto que recibes es igual a tu clase?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

1 respuesta
MisKo

#35 creo q lo quiere saber es si, con un json, angular es capaz de analizarlo e inferir el tipo de clase al que hay q asociar esa estructura.

Yo no estoy muy puesto en angular/typescript pero diría q no lo hace automático y se lo tienes que indicar manualmente

1 respuesta
desu

#36 Si eso era una parte, la otra erasi JSON no es capaz, entonces cual es la buena práctica.

Renombrar todos los campos o poner una etiqueta?.

1 respuesta
NoRelaX

El componente Typescript que vaya a consumir ese objeto JSON no va a saber de qué "tipo" es el objeto no ser que tú se lo especifiques y le añadas un mapeo.

MisKo

#37 Pues realmente ahí depende de lo que se vaya a hacer en el front.

Si necesitas llamar al mismo método implementado de manera distinta en cada clase, tendrás que agregar un atributo que indique el tipo y tenerlo en cuenta para castear manualmente el objeto a la clase acorde.

Si el método es el mismo para ambos, podrías castearlo todos los objetos a una clase padre independientemente del tipo.

Si realmente el tipo cambia la funcionalidad del front (segun el tipo hace unas cosas u otras), lo ideal sería tener 2 endpoints y que cada una devuelva un tipo concreto de objeto (y desde angular, que llame a ambos endpoints)

Soulscx

haz un metodo get portatiles y get sobremesa , pero como dicen si tienes q diferenciar dos cosas con los mismos campos entonces tienes un fallo de diseño anterior.

desu

Gracias a todos, veo triste que se pierda ese polimorfismo y haya que modificar o bien tu modelo o bien tu api para que funcione por las limitaciones del JSON.

1 respuesta
MisKo

#41 No termino de entender lo que comentas de que hay que modificar la API o el modelo.

Tu al final envías el json con los atributos de un objeto desde el servidor y lo recibes directamente en el cliente, pero de alguna manera has de determinar en el cliente que el objeto es de un tipo u otro.

Si yo tengo la clase abstracta vehículo y 2 clases que heredan como coche / moto, si los atributos son potencia y tipo_gasolina como determinas en el cliente que se refiere a un coche o a una moto ?

Has de incluir algo que los diferencie, ya sea un atributo como el tipo, o programar en el cliente que si el nº de ruedas (nuevo atributo) es 2 es una moto o si es 4 es un coche...

No conozco GraphQL, pero por lo que comentas, entiendo que cuando se usa para APIs, ya se indica en el propio código de que tipo es lo que devuelve, por lo que esa 'identificación' ya la haces previamente.

Que oye, lo mismo estoy diciendo una tontería porque no he usado GraphQL en la vida xDD

JuAn4k4

JSON no tiene tipado, es un modelo de datos. JS tampoco tiene tipos, son solo objetos. Algunos fw meten el tipo (full qualified class name) en el json, que para mi es una burrada.

Tus APIs para mi tienen que devolver lo que necesite el cliente. Si pido ordenadores, tengo ordenadores, si pido portátiles, pues portatiles, etc..

Y el dto solo debería tener los campos que hagan falta.

Si quieres poder pedir portátiles y sobremesa y poder diferenciarlos, si, hace falta un campo type.

El recurso de la API define el tipo.

1 1 respuesta
desu

#43 Entoncesdebo tener dos modelos de datos para "entities", uno con los DTO con los campos adicioneles y otro con el que trabajo en el servicio. En el backend yo no necesito ninguna etiqueta, el lenguaje si tiene un buen sistema de tipado sabe diferenciar el "type constructor" que se ha utlizado.

Prefiero solo tener Entidades y Value Objects en mi codigo, añadir DTOs aparte se me hace "redundante".

No sé si me he explicado bien. Me baso en que quiero aplicar DDD, tener entidades bien definidas acopladas al dominio y no tocarlas nunca.

1 respuesta
Zerokkk

Es que ya antes de empezar, diría que #1 no se está explicando demasiado bien con respecto a cuál es su situación, y qué busca.

Yo he entendido, y quizá me equivoque, que está trabajando con un tipo de objetos que tiene varios subtipos, y que necesita exponer estos subtipos al consumidor en Angular. El problema de esto, es que sin importar el lenguaje en el que esté hecho el backend, cuando se transfieren esos datos a Angular, el tipado se pierde, así que o bien se expresa en los propios datos enviados (con una propiedad), o bien se parsea directamente en Angular al consumir datos de esa misma API.

El tema es que yo me imagino que tiene una API entry point que consume directamente todos los objetos de esas subclases. Esto tiene sentido si aprovecha polimorfismo, aplicando funciones a supertipos en lugar de a subtipos. Para esto, y con objetivo de conseguir un array de type definitions (que no entity types) del supertipo que usar en Angular, diría que el mejor truco es el siguiente:

const elemsSubClase1 = (await fetch("https://tuweb/api1")).map( elem => new SubClase1(elem));
const elemsSubClase2 = (await fetch("https://tuweb/api2")).map( elem => new SubClase2(elem));
const elemsSubClase3 = (await fetch("https://tuweb/ap3")).map( elem => new SubClase3(elem));
const allElements = elemsSubClase1.concat(elemsSubClase2).concat(elemsSubClase3);

No es el ejemplo más optimizado ni más bonito (sería mejor con Promise.all y proveyendo los entry points y handlers externamente), pero creo que se pilla un poco cuál es la idea. Cabe destacar que yo para situaciones así pondría la superclase como una clase abstracta (algo posible con Typescript, que supongo que lo usarás en tu proyecto Angular), a menos que sea estrictamente necesario instanciar objetos de esa clase. Luego las otras subclases derivarían de ella. Mejor incluso si las propiedades de estas entidades que aluden a comportamientos no necesariamente dependientes del tipo, están segregados en interfaces, pero eso es otro tema ya.

Así, al final de todo este proceso, podrás aplicar el array grande (allElements) a métodos pensados para funcionar para el supertipo, es decir, para todas las subclases.

NoRelaX

Vaya lío te estás montando.

r2d2rigo

Otro thread de desu en el que no tiene ni puta idea y se va por las ramas y aun asi se encabezona cuando la gente le dice que no lleva razon? No hombre no, eso no puede estar pasando.

1 respuesta
Wei-Yu

los extremos se tocan; afhn y desu son la misma persona

1 respuesta
desu

#47 no consiste en llevar razón, responde lo de doblar las entidades. No me queda claro. #44 por favor.


A ver yo estoy trabajando modelando un dominio.
Para ese dominio creo entidades y tendré value objects.
Yo necesito exponer mi dominio a una API.
a. Tengo que crear DTOs equivalentes a mis entidades
b.Tengo que modificar mis entididades añadiendo campos redundantes.

NoRelaX

No doblas nada, una entidad es una entidad y un DTO es un DTO.

Si en el lado front necesitas mapear los datos en una estructura concreta para manejarlos de cierta forma o añadirles una lógica no te queda otra que replicarlos.

1 respuesta
desu

#50 Voy a re-hacer mi código entonces, no voy a prostituir mis entidades.

Me parece triste que tenga que tener objetos DTO a proposito.
Me parece triste que la gente de front end no trateis de solucionar estos problemas.

Código duplicado = Más posibilidad de errores = Más dificil de mantener

Pregutna: En graphql o con otras alternativas a JSON se puede solucionar?

NoRelaX

Esas cosas pensaba yo en mi primer año programando. Después ya aprendí.

Wei-Yu

no estás duplicando nada, son responsabilidades distintas

es como decir que un repositorio duplica el código de un servicio xd

1 1 respuesta
desu

#53
Son responsabilidades impuestas por json. Eso es acoplamiento.

1 respuesta
Wei-Yu

te voy a acoplar yo la cara al suelo de un meco

1
NoRelaX

por json sí

Wei-Yu

#54 no son impuestas por json, son representaciones ligadas al contexto; qué haces con los datos de auditoría o tracking por ejemplo? exponerlos al front? Y cuando tus modelos son una agregación de varios servicios o componentes?

1 respuesta
afhn

#48 yo estaba trolleando, pero lo de desu ya no sé si es trolleo o qué.

desu

#57 En ese caso si tiene sentido.

gRpc que tal va?

1 respuesta
Fyn4r

#59 A mí me estuvieron vendiendo la moto de gRPC hace poco, el poco caso que le hice me pareció que para comunicación entre servicios tiene buena pinta

1 respuesta