Skip to content

Instantly share code, notes, and snippets.

View mpaleo's full-sized avatar
🤓
Focusing

Michael Paleo mpaleo

🤓
Focusing
  • Montevideo, Uruguay
  • 05:10 (UTC -03:00)
View GitHub Profile

Cognitive Complexity: Optimize for the Reader, Not the Linter

I've reviewed code that passed every check we had. Functions were short, lint was clean, coverage was north of ninety percent. And I still had to read it four times to understand what it did. The metrics were green and the code was a fog. That gap, between code that scores well and code a human can actually follow, is the whole reason cognitive complexity is worth talking about.

What the metric actually measures

Most of us learned cyclomatic complexity first, which counts the number of independent paths through a piece of code. It's fine for knowing how many test cases you need, but it's a poor model of how hard code is to read. A flat switch with twelve cases has high cyclomatic complexity and is trivial to understand. Three levels of nested conditionals have fewer paths and are miserable.

Cognitive complexity, introduced by SonarSource and largely credited to G. Ann Campbell, tries to measure the second thing: how much effort a person

The Wrong Abstraction Costs More Than Duplication

Every codebase I've worked on has a function that everyone is quietly afraid of. It started small and reasonable, two or three callers, a clear job. Then it grew a boolean parameter. Then another. Then an options object, a couple of early returns keyed on who was calling it, and a comment that says // don't touch unless you know what you're doing. Nobody knows what they're doing. That function is what a good intention looks like three years later.

I want to make a case that cuts against one of the first instincts we train into engineers, that duplication is the enemy. It usually isn't. The wrong abstraction is the enemy, and it's a lot more expensive than the duplication it was meant to remove.

How the wrong abstraction forms

The failure mode is almost never recklessness. It's diligence. You see two pieces of code that look alike, two components, two handlers, two mappers, and you do the responsible thing and pull out the shared part. At that moment

@babylonjs_inspector.js?v=f87d2864:60895 Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
@babylonjs_inspector.js?v=f87d2864:134076 Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
sounds.ts:17 The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. https://goo.gl/7K7WLu
setupAudioContext @ howler.js?v=d42e0af2:1770
init @ howler.js?v=d42e0af2:393
(anonymous) @ howler.js?v=d42e0af2:1904
Howl2 @ howler.js?v=d42e0af2:382
createMenuSounds @ sounds.ts:17
Splash @ splash.svelte:11
(anonymous) @ chunk-MTPAUIYB.js?v=dd900c11:283
const inmuebles = [
{
id: 1,
...
},
{
id: 2,
...
},
{
@mpaleo
mpaleo / rndriver.js
Created January 2, 2017 19:22
Lowdb react native driver based on RNFS
import RNFS from 'react-native-fs';
module.exports = {
read: (source) =>
{
return RNFS.exists(source).then((fileExists) =>
{
if (fileExists)
{
return RNFS.readFile(source).then((data) => JSON.parse(data));
---
- name: restart nginx
service: name=nginx enabled=yes state=restarted
#!/usr/bin/env bash
echo "########################################"
echo "Update the box"
echo "########################################"
# Update apt cache
sudo apt-get update
echo "########################################"