All posts by Abhishek Nagekar

DIY Web Analytics

I’ve long established that adding heavy duty analytics and tracking scripts to my blog pages isn’t the right thing to do. Personally, it is also a bit liberating to not know which article of mine is getting a lot of traffic and which isn’t, because then I’m not biased by what the internet is searching for and can write about pretty much anything that I feel like writing about. 10 programming languages you should learn in 2020 has exactly the same weight as Let me tell you a funny story from last night, so which one do think I’d write about?

The analytics and tracking world has come a long way and is viewed very negatively in the light of recent internet incidents. But it started off very simple and had a very simple and non-malicious idea at its core: Getting to know your user better so that you can serve them better.

That thought made me search for a simple analytics solution that I could run on my blog for a couple of weeks and get enough insights to make informed decisions regarding the frontend design changes while not compromising on the privacy of the visitors. If I’m completely honest, I was also just curious to know these things with no agenda behind it.

I looked into Simple Analytics, a nice solution that does exactly what I needed (perhaps a bit more than that), but a little expensive for me at USD 19 a month. There are also self hosted analytics solutions like Plausible, but that was too much work for realizing this simple thought. So I decided to put something together quickly and the following is what I ended up implementing.

Client side JavaScript

On the client side, I needed to get the data that interested me. It was details like the browsers used by my visitors, platform, width of their screens etc. More technically, the user agent, platform, screen width, referrer and the current page’s url (although I don’t plan on using it for this article. Spoiler: One of my lowest effort articles is pulling more than half of all pageviews which is a bit saddening).

1
2
3
4
5
6
7
8
9
10
11
if (!('doNotTrack' in navigator) || !(navigator.doNotTrack === '1')) {
  let analytics = 

  analytics["href"] = window.location.href
  analytics["userAgent"] = navigator.userAgent
  analytics["width"] = window.innerWidth
  analytics["referrer"] = document.referrer
  analytics["platform"] = navigator.platform

  navigator.sendBeacon(ANALYTICS_ENDPOINT, JSON.stringify(analytics
}

There’s not much happening here. Just checking if the user prefers to not be tracked, else get the desired data and POST it to our analytics endpoint using the navigator.sendBeacon API.

Server

We need to implement the endpoint that’s listening for the POST requests from our client browsers. I decided to go with Firebase’s functions for handling the request and Firebase’s realtime database to store the data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const functions = require('firebase-functions'
const admin = require('firebase-admin'

admin.initializeApp

const cors = require('cors')({
  origin: true,


exports.handler = functions.https.onRequest(async (req, res) => {
  if(req.method === 'POST') {
    const snapshot = await admin.database().ref('/hit').push(JSON.parse(req.body
    return cors(req, res, () => {
      res.json({ message: 'success' 
    
  }
  else {
    res.json({ message: 'have a good day!' 
  }

Now this is super bad code for a variety of reasons, but it worked for my temporary needs. I deployed this, waited for a couple of weeks and had some data to answer some basic questions about my blog’s visitors.

Parsing data

So at this point I had let this code run long enough to have accumulated couple of hundred entries. It was time to analyze. Firebase allows you to easily export the database in JSON format. Using some basic Python-fu, I created lists of each dimension and passed these lists to Python’s builtin collections.Counter (which is perfect since I’m only interested in aggregated stats), and then take the top 5 most frequent items using the .most_common method. Finally, we plot bar charts for these top 5 values across each dimension using Matplotlib to visualize the results.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import json
from collections import Counter, defaultdict
from user_agents import parse
import matplotlib.pyplot as plt

analytics_data = defaultdict(list)


def plot_chart_from_ctr(ctr):
    most_common = ctr.most_common(5)
    x, y = [item[0] for item in most_common], [item[1] for item in most_common]
    x = [str(i) for i in x]
    plt.bar(x, y)
    plt.show()


def driver():
    with open('export.json', 'r') as output:
        data = json.load(output)
        hit = data['hit']
        entries = []
        for item in hit:
            entries.append(hit[item])

        analytics_data['height'] = []
        for item in entries:
            analytics_data['width'].append(item['width'])
            analytics_data['href'].append(item['href'])
            analytics_data['platform'].append(item['platform'])
            analytics_data['referrer'].append(item['referrer'])
            analytics_data['userAgent'].append(item['userAgent'])

    browser_family = []
    for agent in analytics_data['userAgent']:
        user_agent = parse(agent)
        browser_family.append(user_agent.browser.family)

    ctr_browser_family = Counter(browser_family)
    plot_chart_from_ctr(ctr_browser_family)

    ctr_platform = Counter(analytics_data['platform'])
    plot_chart_from_ctr(ctr_platform)

    ctr_referrer = Counter(analytics_data['referrer'])
    plot_chart_from_ctr(ctr_referrer)

    ctr_width = Counter(analytics_data['width'])
    plot_chart_from_ctr(ctr_width)


if __name__ == '__main__':
    driver()

The questions

What are the most common browsers?

I would’ve guessed this to be the case for browsers, but not in Chrome’s favour to this extent 🙁

What are the most common platforms?

Win32 is still the majority platform among my visitors and there’s some Apple action going on. There’s also a healthy chunk of Linux X86_64 visitors. The armv7l and armv8l may contain Android devices but hard to tell.

What are the most common referrers?

Unsurprisingly, most of the traffic comes through Google.

What are the most common screen widths?

There’s a healthy mix of screen resolutions with the most frequent being 360px.

In closing

So that’s it for this little article. I’m happy with the outcome given how little effort went into this whole assignment. I hope you enjoyed reading it. As always, write me an email in case you have any comments!

Thank you for reading.

A Tale Of Internet Speeds

Similar to the last two articles, this one is about the little improvements I’m making to my workstation. So far, I got a gaming mouse and a mechanical keyboard, a nice desk pad and a 24in full HD monitor from Dell to add to my existing setup (while we’re at it, do checkout my setup page here).

For this one, I’ll be talking about internet speed, and the upgrade associated with it. This upgrade is special in more than one way and hence, I want to go into a bit of history, my history with internet bandwidth.

Ever since adolescence, internet has been a basic necessity for me and the people from my age group (even before it becoming a source of livelihood for many of us). One of my first memories of the internet is this screen:

I distinctly remember this from my first computer*, an HP desktop PC with a Pentium Dual Core processor and 1 GB RAM, since it also had 100Mbps LAN card. Not knowing the difference between hardware capabilities and internet bandwidth, I naively assumed that when I get a broadband connection, that’s the speed I’ll see. But little did I know it would take more than a decade to reach this milestone.

*which practically didn’t exist by the time I started writing on this blog, and as a result there’s very little, if any, mention of my first computer here.

Life at 10KB/s

Back in those days, in around 2008-2009, we didn’t have broadband at home. My PC was barely 6 months old and I had realized that there’s only so much GTA Vice City one can play and be entertained.

My dad had this Nokia Expressmusic 5310 phone that supported Edge network, so slightly faster 2G. I figured out that if I can get internet on that phone, I could use the CD that came it to tether internet to my PC. I remember it was INR 98 or 99 for unlimited 2G data then.

It worked, but the speeds were really miserable. On a good day, keeping the phone on the window sill, I would get around 10KB/s or 80kbps which is close to the promised speed of 16.8KB/s or 135kbps. At those speeds, speed test websites like speedtest.net just don’t load, much less show you your network speeds. Facebook, which people used back then, took more than a couple of minutes, literally, to load. Needless to say, Youtubing or any sort of video streaming was out of question.

Even download small files, like a couple of megabytes, was a challenge, and I would almost never download directly using the browser. I would always use the fancy bloated download managers which supported resume functionality and parallel connections (not like it made a difference, but who knew).

I was on Windows XP, no firewall or antivirus software, downloading these shady browser plugin and download mangers. Those were the wild days!

Nmap download adventure

One incident worth mentioning is the download of Nmap, a network scanning tool. It was around 15MB in size, and believe it or not, it took me many months worth of trying to finally download it. The download would always fail and no download manager helped. But when it finally did, my joy knew no bounds and it genuinely made me happy. It is a bit weird that I still remember it so vividly, but it was special in a way.

So anyway, the struggle continued for a while. For the next couple of years I would ask friends or my aunt to download me anything that was more than 20MB in size.

Emergence of broadband

I finally got a broadband connection. It was a 2Mbps connection capped to 1GB of data. 1 whole gigabyte of data for the whole month. It definitely improved things a bit, but on the whole it was still painful. Now the internet was fast enough to watch a Youtube video in 720p. But if I did, that’d pretty much be the only thing I did that month.

I ‘upgraded’ to a 512Kbps unlimited connection which was a lot better. This was, in fact, my first real broadband. Usable, and unlimited. 65 kilobytes a second isn’t bad, especially for browsing the web or download a GB or two of data overnight. That also started this whole phase of my life when night time was download time. I remember the disappointment I used to have after checking the download progress first thing in the morning and realizing the download failed halfway through.

But yes, the internet was within reach.

Real broadband speeds

I changed ISP a couple of years later as the first one was too bad in terms of service, and got a local one with Google and torrent peering. Basically, any website owned by google would work at higher speed, which would typically be around a couple of MB/s. Even speeds of up to 40mbps weren’t unheard of, as long as you’re able to find it on a Google service. This same ISP later upgraded my connection to some 8mbps for free.

That was my first time breaking the 1MB/s barrier. Major achievement.

The upgrades after this were incremental, if I’m being honest. I think I was at 25mbps by the time I left for Germany. After settling down here in Germany, I opted for a 50Mbps link. 50Mbps is exactly like 16Mbps for 90% of the time (unless of course you’re downloading stuff in a hurry).

So in that sense, I already knew that going 100Mbps isn’t going to bring any meaningful change to most of my surfing habits. But it does feel like a big change, psychologically. Remember that image from before, the one which says 100Mbps speed on the LAN interface status page? I’ve finally maxed that out, a little over 11 years later.

My 13 year old self might find it unimaginable to think of what a 12MB/s broadband connection feels like, which is a bit of a jump from his humble 10KB/s flaky dial-up connection tethered off a 2G mobile phone.

Edit – 31/07/22

I moved into a new flat that supposedly has a gigabit internet connection. I’m getting 500+ mbps speeds consistently which is unbelievable. I also got a phone that supports 5G which also pulls data at rates upwards of 500 mbps. I’m living the dream!

In closing

I’ve mentioned this a few times before, but I’ll do it again. Adulting, getting a job and living on your own has little meaning to it if you don’t realize those childhood dreams, which for me is overkilling on tech stuff and buying 8 year old laptops off ebay.

Having said that, I might actually make use of the bump in upload speed, which does bottleneck my offsite backup plans. Stay tuned for updates on that front. Also, downloading ISOs and doing system updates are a delight these days.

Finally, I’d probably never feel the same level of joy that I felt on getting a real broadband after years of doing sub-10KB/s on mobile data. But that makes me think of all the things that I’m getting started on, my professional career, a new language that I’m learning, Chess, or anything that I’m a newbie at. With each passing milestone, the next one becomes a little less exciting. Keeping that in mind, I should try to celebrate any incremental progress that I make in any of these things. That was just a long way of saying that the journey matters more than the goal.

Thank you for reading!

IKBC MF108 V3 Unboxing And Review

Lenovo recently released their Thinkpad TrackPoint Keyboard II which I got super excited about. I could finally use a keyboard identical to my laptop’s while not having the laptop down on my desk, something that’s bad for posture and causes neck strain. But while looking at it, and some other options, I found some very pretty mechanical keyboards from brands that I had never heard of before. After a few days of searching the web and watching review videos, I decided to go for a mechanical keyboard instead of the Lenovo one. That’s the prelude to my journey of acquiring my first mechanical keyboard.

In this little article, I’ll talk about mechanical keyboards in general, and then talk specifically about the one that I chose. If you’re here just for the review of IKBC MF108, feel free to skip to the actual review.

What is a mechanical keyboard?

Unlike a membrane based keyboard found on most laptops and many cheaper desktop keyboards that we’re all familiar with, mechanical keyboards have a separate switch for each key. The switch action is similar to how a household electrical switch works; with a metal contact completing the circuit and registering a ‘click’. The kind of switch determines how the switch will react to being pressed (if it will make a click sound, or if it will have a tactile feedback, or if it will be heavy or light etc). I recommend this helpful video to get a better idea.

Mechanical keyboards are, generally speaking, more expensive than their membrane counterparts. They also last quite a bit longer, which is mostly due to quality materials that go into their manufacturing (Cherry claims 50 million clicks for the Cherry MX Blue switches). These keyboards can be customized with a wide variety of keycaps (the part that we touch with our fingertips while typing), switches (the part that actually registers the keypress – look at the image below) and the case (the enclosure for all of the components).

Cherry MX Blue, a popular switch from Cherry GmbH, a keyswitch manufacturer, in action. Notice the tactile bump on the way down – Source

Cherry MX switches beneath the keycaps on my IKBC MF108. The switches are transparent to allow for the backlight to shine through the switch’s case

Apart from the functional stuff, many of the mechanical keyboards have some sort of backlighting, even fully customizable RGB for aesthetics (and for typing in the dark if you need to look at certain keys).

IKBC MF108 V3

Okay, so let’s get to the meat of this article. My first mechanical keyboard and my thoughts after having owned it for the last four days or so.

Build quality

As soon as the delivery person hands you the package containing the keyboard, you’ll notice the weight. It is heavy, and not in the way of a sensation or feeling. It is literally heavy. How heavy, you might ask. Very. You’d probably not be able to pick it up with just one hand, and to someone unsuspecting, they might think it is glued to the desk if they try picking it up. It weights around 2.5 kilograms, and can cause serious injury if you drop it on your foot.

I made a very amateur unboxing video that’s embedded below. It shows what you get in the retail box and my initial impressions. I’ll link some timestamps in the video description so that you can skip to points of interest (it is a super long video of me fiddling with stuff).

Connectivity

It comes with a USB cable (USB-C port in the center on the back) and connected seamlessly to my laptop running Ubuntu. I don’t mind the lack of bluetooth/wireless. Would’ve been nice for some minimalistic desk setup, but I’m not very keen on such things.

Included accessories

A couple of accessories are included with the keyboard. Extra blue and red keycaps which are fairly low quality. A dust cover that doesn’t fit. The USB cable feels nice to the touch.

Overall I’d expect more quality in the accessories department for the price. On the bright side, the part that actually matters–the keyboard itself–looks uncompromised on quality. My unboxing video has timestamp to the point where I show all of these accessories.

RGB backlight

Key labels are nice and crisp, and it is a pleasure looking at the keyboard in dark

I loved the backlight. The lights can be controlled from the keyboard itself (brightness, per key color, prebuilt modes, stopwatch functionality etc) and thankfully doesn’t need a software (it is especially important if you don’t run Windows OS as most of these software are made exclusively for Windows).

Typing and click-y sound

I’m not super fast at typing, but could type at roughly the same speed as on my laptop at around ~65wpm.

Double shot ABS keycaps

This keyboard features ABS double shot keycaps. ABS is considered inferior as compared to PBT found on many other competing keyboards. This article goes into the difference in detail. Since this is my first keyboard, I don’t have a taste so can’t comment. Also, it is fairly easy to replace keycaps whenever you feel the need for change.

Price and purchasing – Shout out to CandyCase

It is retailing for EUR 190 at CandyKeys at the time of my writing, which is exactly what I paid for it. It is hard to get an ANSI layout keyboard, or any mechanical keyboard for that matter, here in Europe (slightly envious of my friends in the US right now).

I can highly recommend CandyKeys and its founder David (who handles the support@ email address). Super quick with the support and provides honest recommendations (didn’t expect that). The processing took a couple of days after payment and so did the shipping. Overall, very satisfied with the service so far.

Certain misconceptions about mechanical keyboards

Mechanical keyboards are only for gamers: They certainly are for gamers but a lot of people who work with computers, including software developers, also prefer these keyboards because typing on them is a joy.

Mechanical keyboards are loud: Some are, while others aren’t. There are tons of options when it comes to choosing the switches.

Mechanical keyboards are gimmicky: There’s no shortage of bright blinking mechanical keyboards that scream “look at me”, but there also are very professional beautiful keyboards that’d sit on your desk without a hint of the brilliancy unless someone decides to take a closer look.

Leopold FC660C

Mechanical keyboards will make your friends/colleagues go wow!: Most people will roll their eyes if you start talking about your beautiful keyboard or how nice the clicks sound. Probably the only people who’ll care are a bunch of random internet strangers over at r/MechanicalKeyboards, so make sure you post a snap of your new keyboard there.

Mechanical keyboards make you a 10x programmer (or gamer): I honestly think it doesn’t make that huge of a difference in your overall productivity. They certainly are a joy to type on and add character to your workstation, but is it worth spending hundreds of Euros on? Depends on what you currently have. Probably a secondary monitor would do you more good 🙂 But hey, if you can afford one and it brings you happiness everytime you look at it, go for it!

In closing

That’s it for my keyboard review article. I hope you found it useful. Your first keyboard doesn’t have to be super expensive. There are plenty of good quality keyboards in 60% or TKL sizes (more on sizes here: keyboardco.com) that would’ve been my first priority had they been in stock. Ducky, Leopold, Anne Pro are some of the brands I kept hearing about all over the place (perhaps good marketing?) so do check them out.

Before deciding on the switch type, I went to a nearby electronics store to try the different switches on the keyboards on display there. I’d recommend you do the same if this is your first time, just like me. If you have any questions or comments, feel free to write me an email.

Thank you for reading (and watching)!

So we’re making it a thing now? 6th Anniversary Of Blog

I wrote a blog birthday blog post last year, and the year before that and for whatever reason, one after the first year but none in between. So I think we can really say I’m making this a thing going forward. But that’s okay, as there’s something happening around this time every year. This year our senses are clogged by the news from the pandemic going on around the world which I touched upon a bit back in April.

Compared to April, things are much better right now here in Germany. We can go out and meet friends, eat at restaurants and shop for our favourite stuff. Life’s slowly getting back to normal, although there’s still that element of fear of catching the virus. Things aren’t as good in India, so it is anyone’s guess when I get to visit home next ‍♂️

As for my blog, this year wasn’t super active apart from a few posts and some cosmetic changes to the template. An interesting moment was a blog post getting featured in RealPython‘s newsletter! I’m quite proud of that.

I want to move the blog away from Jekyll, maybe to something Python based. Don’t get me wrong. I love Jekyll on Github Pages, but it is just too straightforward with rarely any problems to fix. I want something that’d break, allowing me to fix things and learn. But all of that is still to happen. Hopefully I find a stretch of time to finally make the move to a different blogging platform in the near future.

As for the rest of the year, I plan on making my workstation a little better, so expect small tech gear reviews here and there from the purchases I make. You can also expect more on Python programming and infosec as that’s on the agenda. So yeah, that’s it for this blog birthday celebration on a slow lazy Sunday afternoon. Cheers, I’ll see you in the next one.

Thank you for reading!

Logitech G305 Gaming Mouse Review

I was looking for an ergonomic mouse for my workstation upgrade (this mouse is one of the many things I’m adding to my work/hobby setup) and stumbled upon a lot of expensive gaming mice with RGB, scroll wheel and other fancy stuff. But I wanted none of that, just a mouse that’s good to hold, wireless but not Bluetooth, and is fairly accurate with a couple of extra buttons that can be customized to custom actions. I stumbled upon G305 from Logitech which had their premium HERO sensor with 12,000 DPI and good battery life. It has good reviews on Youtube and Amazon DE and was fairly cheap at EUR 43.

Initial impressions and build


In a nice little box, we find the mouse itself along with colorful paperwork, a Logitech sticker, USB-A extension and a Duracell AA battery. The mouse had the USB receiver inside it. After inserting the battery into the mouse, it does become a bit heavy. I like how solid it feels, but apparently more weight is bad when it comes to gaming mice. I’ve been away from both, gaming and physical mice for about 7 years now, so it was good to know, and is something to consider if you’re actually going to game with it.

No RGB

Another thing to note is that many gaming mice, even the ones half the price of this (albeit from no-name brands), come with RGB lighting. This one doesn’t but that’s not a problem for me.

Pointer speed toggle


There’s a button right behind the scroll wheel that changes the speed of the mouse pointer speed. It has four levels, and each level has a different colored LED indicator that lights up when it is toggled. Pretty sleek and handy.

Utility buttons


There are two utility buttons on the side which don’t do anything by default on Ubuntu (they did navigate to the next/previous tab in Chromium by default though). I used xev to find their button codes and then xbindkeys to bind them to toggle previous/next workspace in Ubuntu with the following

# in .xbindkeysrc
"xdotool set_desktop --relative -- -1"
  b:9

"xdotool set_desktop --relative 1"
  b:8

Install xdotool if you don’t have it already.

In closing

I am really enjoying this mouse, and have no problems so far. It is nice to have the Thinkpad clit mouse when typing/working and using the mouse when casually surfing the web (like browsing Youtube). I’ll post a little review of the new keyboard soon and if you’d like to know when I do, you might want to subscribe to the RSS feeds of my blog.

Chess – Basics

So recently I got interested in Chess, and by recently I mean 6 months ago. I learned some important beginner’s lessons along the way and I planned to document them in non-technical language in this article.

I’m assuming you know the very basics, like how the pieces move and what castling is, which is exactly how much chess I knew when I started. If not, go outside (on the internet) and learn the basics. Then create an account on lichess.org or chess.com and play around 10 games with other people. Then come back to this article.

So assuming that we’re on the same page, let’s start!

Stages of the game

A chess game can be visualized to happen in three stages; Conveniently–start, mid and end game. You can be mindful of what stage the game is in as there are certain things you can do in each stage to give yourself a slight edge in the game.

When you start, you try to develop the pieces as quickly as possible and castle. That means all pieces are ready to jump into action; whether attack or defence, and your king’s safety is ensured.

Midgame, depending on your position, you exchange pieces and try to get a better position. Make sure you’re either up material (pieces or pawns), or you have a better hold of the position and control more space on the board.

Endgame is when both sides go all out using whatever positional advantages they’ve created previously. It is also common for endgames to just have king and pawns, maybe a minor piece as well. In this case, both sides try to push their pawns and promote them to Queens (or any other piece but usually the Queen, and the first side to do it usually wins).

Pre game

Know value of the pieces: Not all pieces are as valuable. Pawns are unit value, that is 1. Knights and Bishops are 3, Rooks are 5 and Queen is 9 units each. When exchanging pieces, these values should be taken into account. It generally doesn’t make sense to sacrifice a Rook for a Bishop. Of course, there are times when you’ll want to do it (especially if you have a forced checkmate in place).

The value of your pieces changes depending on your position and the stage of the game. You can read about it on Wikipedia but you will also learn these things intuitively once you have enough games under your belt.

Starting tactics

Castle early, ensure king safety before anything: I used to frequently go for material (i.e. trying to win pawns or pieces) and space before castling which generally doesn’t end well. Once your opponent is done developing their pieces and castling, you’ll end up playing a very defensive game if your king is in the center of the board with undeveloped pieces.

Develop pieces as early as possible: Move all pieces out of their initial position, ready for attack or defence and connect rooks early in the game.

Don’t move the same piece twice in opening: In general, you should avoid moving a piece more than once in the opening as the goal is to develop pieces fast. Of course, exceptions are when your piece is attacked or if the other side offers a gambit (a pawn or minor piece sacrifice to gain positional advantage).

Develop Knights before Bishops: Another general rule of thumb as both Knights can develop and simultaneously control central squares which is usually a good idea.

Rooks work better when connected: Rooks are developed when they’re connected (both Rooks are defending each other). Another common tactic is to double rooks on an open file (a column on a Chess board without pawns) to mount a powerful attack.

Doubled Rooks on an open file are very powerful in infiltrating enemy territory

Aim for center control: It is generally a good idea to control the center four squares of the board. There are exceptions, however, as with certain openings we can aim for control over one side of the board and continue our attack from there.

The highlighted squares are important and you should try to gain control over them

General tactics

Don’t keep pieces in pin: If your piece or pawn is pinned, meaning a more valuable piece is behind it, it is good to unpin the piece (move the piece that’s behind it). This is especially true with king. You don’t want your king to be on the same file as your opponent’s Rook or Queen, and same diagonal as your opponent’s Bishop. If the other side brings their Rook to the same file as your King or Queen, move it away even if there are pieces in between.

White to play: The d pawn (pawn on ‘d’ file) cannot capture the Knight as the Queen is hanging and the Rook on d8 is xraying it. It is best to unpin (get away from the Rook’s file or Bishop’s diagonal) as soon as possible.

A piece that has moved a lot is worth more than an unmoved piece: If your knight has been moving around the board, it is generally in your opponent’s favour if they manage to exchange your active piece for their dormant piece.

A piece that covers more area is worth more than a piece that covers less area: Similar to a previous one, if your Bishop covers and controls a beautiful diagonal, your opponent might want to get rid of it by exchanging their unused piece for your beautiful Bishop. Try to protect your active pieces.

If you control more space, don’t trade pieces: If your pieces control a lot of space on the board, you should avoid trading pieces.

If you’re crammed, exchange pieces to create room: Conversely, if you’re crammed by your opponent, try forcing exchange of pieces and pawns to create some room for your pieces to develop.

If defending, defend a piece as many times as it is attacked: If you want to defend a piece or pawn, defend it as many times as it is attacked.

If attacking, attack a piece as many times as it is defended plus one: If you’re the one attacking, mount an attack such that the other side runs out of ways to defend.

Two pieces are better than one piece: It generally doesn’t make sense to sacrifice a Bishop and a Knight for a Rook, or two Rooks for a Queen. It is, generally speaking, better to have two pieces instead of one (use the point value of pieces to decide if the exchange makes sense, but remember that active pieces are more valuable than passive ones).

Avoid back rank issues: If you don’t defend the last rank (where your king usually resides), a Rook from your opponent might simply deliver a checkmate (since the pawns in front of your king might be unmoved leaving no room for your king to escape).

In this position, if White isn’t careful, the Rook on a8 can deliver a checkmate which is why you must make an escape route for your king or have a defender on the last rank

Capture with pawns towards the center: Generally, if you capture with a pawn, you want to capture towards the center of the board if that’s an option.

Knights belong in the center of the board: It is usually not the best idea to move the Knight to a corner of the board as they cover fewer squares from there. They say Knights on the rim are dim. This applies to most pieces but especially the Knights.

As you can see, a centrally positioned Knight controls many more squares than a cornered Knight

Avoid creating pawn islands: An isolated pawn is one that isn’t connected with your other pawns. Such pawns are liabilities and weaknesses, and hence should be avoided (or sacrificed for positional advantages). In general, try to have as few pawn islands as possible.

Black has 2 pawn islands and white has 4. Black is to be preferred here.

Avoid doubled pawns: Doubled pawns are two pawns on the same file. As with pawn islands, they are weak and can become a liability in the endgame. It is said that a Rook’s favourite meal is a doubled pawn and is best to avoid doubling your pawns.

Grab any open files for your Rooks: When pawns are traded, they leave behind open files. Be quick and place a Rook behind an open file to gain control over the entire file. Later you could also double Rooks on the same file for a powerful attack.

A Rook on an open file covers a lot more square compared to a rook behind pawns

Avoid exchanging the fianchettoed Bishop: The fianchettoed Bishop is supposed to defend the weaker squares around the King and control a long diagonal. You shouldn’t exchange it in early or mid game if that’s an option.

The Bishop on g2 does a nice job of defending the weaker squares around your King’s castle.

Know thy Bishops – Bad Bishop vs good Bishop: A bad Bishop is one that’s obstructed by your own pawns, ending up looking like a pawn itself (and not controlling much space). A good bishop covers a nice long diagonal.

Notice how Black’s Bishop is nicely controlling a diagonal while White’s Bishop is essentially a pawn

Bishops and Knights are equal, except…: Bishops and Knights are both 3 points, but Bishops are usually preferred when the board has few obstacles, while Knights are preferred when the position is very tight. In general, a Bishop pair is always something you’d want to save if you can.

Be mindful of forks: Forks come when two pieces are attacked by an opponent’s piece and we lose one of them anyhow. Knight forks are common and can be tricky to spot. A fork that comes with an attack on the King and the Queen is called a royal fork.

Here, black will lose a Rook
A royal fork

Next steps

From here, you should learn some of the openings and endgames. Openings will help you quicky get to a position where all of your pieces are mobilized and ready, and also know what’s on your opponent’s mind depending on what they play.

Endings are important to know how to actually win most games. Many games might not end with you having a bunch of heavy pieces storming your opponent’s king. On the other hand it would be quiet and tactical, and you should know how to best make use of the couple of minor pieces and pawns that are on the board.

In closing

Hope you enjoyed this article on some beginner tips for levelling up in Chess. If you’d like to play Chess with me, challenge me on lichess at lichess.org/@/abhn.

Thank you for reading!

Concurrency In Python For Network I/O – Synchronous, Threading, Multiprocessing and Asynchronous IO

In this article, let’s look at some of the ways to do batch HTTP requests in Python and some of the tools at our disposal. Mainly, we’ll look at the following ways:

  1. Synchronous with requests module
  2. Parallel with multiprocessing module
  3. Threaded with threading module
  4. Event loop based with asyncio module

I was inspired to do this because I had a task at hand which required me to write code for a superset of this problem. As someone who can write basic Python, I implemented the most straightforward solution with for loops and requests module. The task was to perform HTTP HEAD requests on a bunch of URLs, around 20,000 of them. The goal was to figure out which of URLs are non-existent (404s, timeouts and so on) in a bunch of markdown files. Averaging a couple of URLs a second on my home network and my personal computer, it would’ve taken a good 3-5 hours.

I knew there had to be a better way. The search for one lead to me learning a few things and this blog post. So let’s get started with each solution. Do note that depending on the hardware and network, it might go up and down quite a bit, but what’s interesting is the relative improvements we make going from one method to the next.

Synchronous code with requests module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import time
from helper.urls import urls
import requests


def make_request(url):
    try:
        res = requests.head(url, timeout=3)
        print(res.status_code)
    except Exception as e:
        print(e.__class__.__name__)


def driver():
    for url in urls:
        make_request(url)


def main():
    start = time.perf_counter()
    driver()
    end = time.perf_counter()
    print(f'Synchronous: {end - start:.2f}')


if __name__ == '__main__':
    main()

If you try to think what you’d do if you had to check 10 URLs if they work, and write that process down in pseudocode form, this approach is pretty much what you’d get. Single threaded and synchronous, just like a human.

This script fetches 800 random URLs from a different file, makes an HTTP HEAD request to each, and then times the whole operation using time.perf_counter().

I ran all the tests on a Raspberry Pi 3 running freshly installed Ubuntu 20.04 LTS, but I don’t intend on making this scientific or reproducible, so don’t take the results at face value and test it yourself. Better yet, correct me and tell me how I could’ve done it better!

Synchronous code took 536 seconds to hit 800 URLs

With that we have our baseline. 536 seconds for 800 URLs that we can use to compare our other methods against.

Multiprocessing with multiprocessing module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import time
from helper.urls import urls
import requests
from multiprocessing import Pool
from multiprocessing import cpu_count


def make_request(url):
    try:
        res = requests.head(url, timeout=3)
        print(res.status_code)
    except Exception as e:
        print(e.__class__.__name__)


def driver():
    with Pool(cpu_count()) as p:
        p.map(make_request, urls)


def main():
    start = time.perf_counter()
    driver()
    end = time.perf_counter()
    print(f'Multiprocessing: {end - start:.2f}')


if __name__ == '__main__':
    main()

My Raspberry Pi is a quad core board, so it can have 4 processes running in parallel. Python conveniently provides us with a multiprocessing module that can help us do exactly that. Theoretically, we should see everything done in about 25% of the time (4x the processing power).

Multiprocessing solution took 121 seconds

So a bit less than 25% but if I run both the scripts over and over again, the average converges to a ratio of roughly 4:1 as we’d expect.

Threading with threading module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import time
from helper.urls import urls
import requests
import threading


def make_request(url):
    try:
        res = requests.head(url, timeout=3)
        print(res.status_code)
    except Exception as e:
        print(e.__class__.__name__)


def driver():
    threads = []
    for url in urls:
        t = threading.Thread(target=make_request, args=(url,))
        threads.append(t)

    for t in threads:
        t.start()

    for t in threads:
        t.join()


def main():
    start = time.perf_counter()
    driver()
    end = time.perf_counter()
    print(f'Threading: {end - start:.2f}')


if __name__ == '__main__':
    main()

With threading, we essentially use just one process but offload the work to a number of thread that run concurrently (along with each other but not technically parallel).

Threading code runs in 41 seconds

Threading runs much faster than the multiprocessing, but that’s expected as threading is the right tool for network and I/O bound workload while multiprocessing suits CPU intensive workloads better.

Short detour: visualizing threading and multiprocessing

If you look into your system monitor, or use htop like I have in the following images, you’ll see how multiprocessing differs from threading. On my dual core (with 4 threads) personal computer, multiprocessing creates four processes (with only the default one thread per process), while threading solution creates a much larger number of threads all spawned from one process.


Code running the multiprocessing [above] and threading [below] solution as viewed through htop

This helped me better understand the difference between threads and processes on a high level and why threading solution is much faster for this particular workload.

Asynchronous code with asyncio module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import time
from helper.urls import urls
import httpx
import asyncio

async_client = httpx.AsyncClient()

async def make_request(url):
    try:
        res = await async_client.head(url, timeout=3)
        print(res.status_code)
    except Exception as e:
        print(e.__class__.__name__)


async def driver():
    await asyncio.gather(*[make_request(url) for url in urls])


def main():
    start = time.perf_counter()
    asyncio.run(driver())
    end = time.perf_counter()
    print(f'Async IO: {end - start:.2f}')


if __name__ == '__main__':
    main()

Finally, we reach Async IO, sort of the right tool for the job given its event driven nature. It was also what sparked my curiosity in the subject in the first place as it is quite fascinating, coming from the event driven JavaScript land, to find an event loop in Python. [Read: Callbacks And Event Loop Explained and Event Driven Programming]

Asynchronous IO code ran in 11 seconds

Clearly this task is made for this approach, and the code looks surprisingly simple to understand which is a plus.

In closing

That’s it for this little adventure in Python land I sincerely hope you enjoyed it. If you find any corrections and improvements in the above text, please write them to me. It will help me get better at Python (and writing )

Thank you for reading

Buying A Lenovo Thinkpad X230 In 2020

I upgraded from my Lenovo Thinkpad T440 to a Lenovo Thinkpad X230. That sounds more like a downgrade, you might say, but it isn’t. Well, not in most cases for me, that is.

Hopefully. We’ll see.

In this little article I’d like to outline why an X230 in 2020 and if it could be your next daily driver.

First, enjoy the pictures and specifications

X230


So why buy an X230 in 2020?

Let’s dive straight into the meat of this article. Why buy an 8 year old laptop and not something new? There are a bunch of reasons that I can think of, not all as important but worth mentioning nevertheless, so let’s look at each of them in brief.

  • Cheap: I don’t mind paying for quality, but ironically, some of the best quality laptops out there are in the refurbished market. I really like the new X1 carbon and the Dell XPS 13 but I feel like the price premium is a bit disproportionate given what you get in return.

  • Upgradable: A user replaceable screen, keyboard, trackpad, RAM, storage, PCIe WWAN (cellular 3G/LTE), battery and god knows what else. RAM tops out at 16GB at 1600Mhz, SSDs upto 2TB at SATAIII supported, X220 classic keyboard and trackpad swap, IPS screen replacements available for EUR 60-70 and the list goes on. Since my Macbook Pro’s screen broke recently and was given a EUR 569 quote for the replacement, you can tell I appreciate cheap, user serviceable spare parts.

  • Practical: This isn’t one of those enthusiast laptops that you buy out of sheer impulse and idealization, and then find very inadequate for normal computing. With 16GB RAM and a 35 Watt i5-3320m processor, I have absolutely no problem running tens of tabs on Firefox, a Webstorm instance, dev server, Slack and Spotify simultaneously. It also has a Display Port and projects to my Dell Ultrasharp display at native 2560×1440 QHD resolution. If you’re into gaming, you could do that with an external GPU via the Express card slot.

    X230 (i5-3320m) vs T440 (i5-4300u) vs Macbook Pro 2017 (i5-7360u) — As you can see, the processor isn’t much slower than a much more modern machine, and actually faster than the T440, which is a generation newer than the X230. Source
  • Driver support: With an old machine like this one, drivers support is usually very good. I installed Ubuntu, and every thing worked out of the box from simple things like Wifi and Bluetooth to fingerprint sensor, and mobile broadband.

  • Build quality: Something we just expect from the Thinkpad lineup, especially the old Thinkpads. If this machine has survived 8 years of use, it’ll probably survive a few more. Unfortunately, you can’t say the same about many laptops in the same EUR 150-350 price segment.

  • Hardware & I/O: Thinkpad keyboards are usually good with ample key travel. You could opt for an X220 keyboard swap for the classic 7 row keyboard layout. What’s also great is the wide array of I/O option you get on board; Two USB 3.0s and one USB 2.0, mini display port, VGA port, Express card, ethernet port, SD card reader, combo headphone jack, fingerprint reader, hardware wireless kill switch; I think I’d miss a full sized HDMI, but that’s asking for a bit too much at this point.


  • Community & support: The Thinkpad community on Reddit is great for asking queries and upgrade suggestions. Having an old laptop means most issues are well documented and it is unlikely you’ll hit a novel roadblock if you don’t do anything fancy with your computer. I’ve been a lurker on this sub ever since getting the T440, and I knew one cannot go wrong with the X230.

Why not to buy a Thinkpad X230?

Of course, as you can imagine, I’d not recommend this laptop to everyone out there. Here are some of the reasons for that.

  • No warranty: If the thought of buying a device without warranty makes you sweat, this isn’t for you. Yes, you could get seller’s warranty on Ebay, but it is still not a manufacturer’s warranty.

  • Form factor: It is a small lightweight laptop, but not the smallest, lightest or thinnest. Most ultrabooks these days will be lighter and thinner, like the Dell XPS or Thinkpad X1 Carbon.
  • Battery life: You could get a 9 cell battery with the X230, but it will still not match that of a modern ultrabook thanks to the improvements in energy efficiency.
  • Need for tinkering: If you find this laptop for cheap, chances are you’ll have to do a few upgrades before it becomes usable (at least if you plan on making it your daily driver). If you aren’t comfortable with opening laptops and installing upgrades, it is better to buy either a fully upgraded machine or find a IT nerd friend who would do it for you.
  • Limit to upgrades: There’s often a limit to what upgrades you can do, and given this isn’t a new laptop, that limit isn’t that high. And all these upgrades cost money, of course. You shouldn’t spend a lot of money upgrading only to find out this still isn’t the laptop for you, regretting not getting a new computer in the first place.
  • Specialized usecases: Goes without saying, but if you definitely need a modern GPU for working or gaming, or a fast CPU for specialized needs, then this isn’t a laptop for you. But in that case you probably already know that.

What’s wrong with the T440? Avoid these in your future laptops

Okay, with that out of the way, let’s talk about the issues I had with my T440. My biggest complaint was the screen. It was a TN panel (a bad one in that), which has dull colors and bad viewing angles (as compared to an IPS). There was also only one RAM slot maxing out at 8GB, and I had the version with no soldered RAM. I missed the ability to expand the memory at times.

Then there was the trackpad, which I later learned was nothing like Thinkpad trackpads, and this had to be upgraded too. I could’ve done the upgrades, but I preferred going for a new laptop as it wasn’t much of an overhead in terms of price (factoring in T440’s resale value) and I was eyeing an X230 for some time now.

What I really liked about the T440?

Snap from my other article

I absolutely loved how sturdy and rugged the laptop was. No flex in the keyboard or the screen whatsoever. My previous laptop, Fujitsu Lifebook A514, had to retire because of this exact problem. The keyboard was a joy to type on, and while I later learned that this keyboard was a step back for many from the classical Thinkpad keyboard, I’d any day prefer the new Thinkpad’s keyboard over my Macbook Pro’s or Fujitsu Lifebook’s.

In closing

Overall I’m very happy with my new X230. It seems like a laptop I could use for some years, hopefully without many issues. I’m also happy that I’m back to running GNU/Linux as my daily driver! Reach out to me if you are planning on going this route and have questions.

Cheers, thank you for reading.

Coronavirus Gratitude

I distinctly remember the last week of February. A bunch of my colleagues and I got together at a Chinese restaurant to have nice food. The next day was Saturday and I went running at Tempelhofer Feld. Sunday was relaxing at home all day except for a little Coffee trip to Alex.

Like for many people, the threat of Coronavirus was downplayed by the fact that it seemed way too far away. Until suddenly it wasn’t. We hurried home on the first Monday of this month halfway through the day, and that marked the beginning of self quarantine for me. More a month later, here I am writing this article after having embraced this new way of life in self quarantine; social distancing, self isolation and working from home culture.

So I’m sure most of you reading this in the near future or even the distant future know and understand the gravity of the current situation, and even if you don’t, there are great sources out there that you can use to make and keep yourself informed. We’re not going to talk about any of that in this article. What I’ll instead like to write about is all the things in life that I took for granted that I should’ve been grateful for. If there’s something positive about this whole situation, it is that it reminds us how lucky many of us are living in comforts of our social security, freedom of movement, privilege to eat and hangout in the sun. To make sure I don’t forget the lessons from this time, I’ll make a note of some of these privileges in this article.

Freedom to travel

For me, the only restriction of movement I ever felt was either bureaucratic, like requirement of visa, or monetary, like needing to save money to visit some place. I grew very introverted and most of my time would get spent at home, but that was a choice. I never had to experience what a lockdown feels like. Now, I feel like many people like myself can relate more, and hence, empathize with the struggles of communities living under lockdown, not because of a virus but geopolitical instability.

Meeting friends and colleagues at work

Having the option to socialise is very underrated. In fact, having to meet people in real life is sometimes frowned upon. We tend to make jokes about how meetings at workplaces suck, and how we’d rather work in solitary for all our lives if we could. While there’s certainly some truth to the notion of reducing unnecessary meetings, I think workplaces can be a great place to meet people of different kinds, find friends and work on your soft skills. There’s also that extra joy of forming little groups to go to fancy lunches.

Biking on a super fine day

I love my bike. And when the day is nice and sunny, there’s nothing better than riding the bike in a random direction for a while, parking next to a Coffee shop, grabbing a Coffee, hanging out at the flea markets and more! Aah, those days. It is especially painful writing this because today is almost one such day.

Hangout at the supermarkets

For me, grocery shopping has become something that I look forward to. I find it quite entertaining to go to supermarkets and ponder over all the variety of goods they have there. It is probably also because German supermarkets are sort of new to me, coming from a convenience store culture, I get mesmerized by all these huge supermarket chains they have here (not to mention the differences in cuisines between Germans and Indians). Can’t wait to get back to that routine!

Hangout at friends’ places

I often go to my friends’ places, and they sometimes come over to mine. It is always nice meeting people over the weekend, playing a board game or cooking, or simply chatting through the evening. It recharges you for the next week and during the week there’s always something one can look forward to if things aren’t the smoothest!

Shawarma, Kabap, Döner, Kofte

For me, all of these are my guilty pleasures and I can’t wait to get back to them. In Berlin, no matter what, you have a Döner joint right around the corner and for many, life’s just not the same without a regular Döner meal.

They take Döners very seriously in Berlin

The feeling of control

On slightly more abstract terms, I miss the feeling of control we generally have, or think we have, in life. We plan vacations months in advance, not worrying about flights being grounded or international borders closed. The recent timeline of events makes one realize how fragile things are, and man made structures do a good job of, even if momentarily, giving an illusion of full control and predictability.

In closing

I hope you are doing well wherever you are. If you work in an essential services industry and still go to work, I applaud your efforts and your courage. If you are sitting at home waiting for times to get back to normal, I think it helps to document or simply reflect on exactly what you’re looking forward to so that when things actually go back to normal and you do your everyday activities like going to work, eating good food at a restaurant or visiting a friend, you would be reminded how special each one of those activities are.

Stay healthy and safe, and thank you for reading!

What Writing A Web Development Tutorial Taught Me

I recently wrote a tutorial on getting started with web development. It was a frontend only (meaning covering only HTML, CSS and JavaScript), 5 day tutorial that covered very basic web development topics and concepts like HTML elements, CSS selectors and JavaScript language semantics. Along with learning the basics of frontend web development, the course takers built their very first website which was a simple, one page portfolio site listing their interests and some pictures.

I’d not go into the technicalities of the course itself, as that’s off topic. What I’d like to do in the little post is list down some things I learned while I was writing the course, about writing the course and also about writing your thoughts down in general.

  1. If you’d like to test your understanding, try explaining it
  2. Many obviously true beliefs that you hold probably aren’t true
  3. Explaining is an art
  4. The role of an editor
  5. Writing requires a lot more focus than programming
  6. Having a continuous thought train for a multipart article is exponentially more difficult than writing a one off article
  7. Have a plan or outline
  8. Know your audience’s technnical competence

So, without further ado, let’s get started.

If you’d like to test your understanding, try explaining it

“The person who says he knows what he thinks but cannot express it usually does not know what he thinks.”
— Mortimer Adler

The above quote from this interesting blog post about Feynman Technique on Farnam Street captures the gist of this learning. We’re good at convincing ourselves that we understand something when in reality we might not. It is similar to when we speak a language natively and are confident in our knowledge, but then when a language-learner asks us a simple question, we don’t have an explanation but rather know it ‘intuitively’.

As an example, when I was writing the chapter on JavaScript, I was tempted to write that arrow functions have replaced the ‘function()’ functions. I asked myself why I thought that was the case, and I didn’t have an answer. I had just ‘believed’ that to be the case.

Upon researching, I learned the differences in their workings and their use cases, and I came out of that a bit wiser than before. That was just one instance where I wrote something, then asked myself why I thought that was the case, and learned that that was in fact not the case.

The bottom line here is, if you want to learn something well or test your understanding, try explaining it. Interestingly, that’s just me rediscovering the Feynman technique.

Many obviously true beliefs that you hold probably aren’t true

This is an extension of the previous point. But with a different takeaway. Since we’ve now established that many of our beliefs are wrong, it is wise to not be too confident in them and always practice humility when it comes to your knowledge, and consequently, your opinions and worldview. In other words, while it is great to put in time and energy to learn something properly and have opinions about it, it is also important to be ready to accept that you could be wrong and change.

This point is best illustrated by the “Strong Opinions, Weakly Held” philosophy, best outlined by a little paragraphy from this post.

A couple years ago, I was talking the Institute’s Bob Johansen about wisdom, and he explained that – to deal with an uncertain future and still move forward – they advise people to have “strong opinions, which are weakly held.” They’ve been giving this advice for years, and I understand that it was first developed by Instituite Director Paul Saffo. Bob explained that weak opinions are problematic because people aren’t inspired to develop the best arguments possible for them, or to put forth the energy required to test them. Bob explained that it was just as important, however, to not be too attached to what you believe because, otherwise, it undermines your ability to “see” and “hear” evidence that clashes with your opinions. This is what psychologists sometimes call the problem of “confirmation bias.”

While you’re at it, I recommend reading this article by Jeff Atwood where I first read it. There’s also this nice TED talk along the same lines.

Explaining is an art

It is not easy to explain why linear-gradient works the way it does. It is hard to explain parameters of a function to someone who has never written any code, and you cannot use words like parameters, arguments or function call before explaining them. In short, writing a beginners programming course is some work (who would’ve thought?!). Now I look back at all those books, articles and tutorials that taught me the basics of everything I’ve learned and realize how great it was to have had all of that top quality learning material for free on the internet.

My personal experience is that we don’t notice when something is very well written or explained, especially with technical writing and documentation. It feels very natural and in-flow. But try to remember the last badly written article that you read. It was exhausting, you had to re-read through paragraphs to make sense of the text and you probably didn’t even finish it. That’s why, the next time you read through something and don’t notice anything wrong, take a moment to appreciate the effort that might’ve gone into making it come across the way it does.

The role of an editor

I learned what an editor does while writing this course. I would typically submit a day’s work as a document, fairly confident that I had done a good job only to find out the next day that the document has 200 new comments and edits. How was that even possible? I’m not a good writer, accepted, but those many edits? I would genuinely fear submitting my work for editing, just like my younger self would fear exams for all the bad grades I could get.

But in this case, the editor is really there to make the text readable, check if the sentences flow naturally and there’s no discontinuation of thoughts (and of course, spelling and grammatical shortcomings in the text). All in all, after the edit the content doesn’t look anything like the initial draft I sent for editing. If you ever get the chance to get your work reviewed by an editor, don’t miss it. You’ll learn a lot.

Writing, for me, requires a lot more focus than programming

I realized how much more focus writing content needed as compared to programming. I could just not do it in the office. Every 15 minutes I’d lose my train of thoughts due to some or the other distraction. I believe this could be just because I’m not used to the idea of writing content in the office, or writing professionally in general. I would end up taking work from home days to make sure I’m making progress. I had not expected this to happen, especially after having been an amaeteur blogger for a while now. But there I was, trying to think of the next sentence while repeatedly reading the paragraphs above.

Having a continuous thought train for a multipart article is a lot more difficult than writing a one off article

So I feel quite comfortable writing something like this very post. It is not as long, and one can write the whole thing in a couple of sittings. Then there are also not a lot of different ways of presenting here. Just text followed by headings followed by more text. That’s quite a lot easier than writing a multi-day course with each day three or four times as long as a typical blog post with many screenshots, git commits, code snippets and, of course, text. It is important to keep track of all your resources, and any mistake you find later on means all the screenshots and git commits from that point on needs to be updated, which is quite a hassle.

Have a plan or outline

To avoid finding technical faults / discontinuities in the text much later in the course writing, having a plan or an outline about the content is very important. Each chapter, and every topic in the chapter should be outlined before even starting with the actual writing. Ideally, even the outline should be reviewed by someone who knows about how learning works (yes, that’s an expertise), and the final outcome should be communicated well in advance. You want to avoid making the course too difficult (and have people drop out after getting stuck) and too easy (and have people drop out after getting bored).

Know your audience’s technnical competence

When you’re writing a beginner course in software development, you have to explain every bit of technicality. From creation of a file with special extension to what a git commit is. Any assumption you make regarding the ability of the user to understand the course’s substance can backfire resulting in many course takers abandoning the course mid way or flooding the communication channels with their questions. To avoid this, it is important to know the technical competence of your target audience. You cannot cater to a wide range of expertise, and no matter what you write, many people are going to be left out. But that’s okay.

In closing

I’m glad I found this opportunity to do some professional writing. I learned some important aspects of writing, and I tried to share my experiences with you through this post. I hope you find something useful out of this. As always, thank you for reading!