Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save fernandocanizo/582fb8cb15cf80ce280293550f8911b7 to your computer and use it in GitHub Desktop.
Save fernandocanizo/582fb8cb15cf80ce280293550f8911b7 to your computer and use it in GitHub Desktop.
Attempt at refactoring a procedural code into a more functional form. Resulting code looks more bloated than procedural version.
// Possible result as it comes from DB
let dbResults = [
{ username: 'crmeco', status: 'synchronized', count: '19' },
{ username: 'pamela', status: 'synchronized', count: '16' },
{ username: 'pamela', status: 'todo', count: '26' }
];
// Expected result:
// [
// { username: 'crmeco',
// todo: 0,
// synchronized: 19,
// confirmed: 0,
// totalCount: 19
// },
// { username: 'pamela',
// todo: 26,
// synchronized: 16,
// confirmed: 0,
// totalCount: 42
// }
// ]
// Current code making the required transformation, pure Javascript
let ret = [];
let previousUser;
let objResult = {};
dbResults.forEach(row => {
const actualUser = row.username;
const actualStatus = row.status;
const actualCount = parseInt(row.count);
if (previousUser !== actualUser) {
if (previousUser) {
ret.push(objResult);
}
previousUser = actualUser;
objResult = {
username: actualUser,
todo: 0,
synchronized: 0,
confirmed: 0,
totalCount: actualCount,
};
} else {
objResult['totalCount'] += actualCount;
}
objResult[actualStatus] = actualCount;
});
if (previousUser) {
ret.push(objResult);
}
console.log('Good ol\' imperative code solution\n', ret);
// My attempt at refactoring it (required Ramda to avoid bloating even more the solution)
const r = require('ramda');
const splitByUser = (dbResults) => {
return dbResults.reduce((acum, v) => {
acum[v.username] = acum[v.username] || [];
v.count = parseInt(v.count, 10);
acum[v.username].push(v);
return acum;
}, {});
};
const combineAndTotalizeResults = (splittedByUserResults) => {
const userKeys = Object.keys(splittedByUserResults);
return userKeys.map(
user => splittedByUserResults[user].reduce((a, v) => Object.assign(a, {
username: v.username,
[v.status]: v.count,
totalCount: a.totalCount + v.count || v.count}), {})
);
};
const addMissingFields = (o) => {
const requiredFields = ['todo', 'synchronized', 'confirmed'];
const currentFields = Object.keys(o);
const missingFields = r.difference(requiredFields, currentFields);
missingFields.forEach(f => o[f] = 0);
return o;
};
const result = combineAndTotalizeResults(splitByUser(dbResults)).map(o => addMissingFields(o));
console.log('\nRefactored results\n', result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment