SMAG Directory Structure — Part 4
Data Models Directory Structure
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 types of 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 on the 40 functions that
now to be updated. This is incredibly valuable. There are many more benefits
which are beyond the scope of this chapter. However, when introducing interfaces into one’s app, does introduce an interesting dilemma.
Dilemma with interfaces in Typescript
In any enterprise data heavy app, the majority of interfaces will be used in unison with data from the backend. In an Angular setting, this means that we will be using a service to make the request. In addition, we will be feeding the data through the entire ngrx/store pipeline, for http requests. This would be Effect > Action > Action > Reducer. In addition, inside of the component that will be consuming this data, we will also need to use the interface. Not to mention, if we want to tightly couple our unit tests to our 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 be missing as a result of data type(array, dictionary, object), some particular use case. Integrating data type with component as well, 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, by the fact that 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 rather interfaces related to data being pulled in from backend. In addition, interfaces created as a result of interacting with aforementioned
│ ├── 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
You will notice that 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. 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, actually 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 best practice to do so, is ideal.
Thank you for reading, and keep being amazing you!