Skip to content

Instantly share code, notes, and snippets.

@sanandnarayan
Last active July 23, 2025 06:24
Show Gist options
  • Select an option

  • Save sanandnarayan/cb77dc2d9e119f8cda9e0d7a881b656b to your computer and use it in GitHub Desktop.

Select an option

Save sanandnarayan/cb77dc2d9e119f8cda9e0d7a881b656b to your computer and use it in GitHub Desktop.
Complex vs Simple , TS example , Rich Hickey
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Complexity vs. Simplicity Toolkit</title>
<style>
body{font-family:Arial,Helvetica,sans-serif;margin:0;padding:0;line-height:1.4;background:#fafafa;color:#222;}
h1{text-align:center;padding:24px 0;margin:0;background:#1e1e1e;color:#fff;}
section{display:flex;flex-wrap:wrap;border-bottom:1px solid #ddd;padding:24px;}
.side{flex:1 1 50%;box-sizing:border-box;padding:0 16px;}
.complex{background:#fff8f6;}
.simple{background:#f6fff8;}
h3{margin:0 0 8px 0;font-size:1.2rem;}
p{margin:4px 0 12px 0;}
pre{background:#f6f8fa;border:1px solid #e1e4e8;padding:12px;overflow:auto;border-radius:4px;font-size:0.9rem;}
code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;}
</style>
</head>
<body>
<h1>Complexity ⇄ Simplicity Toolkit</h1>
<!-- 1 -->
<section>
<div class="side complex">
<h3>State / Objects</h3>
<p><strong>Complects:</strong> value, identity, time</p>
<pre><code class="language-ts">class Counter {
private n = 0;
inc() { this.n++; }
value() { return this.n; }
}
const c = new Counter();
c.inc();</code></pre>
</div>
<div class="side simple">
<h3>Values</h3>
<p><strong>Get it via:</strong> final, persistent collections</p>
<pre><code class="language-ts">const bump = (n: number) => n + 1;
const n2 = bump(0);</code></pre>
</div>
</section>
<!-- 2 -->
<section>
<div class="side complex">
<h3>Methods</h3>
<p><strong>Complects:</strong> function + state + namespace</p>
<pre><code class="language-ts">class User {
constructor(public age: number) {}
incrementAge() { this.age++; }
}
const u = new User(30);
u.incrementAge();</code></pre>
</div>
<div class="side simple">
<h3>Functions / Namespaces</h3>
<p><strong>Get it via:</strong> stateless methods</p>
<pre><code class="language-ts">interface User { age: number }
export const incrementAge = (u: User) => ({ ...u, age: u.age + 1 });</code></pre>
</div>
</section>
<!-- 3 -->
<section>
<div class="side complex">
<h3>Variables (<code>var</code>)</h3>
<p><strong>Complects:</strong> value + time</p>
<pre><code class="language-ts">let clicks = 0;
document.body.onclick = () => ++clicks;</code></pre>
</div>
<div class="side simple">
<h3>Managed refs</h3>
<p><strong>Get it via:</strong> RxJS / Immer refs</p>
<pre><code class="language-ts">const clicks = new BehaviorSubject(0);
document.body.onclick = () => clicks.next(clicks.value + 1);</code></pre>
</div>
</section>
<!-- 4 -->
<section>
<div class="side complex">
<h3>Inheritance / Switch</h3>
<p><strong>Complects:</strong> multiple who/what pairs</p>
<pre><code class="language-ts">abstract class Animal { abstract speak(): string; }
class Dog extends Animal { speak() { return "woof"; } }
function talk(a: Animal) { a.speak(); }
talk(new Dog());</code></pre>
</div>
<div class="side simple">
<h3>Polymorphism a la carte</h3>
<p><strong>Get it via:</strong> interfaces / protocols</p>
<pre><code class="language-ts">interface Speak { speak(): string }
const dog: Speak = { speak: () => "woof" };
const talk = (s: Speak) => s.speak();</code></pre>
</div>
</section>
<!-- 5 -->
<section>
<div class="side complex">
<h3>Syntax‑driven branching</h3>
<p><strong>Complects:</strong> meaning + order</p>
<pre><code class="language-ts">function calc(op: "add" | "sub", a: number, b: number) {
if (op === "add") return a + b;
if (op === "sub") return a - b;
}
calc("add", 3, 4);</code></pre>
</div>
<div class="side simple">
<h3>Data‑driven dispatch</h3>
<p><strong>Get it via:</strong> maps / arrays / JSON</p>
<pre><code class="language-ts">const ops = {
add: (a: number, b: number) => a + b,
sub: (a: number, b: number) => a - b,
};
const res = ops["add"](3, 4);</code></pre>
</div>
</section>
<!-- 6 -->
<section>
<div class="side complex">
<h3>Imperative loops</h3>
<p><strong>Complects:</strong> what + how</p>
<pre><code class="language-ts">let total = 0;
for (let i = 0; i < nums.length; i++) {
total += nums[i];
}</code></pre>
</div>
<div class="side simple">
<h3>Set functions</h3>
<p><strong>Get it via:</strong> <code>map</code>, <code>reduce</code>, etc.</p>
<pre><code class="language-ts">const total = nums.reduce((a, b) => a + b, 0);</code></pre>
</div>
</section>
<!-- 7 -->
<section>
<div class="side complex">
<h3>Actors</h3>
<p><strong>Complects:</strong> what + who</p>
<pre><code class="language-ts">class MailActor {
private inbox: Msg[] = [];
send(msg: Msg) {
this.inbox.push(msg);
this.process();
}
private process() {
/* handle inbox */
}
}
const mailer = new MailActor();
mailer.send(msg);</code></pre>
</div>
<div class="side simple">
<h3>Queues</h3>
<p><strong>Get it via:</strong> libraries</p>
<pre><code class="language-ts">const queue: Msg[] = [];
queue.push(msg);
const m = queue.shift();</code></pre>
</div>
</section>
<!-- 8 -->
<section>
<div class="side complex">
<h3>ORM</h3>
<p><strong>Complects:</strong> objects + SQL + state</p>
<pre><code class="language-ts">await userRepository.save(user);
const row = await userRepository.findOne({ where: { id } });</code></pre>
</div>
<div class="side simple">
<h3>Declarative data manipulation</h3>
<p><strong>Get it via:</strong> SQL / LINQ / Datalog</p>
<pre><code class="language-ts">const rows = await db.query`
SELECT id, name
FROM users
WHERE id = ${id}
`;</code></pre>
</div>
</section>
<!-- 9 -->
<section>
<div class="side complex">
<h3>Conditionals everywhere</h3>
<p><strong>Complects:</strong> scattered business rules</p>
<pre><code class="language-ts">let discount = 0;
if (cust.vip && order.total > 1000) {
discount = 0.1;
}</code></pre>
</div>
<div class="side simple">
<h3>Rules</h3>
<p><strong>Get it via:</strong> rule tables / engines</p>
<pre><code class="language-ts">const rules = [
{ if: (c: Cust, o: Ord) => c.vip && o.total > 1000, discount: 0.1 },
];
const d = rules.find(r => r.if(cust, order))?.discount ?? 0;</code></pre>
</div>
</section>
<!-- 10 -->
<section>
<div class="side complex">
<h3>Inconsistency</h3>
<p><strong>Complects:</strong> partial updates, uncertainty</p>
<pre><code class="language-ts">await db.update(...);
await db.insert(...); // risk of partial failure</code></pre>
</div>
<div class="side simple">
<h3>Consistency</h3>
<p><strong>Get it via:</strong> transactions, immutable values</p>
<pre><code class="language-ts">await db.transaction(async tx => {
await tx.update(...);
await tx.insert(...);
});</code></pre>
</div>
</section>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment