Development

Why do I hate 2FA?

Because it’s too tightly bound to a mobile device. It seems I’ve lost access to one of my email accounts for an indefinite amount of time. I’ll skip the name of the service, it’s not very important. Today I tried to log in and failed because of their 2FA.

  • Their mobile app somehow lost my account. That sucks.
  • I still know the password, I can’t log in without going through a recovery process.
  • Their recovery process requires access to my old SIM card.
  • Luckily I have it and got the SMS
  • Then it asked for a PIN. I don’t have one. I assume they introduced PINs after I set up my 2FA account. Fine, I can skip this step.
  • Next, I had to answer a default security question like “What’s the name of the street …”. I know the answer, but I don’t know whether it’s case-sensitive.
  • Anyway,The system refuses to accept any of my attempts.
  • Now I have to go through a long process of convincing their security team that it’s actually me.
  • I’m not sure it’ll work out. I hope as the last hope I’ll be able to send them my passport data

So, why do I hate 2FA? Because it’s supposed to be a security measure. But instead it’s almost always a suffering measure.

Lazy & Suspense in React

React documentation says:

Now that your component’s code loads on demand, you also need to specify what should be displayed while it is loading. You can do this by wrapping the lazy component or any of its parents into a boundary

“Need to”? Or “must to”?

If you try to use lazy without <Suspense/> it… It works. Wow. So, is it optional?

HELL NO! You must wrap your lazy components with <Suspense/>.

Why? Because such non-connected components can put React’s reconciliation engine into a semi-broken, hung state where behavior becomes unpredictable. It gets auto-healed only when the lazy promise is fulfilled.

So, if you don’t want to play hide & seek in a mine field — do it. Wrap it with <Suspense/> even if you don’t plan to render any fallback JSX.

Math namespace in HTML

TIL: HTML partially supports math:

<math>
  <mrow>
    <mi>a</mi>
    <mo>=</mo>
    <mfrac>
      <mrow>
        <mo>-</mo>
        <mi>b</mi>
        <mo>±</mo>
        <msqrt>
          <msup><mi>b</mi><mn>2</mn></msup>
          <mo>-</mo>
          <mn>4</mn><mi>a</mi><mi>c</mi>
        </msqrt>
      </mrow>
      <mrow><mn>2</mn><mi>a</mi></mrow>
    </mfrac>
  </mrow>
</math>

^ It’s a valid HTML code. It renders this way:

No 3rd party libs needed.

Parametrized var-functions

type Fn = <T>(a: T) => T;
declare const fn: Fn;

const a = fn<number>; // no "()"
a; // const a: (a: number) => number

It was on the surface all along, but it eluded me.

Pure functions

A little rant about functional programming and pure functions. There is a common delusion about pure functions. People often think that:

  • Pure functions cannot use variables. Only constants.
  • Pure functions cannot run impure functions. Only pure.

These statements make some point. But they are not entirely true. Let me clarify this. The only restrictions that pure functions have are:

  • It must be deterministic, meaning it doesn’t have random behavior. No matter how many times you run it with the same set of arguments — you’ll get the same result.
  • It shouldn’t have any side effects.

What is a side effect? Basically, it’s any change in the world outside of the function. E.g.:

  • Changing the given argument
  • Changing a variable defined outside of the function
  • Mutating any value reachable from outside the function (including parameters) or any value that escapes the function
  • Making a query (database, network, etc.)
  • Reading a file, writing to a file, removing a file, etc.
  • Reading external mutable data
  • etc.

I think you got the concept. Now let’s focus on the word “side” in “side effects”. “Side” means it’s outside of the given function. We don’t have these restrictions for internal state. Yep, a pure function may have mutable internal state.

function pure(a: number, b: number): number {
  let c = a ** b;
  if (c > 100) c %= 100;
  return c - 14;
}

^ this one is pure, even though it mutates c. Just because c is internal to the function — it doesn’t affect or depend on anything outside. We don’t mutate it after we return the value.

Ok, what about running impure functions? It’s a dangerous zone. Because it is very dependent on how exactly impure the impure function. If it’s not deterministic, then we have no chance. So the question is about: what side effects an impure function may have while still allowing us to use it inside a pure function? The answer is: the only side effect it may have is mutating the given arguments (only if they are local to the pure function):

function impure(packet: Packet): void {
  // deterministic and based only on packet
  packet.hash = computeHash(packet); 
}

function pure(id: number, data: Data): Packet {
  const packet: Packet = { id, data };
  impure(packet);
  return packet;
}

Here we clearly run impure in pure. But since impure changes only packet, which is entirely managed by pure, we’re safe.

That’s it.

Read more