Aaron Benton es un arquitecto experimentado especializado en soluciones creativas para desarrollar aplicaciones móviles innovadoras. Tiene más de 10 años de experiencia en desarrollo full stack, incluyendo ColdFusion, SQL, NoSQL, JavaScript, HTML y CSS. Aaron es actualmente Arquitecto de Aplicaciones para Shop.com en Greensboro, Carolina del Norte y es un Campeón de la comunidad Couchbase.

FakeIt Series 3 de 5: Modelos Lean a través de definiciones
En nuestro post anterior FakeIt Serie 2 de 5: Datos Compartidos y Dependencias vimos cómo crear dependencias multi-modelo con FakeIt. Hoy vamos a ver cómo podemos crear lo mismo, pero modelos más pequeños aprovechando las definiciones.
Las definiciones son una forma de crear conjuntos reutilizables dentro de su modelo. Le permite definir un conjunto de propiedades / valores una vez, haciendo referencia a ellos varias veces a través de su modelo. Definiciones en un modelo FakeIt son muy similares a cómo las definiciones se utilizan en el Swagger / Especificación API abierta.
Modelo de usuario
Comenzaremos con nuestro modelo users.yaml que definimos en nuestro archivo primer mensaje.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
name: Users type: object key: _id properties: _id: type: string description: The document id built by the prefix "user_" and the users id data: post_build: `user_${this.user_id}` doc_type: type: string description: The document type data: value: user user_id: type: integer description: An auto-incrementing number data: build: document_index first_name: type: string description: The users first name data: build: faker.name.firstName() last_name: type: string description: The users last name data: build: faker.name.lastName() username: type: string description: The username data: build: faker.internet.userName() password: type: string description: The users password data: build: faker.internet.password() email_address: type: string description: The users email address data: build: faker.internet.email() created_on: type: integer description: An epoch time of when the user was created data: build: new Date(faker.date.past()).getTime() |
Digamos que tenemos un nuevo requerimiento donde tenemos que soportar una dirección de casa y trabajo para cada usuario. Basándonos en este requisito, hemos decidido crear una propiedad de nivel superior llamada direcciones que contendrá propiedades anidadas de casa y trabajo.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ ... "addresses": { "home": { "address_1": "123 Broadway St", "address_2": "Apt. C", "locality": "Greensboro", "region": "NC", "postal_code": "27409", "country": "US" }, "work": { "address_1": "321 Morningside Ave", "address_2": "", "locality": "Greensboro", "region": "NC", "postal_code": "27409", "country": "US" } } } |
Nuestro modelo users.yaml tendrá que ser actualizado para soportar estas nuevas propiedades de dirección.
(En aras de la brevedad, se han omitido las demás propiedades de la definición del modelo)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
... properties: ... addresses: type: object description: An object containing the home and work addresses for the user properties: home: type: object description: The users home address properties: address_1: type: string description: The address 1 data: build: `${faker.address.streetAddress()} ${faker.address.streetSuffix()}` address_2: type: string description: The address 2 data: build: chance.bool({ likelihood: 35 }) ? faker.address.secondaryAddress() : null locality: type: string description: The city / locality data: build: faker.address.city() region: type: string description: The region / state / province data: build: faker.address.stateAbbr() postal_code: type: string description: The zip code / postal code data: build: faker.address.zipCode() country: type: string description: The country code data: build: faker.address.countryCode() work: type: object description: The users home address properties: address_1: type: string description: The address 1 data: build: `${faker.address.streetAddress()} ${faker.address.streetSuffix()}` address_2: type: string description: The address 2 data: build: chance.bool({ likelihood: 35 }) ? faker.address.secondaryAddress() : null locality: type: string description: The city / locality data: build: faker.address.city() region: type: string description: The region / state / province data: build: faker.address.stateAbbr() postal_code: type: string description: The zip code / postal code data: build: faker.address.zipCode() country: type: string description: The country code data: build: faker.address.countryCode() |
Como puedes ver nuestras propiedades de dirección de casa y trabajo contienen exactamente las mismas propiedades anidadas. Esta duplicación hace que nuestro modelo sea más grande y verboso. Además, ¿qué pasa si nuestros requisitos de dirección tienen que cambiar? Tendríamos que hacer dos actualizaciones para mantener la misma estructura. Aquí es donde podemos aprovechar las definiciones, definiendo una única forma de crear una dirección y referenciarla.
(En aras de la brevedad, se han omitido las demás propiedades de la definición del modelo)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
... properties: ... addresses: type: object description: An object containing the home and work addresses for the user properties: home: description: The users home address schema: $ref: '#/definitions/Address' work: description: The users work address schema: $ref: '#/definitions/Address' definitions: Address: type: object properties: address_1: type: string description: The address 1 data: build: `${faker.address.streetAddress()} ${faker.address.streetSuffix()}` address_2: type: string description: The address 2 data: build: chance.bool({ likelihood: 35 }) ? faker.address.secondaryAddress() : null locality: type: string description: The city / locality data: build: faker.address.city() region: type: string description: The region / state / province data: build: faker.address.stateAbbr() postal_code: type: string description: The zip code / postal code data: build: faker.address.zipCode() country: type: string description: The country code data: build: faker.address.countryCode() |
Las definiciones se definen en la raíz del modelo especificando una propiedad definitions: y, a continuación, el nombre de la definición. Las definiciones se referencian mediante $ref, cuyo valor es la ruta a la definición, por ejemplo #/definitions/Address. Mediante el uso de definiciones hemos ahorrado casi 30 líneas de código en nuestro modelo y hemos creado un único lugar para definir y generar una dirección dentro de nuestro modelo de usuarios.
Podemos probar la salida de las direcciones de nuestro modelo de usuarios actualizado utilizando el siguiente comando:
|
1 |
fakeit console --count 1 models/users.yaml |

Ahora, digamos que tenemos un requisito para almacenar un número de teléfono principal de los usuarios, y luego almacenar los números de teléfono adicionales opcionales es decir, Casa, Trabajo, Móvil, Fax, etc. Para este cambio vamos a utilizar dos nuevas propiedades de nivel superior: main_phone y additional_phones que es una matriz.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ ... "main_phone": { "phone_number": "7852322322", "extension": null }, "additional_phones": [ { "phone_number": "3368232032", "extension": "3233", "type": "Work" }, { "phone_number": "4075922921", "extension": null, "type": "Mobile" } ] } |
Si bien este puede no ser el modelo de datos más práctico, o cómo yo personalmente habría modelado estos datos podemos utilizar este ejemplo de nuevo para ilustrar cómo podemos aprovechar el uso de definiciones dentro de nuestro modelo FakeIt.
(En aras de la brevedad, se han omitido las demás propiedades de la definición del modelo)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
... properties: ... main_phone: description: The users main phone number schema: $ref: '#/definitions/Phone' data: post_build: | delete this.main_phone.type return this.main_phone additional_phones: type: array description: The users additional phone numbers items: $ref: '#/definitions/Phone' data: min: 1 max: 4 definitions: Phone: type: object properties: type: type: string description: The phone type data: build: faker.random.arrayElement([ 'Home', 'Work', 'Mobile', 'Other' ]) phone_number: type: string description: The phone number data: build: faker.phone.phoneNumber().replace(/[^0-9]+/g, '') extension: type: string description: The phone extension data: build: chance.bool({ likelihood: 30 }) ? chance.integer({ min: 1000, max: 9999 }) : null |
Para este ejemplo hemos creado una definición de Phone que contiene 3 propiedades: type, phone_number y extension. Observará que hemos definido una función post_build en la propiedad main_phone que elimina el atributo type. Esto ilustra cómo se pueden utilizar las definiciones junto con una función de construcción para manipular lo que devuelve la definición. La propiedad additional_phones es un array de definiciones de teléfono que generarán entre 1 y 4 teléfonos. Podemos probar la salida de nuestros números de teléfono actualizados del modelo Users usando el siguiente comando:
|
1 |
fakeit console --count 1 models/users.yaml |

Conclusión
Las definiciones le permiten racionalizar sus modelos FakeIt mediante la creación de conjuntos reutilizables de código para modelos más pequeños y eficientes.
A continuación
- FakeIt Series 4 de 5: Trabajar con datos existentes
- FakeIt Series 5 de 5: Desarrollo móvil rápido con Sync-Gateway
Anterior
- FakeIt Serie 1 de 5: Generación de datos falsos
- FakeIt Serie 2 de 5: Datos compartidos y dependencias
Este post forma parte del Programa de Escritura de la Comunidad Couchbase