Interweaving Data Models
This is part 4 of a 5 part series on SMAG Directory Structure. To read part 3, on Data GraphQL Directory Structure, feel free to click here.
A data model is an abstract model, that organizes different data, and how they relate to each other. Interfaces in Typescript, very much so cater to this cause. Coupling various functionality together is arguably Typescript’s greatest strength. Imagine 40 functions using the same data-model of various required properties. If we add a single required property, or change/update a single required property, the compiler will complain about the 40 functions that now need to be updated. This is valuable. There are many more benefits that are beyond this chapter. However, what we have already touched on, is that having a central location for interfaces, that can be easily re-used throughout the application is fantastic.
Dilemma with interfaces in Typescript
In any enterprise data-heavy app, most interfaces are used in unison with data from the backend. In an Angular setting, this means that we will use a service to make the request. In addition, we will feed the data through the entire ngrx/store pipeline, for http requests. This would be Effect > Action > Action > Reducer.
In addition, inside the component consuming this data, we will also need to use the interface. We want to make sure that there aren’t any use cases that we do not test properly. Data types can be unique. We might miss because of data type(array, dictionary, object), some particular use case. Integrating data types of components is important. Keeping the following scenarios in mind:
- Data Services
- ngrx/store pipeline (Data Access)
- Component (Consuming business logic)
- Unit Tests
What would be the ideal location for us to place our interfaces?
Data Models Directory Structure
Data Models are unique because they tie everything together. Data Models also seems like an appropriate name for the folder containing these interfaces. It is important to note that not all interfaces will go into this folder, but interfaces related to data being pulled in from the backend. In addition, interfaces created because of interacting with the aforementioned data.
libs |-- px-illustrator/ | |-- data-models/ | | |-- src/ | | | |-- lib/ | | | | |-- user/ | | | | | |-- user.interface.ts | | | | | +-- user.mock.ts | | |-- index.ts | | +-- test.ts | |-- karma.conf,file | |-- README.md,file | |-- tsconfig.lib,file | |-- tsconfig.lib.json,file | |-- tsconfig.spec.json,file] | +-- tslint.json,file
Ending off — Data Mocks
We have also coupled mocks with each interface. These mocks help with unit tests. By keeping them with the interface, it eases the ability to update when an interface is updated as well. The importance of mocks depends based on app and feature. Arguably, for most scenarios, it is of less importance that these be kept to date, as long as general integrity of data is represented closely. However, as a rule of thumb hooking mocks directly into interfaces, so that they closely represent interface, is the easiest way to make sure unit tests cover all use cases. So, therefore, making it the best practice to do so is ideal.