5
\$\begingroup\$

I am writing a function to calculate the total size of a "player appearance".

There are various "item slots" the player has, and if they are empty then 1 byte will be sent, otherwise there will be 2.

const getAppearanceBlockSize = (appearance: PlayerAppearance) => {
    const headObscured = isCoveringHead(appearance.outfit.head);

    return (
        40
        + (appearance.outfit.head ? 2 : 1)
        + (appearance.outfit.cape ? 2 : 1)
        + (appearance.outfit.amulet ? 2 : 1)
        + (appearance.outfit.weapon ? 2 : 1)
        + (appearance.outfit.shield ? 2 : 1)
        + (appearance.outfit.head ? 2 : 1)
        + (headObscured ? 2 : 4)
    );
};

The code seems fairly clear to me, but Code Climate has given it a high "cognitive complexity" score - indicating that the code is complex and should be broken up.

I can't think of any ways to break the code up, however, that wouldn't result in it being more complex than it currently is.

\$\endgroup\$

4 Answers 4

1
\$\begingroup\$

I don't know anything about CodeClimate or how it determines complexity, but this is the likely culprit right here:

return (
    40
    + (appearance.outfit.head ? 2 : 1)
    + (appearance.outfit.cape ? 2 : 1)
    + (appearance.outfit.amulet ? 2 : 1)
    + (appearance.outfit.weapon ? 2 : 1)
    + (appearance.outfit.shield ? 2 : 1)
    + (appearance.outfit.head ? 2 : 1)
    + (headObscured ? 2 : 4)
);

This is pretty hard to read and understand at a glance, and all of the ternary operators certainly don't help. Without knowing more about your object it is hard to review, but to me it would make more sense to have a method like this on your outfit object

function getSlotSize(slot) {
    let size = 0;
    if (this.slots.includes(slot)) {
        size = slotIsEmpty(slot) ? 2 : 1;
        if (slot === "head") {
            size += 2 * isCoveringHead(this.head);
        }
    }

    return size;
}

function slotIsEmpty(slot) {
    return this.[slot] === null || this.[slot] === undefined;
}

Now you've separated out your logic for determining the size of everything instead of having to jam it into one function.

An even better approach may be to OOP this, and create objects representing a slot (or a specific kind of slot) and then each one should have a getSize method. Without knowing more about your code it is hard to say whether or not that would be overkill.

\$\endgroup\$
1
  • \$\begingroup\$ Typo in bottom function this.[ has a dot . \$\endgroup\$
    – Blindman67
    Commented Jul 27, 2018 at 19:35
1
\$\begingroup\$

The block size calculations should actually be part of the outfit.
As items are added (worn) that size is increased, as items are removed (dropped) it is decreased. At no point should you have to iterate all the items to know the size.

So the code should actually be

const appearanceBlockSize = ({appearance: PlayerAppearance}) =>appearance.outfit.blockSize;
\$\endgroup\$
0
\$\begingroup\$

One option you can try:

return (
    40 + 5 + 2
    + !!appearance.outfit.head
    + !!appearance.outfit.cape
    + !!appearance.outfit.amulet
    + !!appearance.outfit.weapon
    + !!appearance.outfit.shield
    + 2 * headObscured
);

Take the base size 40, add 5 for the empty head/cape/amulet/weapon/shield slots (btw in your code you listed the head slot twice), and 2 for the headObscured flag's default false status. Then, coerce each slot to a boolean value, which in turn gets converted into the number 1 or 0 by the + operator, thus adding 1 byte for each occupied slot. Finally, add 2 if the headObscured flag is true.

\$\endgroup\$
-1
\$\begingroup\$

You may loose the benefit of TS here, but you could do something like this

const getAppearanceBlockSize = (appearance: PlayerAppearance) => {
   let score = isCoveringHead(appearance.outfit.head)? 4 :2;

    ['head', 'cape', 'amulet', 'weapon', 'shield']
     .forEach(p => score+= (appearance.outfit[p]? 2 : 1));

   return score + 40;
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Code Review! You have presented an alternative solution, but haven't reviewed the code. Please explain your reasoning (how your solution works and why it is better than the original) so that the author and other readers can learn from your thought process. \$\endgroup\$ Commented Jul 30, 2018 at 19:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.