Skip to content

Instantly share code, notes, and snippets.

@Rolando-Barbella
Last active June 10, 2019 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rolando-Barbella/e277764f455ce18153f090d4f67803fa to your computer and use it in GitHub Desktop.
Save Rolando-Barbella/e277764f455ce18153f090d4f67803fa to your computer and use it in GitHub Desktop.
Custom brand
import Color from "color";
import brandStore from "./brand-store";
const defaultColours = [
{ name: "primary", value: "#333" },
{ name: "secondary", value: "#222" },
{ name: "tertiary", value: "#555" },
];
const defaultBodyFont = "Lato";
const allowedFonts = ["lato", "arial", "helvetica", "courier"];
const convertToRgb = (c) => Color(c).rgb().string();
const colorReduder = (acc, colour) => {
acc[colour.name] = convertToRgb(colour.value);
return acc
};
const newColours = (colours) => colours.reduce(colorReduder, {});
const validateBodyFont = (bodyFont) => {
const hasAllowedFont = allowedFonts.includes(bodyFont.toLocaleLowerCase());
return hasAllowedFont ? bodyFont : defaultBodyFont;
};
function buildTheme(colours = defaultColours, bodyFont = defaultBodyFont) {
return {
colours: newColours(colours),
bodyFont: validateBodyFont(bodyFont),
}
};
module.exports = {
getBranding(user) {
const brands = brandStore.getAll();
if (user.brandId && brands.length) {
let brandDetails;
brands.forEach((brand) => {
if (brand.id === user.brandId) {
brandDetails = brand;
return;
};
return buildTheme(defaultColours, defaultBodyFont);
});
const { colours, bodyFont } = brandDetails;
return buildTheme(colours, bodyFont);
};
return buildTheme(brandDetails.colours, brandDetails.bodyFont);
},
};

Comments

Any comments on the code as is?

Before the refactor, there were some functions taking too much responsibility, that is why the code was split into small functions which can be easier to test, debug and read.

They are a few if and else statements that can be refactored applying functional programming as pointed in the comments or with ES6 features like the default parameters, this way the quality of the code is considerably improved.

I personally like to define constant variables like defaultBodyFont or allowedFonts in a separate file as types and name them with capitals, exp:

export const FONT_TYPES = {
    BODY_FONT: "lato",
    ALLOWED_FONTS : ["lato", "arial", "helvetica", "courier"],
}

For the brevity of the test, they were left the way it was.

How would you test it?

Using a library like Jest, I will test the "small" functions first, before testing the main one ( getBranding(user) ), this way, if there is a problem, I would have a better idea where it is and how to tackle it, exp:

test(convert colours into rgb', () => {
  expect(newColours([{ name: "primary", value: "#333" }])).toBe({ primary: "rgb(51, 51, 51)" });
})

Could you use aspects of functional programming to improve the code?

Yes, as it is showed in the optimized code.

  • The newColours and validateBodyFont could have been done in one reduce method, however, I decided to left them separate for better understanding and readability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment