Kartones Blog

Be the change you want to see in this world

Multi-Language Wordle clone fork

I don't touch much React code at work, but I feel I should have a minimal proficiency. While I've read some articles and watched a course about it, in the end nothing beats practice by trying.

In the near future, I plan to do a small personal project built from scratch, although I might go with Preact instead of React.But more recently, a colleague built a Swedish Wordle clone, appropriately called Swordle, and I decided to practice a bit by forking it and making it multi-language.

I won't dig into the details of the changes I implemented, they're really not much.

What I'll show is a small screenshot of how it looks with different languages:

Swordle fork screenshot

I added Spanish, British English and American English, switchable via the header flags. The game state and guesses are also now separated by language so you can actually play one word per language per day, although both English word dictionaries are very very similar.

If you're interested, my fork lives at github.com/kartones-forks/swordle.


Learning the basics of Memcached

Quick post to write down some resources to learn a bit about Memcached. I've used it from time to time but never got into learning how it works under the hood (at least an overall view).

Useful links

The protocol description is the first and foremost resource you should read. To complement it, I highly encourage reading also LZone's Memcached Cheat Sheet.

Regarding how to scale it, Skyscanner post regarding scaling was a simple but good introduction, also useful to learn about consistent hashing.

Journey to the centre of Memcached summarizes how the slabs, pages, chunks, and items work. It also helps you to begin using the stats command and interpreting the data it returns.

Oracle's page about memcached general statistics also has some useful tidbits.

Memcached Command-Line Options Explains precisely that, the CLI options just in case you can/need to tweak them.

Memcached Exporter for Prometheus is quite self-descriptive, a way to obtain all metrics from the stats command for consumption by Prometheus.

And finally, regarding tooling I'm still checking what's out there, so don't have much to mention. The default memcached-tool script is useful, but I like the efficiency metrics that memcached-tool-ng provides.

Side-Notes

  • Docker's official memcached container doesn't contains any configuration file (runs with all the defaults), don't search for one.
  • maximum connections (-c) controls the bandwidth, meanwhile backlog queue limit (-b) is a single queue for that bandwidth that allows to not have client connection errors when the connections limit is reached.
  • evictions are bad; expirations, reclaims, etc. are fine.

Course Review: Learning Kubernetes (LinkedIn Learning)

Review

Continuing with my broadening of topics, now it's time to learn some Kubernetes basics, to at least know what it is capable of, so I picked up Learning Kubernetes, a 2.5 hours Linkedin Learning course that looked nice. Touching topics from building blocks to deployments, jobs, services, labels, data management and logging, while not in depth, it is a good overview, with many hands-on examples.

But the course also has two negative points I wanted to point out. The smaller one is the fact that there are no Linux setup instructions! Mac and Windows yes, and for sure if you're like me will probably use a cloud provider rather than setup my own k8s cluster, but still 😒. The second one is also not critical, but more annoying, because relates with the pacing of the course. Sometimes, examples are really long, slowly going step by step, and repeating the previous command just adding a --show-labels flag, or reading trivial details; Other times, and despite watching it at 1x speed, the author rushes over non-trivial yaml files, executes a command and "voila, that's done!", or does a kubectl describe deployment and mentions so fast the relevant output sections (not even the content) that I had to pause the video, go back and check it. It also happens with the slides presented, he advances slides at times so quickly that you can't even read the latest bullet point or sentence when appears.

Overall, I felt satisfied with the contents. Just be prepared to pause from time to time.

Notes

The author recommends reading Kelsey Hightower's Kubernetes The Hard Way so probably that will be my next step.


Course Review: Learning Docker (LinkedIn Learning)

Review

I wanted to refresh my Docker knowledge, as it is been a while since I've done anything non-trivial. Learning Docker is an almost 3 hours course that teaches the basics, but covers quite a lot of topics; I'd say that almost if not all of the relevant ones. It is really well done, and goes through a lot of content, but well explained, and with very good examples. I was surprised with the samples because, with a topic like containers, you can easily get into boring things, but using netcat to show how networks in Docker are created and function, showing the relation with iptables, or a very clear example of the Dockerfile alters the image layers, are only a brief list of how you'll learn.

Recommended not only because of the content, but also because of the form.


Javascript Named Exports for testing

I'm now using Jest and its useful mocking extensions quite often at work, and while the combination of modern Javascript + NodeJS+ Typescript + third-party packages + your code sometimes makes things quite a challenge to test, with effort (and a few refactors to ease testability) most times I feel satisfied with the ending results.

Javascript imports via import (MDN reference) are quite flexible, but on the other hand being modules means that you either export something, or you don't and then is not available from the outside, so it's not as easy to test the unexposed code fragments. A colleague at work explained to me a testing pattern for that scenario, but I haven't found it online, so this small post is both a personal note and a documentation attempt.

The Testables Named Export Pattern

The main idea is using javascript named exports to export a specific group for testing with a meaningful name (e.g. testables). This way, you do add one additional export, but only one, also clearly signalling the intention; and you don't alter logic elsewhere in the code.

Let's use a tiny example:

a-file.ts

export function aMethod() { 
  ... 
  const result = aNonExportedMethod('something');
  anotherNonExportedMethod();
  ...
}

export function anotherMethod() { ... }

aNonExportedMethod(param : string) { ... }

anotherNonExportedMethod(); { ... }

export const testables = {
  aNonExportedMethod,
  anotherNonExportedMethod,
};

Your normal code will do normal imports, and simply won't care about testables nor be affected by it:

another-file.ts

import { aMethod, anotherMethod } from './a-file';

...

But when writing your tests, you will now be able to also import the testables group, so that you can write tests focused on that logic:

a-file.test.ts

import { aMethod, anotherMethod, testables } from './a-file';

...

const result = testables.aNonExportedMethod('a-string');
expect(result).toEqual(...);

Closing Notes

I am assuming no default export, but the behaviour is pretty much the same otherwise. Just don't return the testables as the default export if you use it (I don't fancy much default exports, and seems I'm not the only one).

Be careful as module logic will still execute upon import (any Javascript/Typescript outside functions will run) no matter if you only import { testables }. This can bite you but in general it is a good practice to avoid "import work" so keep it in mind.

I know not everyone will like this approach and could argue that you should only test the visible surface (even more so if the non-exported methods are called inside the exported ones). But I at least prefer smaller, more focused tests so, in my example, after testing testables.aNonExportedMethod and testables.anotherNonExportedMethod the test(s) about aMethod would be much smaller and focused on the logic not already covered by others.


Previous entries