While staring to code I have done a lot of mistakes and that helped me learn new concepts in JavaScript and the DRY principle. Consider the below transformation logic.
// The source data type coming to be transformed
interface ISourceData {
id: number;
name: string;
email: string;
country: string;
active: boolean;
isPro: boolean;
}
// The data that will be loaded to the db
interface ITargetData extends ISourceData {
modifiedBy: string;
modifiedOn: string;
createdBy: string;
createdOn: string;
isValid: boolean;
}
During my initial development days I would have written my code like this:
class Transformation {
public async transform(data: ISourceData[]) {
const transformedData = data.map((item) => {
let isValid = false;
if (item.active === true && item.isPro === true) {
isValid = true;
}
const modifiedBy = "System1";
const modifiedOn = new Date().toDateString();
const createdBy = "System1";
const createdOn = new Date().toDateString();
return {
id: item.id,
name: item.name,
email: item.email,
country: item.country,
active: item.active,
isPro: item.isPro,
isValid: isValid,
modifiedBy: modifiedBy,
modifiedOn: modifiedOn,
createdBy: createdBy,
createdOn: createdOn,
} as ITargetData;
});
// Loading the data to database
transformedData.forEach(async (item) => await loadToDb(item));
}
}
This code have 1 major issue and can be written in a much better way.
Issue:
async-await does not work withforEach
. So the flow will not be asynchronous.
Now, here is how I write codes now, Which I will improve if needed.
const CREATED_BY_USER = "System1";
class Transformation2 {
public async transform(data: ISourceData[]) {
for (const item of data) {
const transformedData = this.getTransformedData(item);
await this.loadToDb(transformedData)
}
}
private getTransformedData(sourceData: ISourceData): ITargetData {
return {
...sourceData,
...this.getIsValid(sourceData.active, sourceData.isPro),
...this.generateDefaults(),
} as ITargetData;
}
private getIsValid(active: boolean, isPro: boolean) {
return { isValid: active && isPro };
}
private generateDefaults() {
const transformationDate: string = new Date().toISOString();
return {
modifiedBy: CREATED_BY_USER,
modifiedOn: transformationDate,
createdBy: CREATED_BY_USER,
createdOn: transformationDate,
};
}
private async loadToDb(data: ITargetData): Promise<void>{
// logic to load the data to database
}
}
You can see the difference clearly,
- Multiple private methods that have specific tasks.
- CREATED_BY_USER const variable as it won't change.
- transformationData is now an ISO string instead of date & day earlier : "Wed Aug 31 2022" now: "2022-08-31T09:30:16.579Z"
- getIsValid method working specifically to get me the isValid key data.
- De-structuring to get the data into the format needed.
- for-of loop that works perfectly with async-await.
If you like the post follow me for more
Top comments (0)