Kartones Blog

Be the change you want to see in this world

Look on the bright side

Remember that old song from the classic Monty Python's film Life of Brian, Always look on the bright side of life? After so many years it's still stuck in my head 😃

2020 is unfolding as either a weird year or directly a bad year to most people, but in my case some relevant events started in 2019, and even I have to go further back to provide enough context.

In 2017 I switched jobs and I was exploring going full-remote, but in the end I went to a small Spanish ticketing company. It got acquired in early 2018 and, suddenly, a ~70 employees company became part of a multinational with +1000 employees. A few months later they also bought a Canadian company, and on January 2019 I asked my manager if there was a way to get transferred to Canada. I was told that at least in 2019 was impossible, as I was one of the two IC5 level engineers in Eventbrite Spain and I was vital for the Madrid office.

After summer 2019, my partner and I realized we really wanted to change, so I came back to my manager and explained the situation; we agreed to explore a transfer to the Vancouver office for early 2020. This was at the beginning of September. After a few internal conversations, waits and approvals in December 2019 I went to Vancouver and got the final approval from that office.

Advancing to March 2020, with all paperwork ready, the house almost empty, and basically everything good to go... COVID-19 hit globally, and specially hard in Spain. At the beginning of the global confinement, as borders closed we couldn't fly to Canada; then, with the forecasting of extended confinements (which in the ticketing business means almost zero income) the transfer got frozen; shortly after, the company laid off half of the workforce, which included the Vancouver office, so the whole transfer idea went away.

While the lay-offs didn't affected me directly, I was contacted by an ex-colleague with an interesting offer, and this time I listened, liked what I was told and took the opportunity.

Having summarized the key points, what initially was a negative outcome has pivoted to a series of changes for the better:

Remote Work

I started to think about becoming full remote around 2017 but didn't in the end. Now, even if currently it's hard to travel to other countries because of the COVID situation, I have the freedom to move anywhere in the world when the time is right. We're also no longer tied to living in a big city in order to "have an interesting job", so we're moving to the North of Spain to enjoy some nature and a colder (and thus, better) weather.

Out of the Comfort Zone

I've switched my day to day development language one more time! How different is working with Java "for real" from the Java you learn at university, and even from books. Java 8+ features, Lombok, Guava, Dagger, JAX-RS... plus GCP services (Pipelines, MapReduce, DataStore, BigQuery...), and the project itself, which is a new area for me. I am so happy to be learning new things almost every day. Combined with keeping working in English, which means I practice it a bit, I am quite satisfied with the decision.

Minimalism

While discussing and afterwards preparing for the transfer we weren't sure if there was going to be a reallocation package or not, so we took a minimalistic approach regarding physical goods. But before that we had already started to walk that path, in early 2019 when we moved outside of the city center. As an example, excluding clothes and my monitor, all my stuff fits in a backpack and a single standard size box [1]. Two laptops, two handheld game consoles, a tablet, a kindle (I keep only one physical book, until I finish reading it), the phone... and mostly just accessories and cables.

It's been a slow and iterative process, and sometimes not easy to apply. For example, I had a collection of boardgames, and quite a few old videogame consoles, but I gifted or sold each and every one of them. And same with printed books and other things that had emotional value but really I wasn't going to use any more.

Reduced Burdens

We had an old car, and last year almost broke; repairing it was expensive but we had to hold on to it for a few more months. Nowadays was due for another round of checks and potential repairs (again all but cheap), so we sold it instead, opting to try the car leasing model. We now only pay a monthly rent and gas, contract gets renewed each few years (and we get the choice of switching to a different vehicle if we want), and even an early cancellation of the leasing would cost significantly less than remaining rent quotas. Similar to that we have removed or simplified other personal and financial obligations. "The less you have, the less you need to worry about".

Built Healthy Habits

I recently wrote about habits and mentioned specific ones I've been shaping, like pomodoros or meditation, but there have been other areas of improvement, like food & health, a bit of sport (at minimum fitness maintenance, but slowly increasing), quality family time, and keeping less hobbies but fully enjoying the ones that remain. I still think days fly away too quickly, but I definitely "do more by doing less".


[1] : Actually I also have two "optional hobbies" boxes, things that if there's space (both physical and regarding my time schedule) I'll ask my family to send me, but else I can live without.


All roads lead to static typing

Note: Just in case you need a quick refresher, wikipedia has a nice description of strong and weak typing.

In recent years I became a firm defender of Python static typing (via type hints and MyPy, more details at this blog post). It is not that Dropbox, Stripe, Microsoft, Facebook and many others are creating immense projects around dynamically-typed languages, I've also worked with big and sometimes codebases in a variety of languages, and I've seen first-hand how difficult and mentally exhausting is to understand code when there are no type hints, how error-prone it is no matter the amount of tests you add (many of them superfluous and just palliating the fact that any variable can hold anything) and how your IDEs and tools can barely cope with those big codebases (even if it's a robust one like PHPStorm, RubyMine or Visual Studio Code). For an early startup of course you go faster with a dynamic language, I love Python because I get what I want with so few lines of code, but I would probably never ever use it "naked" anymore for anything serious if the plan is to evolve it and work with other people.

Now that I'm working with Java I'm back to real compiled languages, after more than a decade using dynamically typed ones: PHP, Javascript, Ruby and Python. And one thing struck me from that list... all of them have evolved into supporting static typing one way or another, and most directly inside the language core.

PHP introduced type hints in PHP 5.1, but really until version 7 didn't have enough primitive declarations. HipHop compiler was an amazing idea to speed up PHP: Simply compile all of it into C binaries, and now there's a full virtual machine (HHVM) making it more akin to Java than C++, although it's diverging into Facebook's Hack language so it's no longer "pure PHP".

Javascript is a curious creature. I guess the community is reluctant to adding types because being so old and evolving so much in other areas, typing is still weak and dynamic. But that didn't stop folks from adding types with TypeScript, a compiler transpiler that adds types and generates "typed javascript". I haven't personally used it, just seen and reviewed code written with TS, and it looks great. For sure adds more "boilerplate" but no more than for example React adds when you're building a simple form compared with an old HTML + JS implementation.

Ruby until recently only had external type checkers, like Sorbet, but it seems that finally Ruby version 3 will include RBS, a new language for defining types and some related command line tools.

Python has had type hints since version 3.5, optional and allowing also "gradual typing", but with the deprecation of Python 2 its gaining a lot of traction. The benefits will be broader once specific compilers (like mypyc) get more mature, as then Python modules would be able to be compiled into way faster C extensions (much like PHP's HipHop principles).

I think that this static typing convergence of many development languages is just one way of dealing with bugs and errors in long-lasting projects. Code linters and auto-formatters (example for python) are another way, dealing in this case with the human factor: Nobody will remember always all the rules, or will spend time nitpicking instead of focusing on real code issues, so better to enforce them automatically. Other more radical approaches are directly new languages: Both Go and Rust were born to try to fix C++ problems, and Hack derives from PHP.

In the end, all seems to circle around the same: Trying to build robust software in a scalable way requires certain development language guarantees and safeties.


Book Review: The Business Book - Big Ideas Simply Explained

Review

The Business Book - Big Ideas Simply Explained book cover

Title: The Business Book - Big Ideas Simply Explained (Audiobook format)

Author(s): Dorling Kindersley Ltd (DK)

I am lately expanding to not only reading about pure technology related topics, and business is something I don't pay much attention to, and I should. I also decided to digest this title in the form of an audiobook, convinced that, with a duration over 16 hours, it was not going to be a smaller version of the textbook. I definitely don't regret spending the time.

Inside, we find a lot. As the description says, learning about "more than 80 theories and big ideas about trade, commerce, and management" means it can't spend too much on each topic, and while a few feel too brief, it's enough to spark interest on reading more of any that sounds interesting to you. All of them go from the past up until 2013, so a few times it feels a bit outdated. For example, mentions Netflix, Amazon and Dell, but the data and sometimes even the techniques mentioned are different today (e.g. Dell now offers a much narrower customization of laptops/PCs, precisely what in the past made it so successful).

There are great insights and topics relevant today, from applying Kaizen, to the benefits of cross-functional teams, and of course mentions the Agile Manifesto. There are very few software related theories, mostly are generic, which I appreciate as we can still apply them, but they are less "tainted" this way. Again as an example, we're told studies and experiments were made to confirm that cross-functional teams work better, faster and even create stronger bonds between its members. Now think about the typical silos in software company: Systems, Design, Product,...

I've focused on a few samples, but there are way more. Even the book cover provides some hints about what you will find inside:

Full-size The Business Book cover

I enjoyed it a lot, so much as to going to read/listen to more titles from DK, and maybe even in the future grab the book to see the illustrations (which look to be really nice summaries).


Debouncing, Throttling and Queueing

Throttling can be used in a myriad of scenarios, from reliability (avoid flooding with actions) to performance (not doing anything more times than needed in a specific time-frame). I was checking for ways to throttle some event handlers in Javascript for a personal experiment, and gathered 3 (well, in practice 4) approaches, each with different subtleties. So, to keep them at hand I've decided to write this small post.

Debounce

Debouncing a function means delaying executing the function/callback until after a certain delay. The function will only execute once, no matter how many times you trigger it.

Example code (source):

function debounce(callback, delay) {
    let timeout;

    return function() {
        const context = this;
        let later = function() {
            timeout = null;
            callback.apply(context);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, delay);
    }
}

Leading Edge Debounce

Pretty similar to the normal debounce, but instead of waiting before executing the callback, in this mode (also known as immediate debounce) we first execute the callback and then disallow further invocations until the delay is over.

Example code (source):

function debounce_plus(func, wait, immediate) {
    let timeout;

    return function() {
        const context = this, args = arguments;
        let later = function() {
            timeout = null;
            if (!immediate)
                func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow)
            func.apply(context, args);
    };
};

Throttle

Throttling is an old but always effective technique. In its simplest form, we only allow at most one function execution in the specified threshold (very similar to immediate debouncing). Further calls are discarded.

Example code (source):

function throttle(callback, threshold) {
    let last;
    let timeout;

    return function() {
        const context = this;
        const now = Date.now();

        if (last && now < last + threshold) {
            window.clearTimeout(timeout);
            timeout = window.setTimeout(function() {
                last = now;
                callback.apply(context);
            }, threshold);
        } else {
            last = now;
            callback.apply(context);
        }
    };
}

Queue

Queueing is another mature technique, by which we build a "tasks list" and then execute it (usually in a certain order).

The benefits of this technique are mainly that a) you don't lose any invocation request (you enqueue it 3 times, 3 times will be executed) and b) you get fine control of when it will be executed, and can do any kind of operations over it (throttle the dequeueing speed, remove duplicates/aggregate similar calls, etc.).

Example code (source), buffering into a FIFO queue and adding an initial processing start delay:

function Buffer(startDelay) {
    var queue = [];
    let timeout;

    function taskHandler(task, callback) {
        console.log("Queue size: " + queue.length);
        task();

        // call the buffer callback.
        callback();
    }

    function run() {
        var callback = function () {
                if (queue.length > 0) {
                    run();
                } else {
                    // signal the buffer we're done processing
                timeout = null;
                }
        }

        // give the first item in the queue & the callback to the handler
        taskHandler(queue.shift(), callback);
    }

    // push the task to the queue. If the queue was empty before the task was pushed we start processing
    this.append = function(task) {
        queue.push(task);

        // Simulate a delayed start. In the real world, should just be what's inside of the function,
        // and there would be no need of a timeout except if we want a delayed start of queue processing
        if (queue.length && !timeout) {
            clearTimeout(timeout);
            timeout = window.setTimeout(function() {
                run();
            }, startDelay);
        }
    }
}

A minimalistic working example can be checked at https://kartones.net/demos/023/. Just some inputs, each applying a different technique to the onkeyup event.


We are creatures of habit

We are creatures of habit. By repetition, may it be willingly or unintentionally, we add new actions, reactions, ways of thinking... habits come in so varied ways.

Some habits take time to acquire; Some people say you need 60 days of repeating something for it to become a habit... or was it 61 times? I love those off-by-one errors even outside of software development 😂 Anyway, you get the point: they don't simply suddenly appear and "now you have it".

Habits can be good and healthy: For example, thanks to the COVID-19 house confinement (which lasted 2.5 months in Spain) I've introduced myself into meditation, and now have the habit of doing it first time in the morning almost every day. Regarding development, as an example I've been an avid fan of practising the pomodoro technique as a way to maintain focus while working.

But we sadly can also merge bad habits to our lives.

I've always disliked open offices, mostly because of the noise they help spread and the education in silence that employees need when working in such a wide space. Yes, I do have noise cancelling headphones since 2010 or 2011, and many times listening to electronic music gets me into the zone and boosts my coding speed, but I also like sometimes to enjoy the sound of silence. And that is almost impossible in any office nowadays.

And is not just a matter of some noise, is more of an issue of constant interruptions: "Did you read the Slack I just sent you?", "Hey, just in case you didn't saw the email invite and Google Calendar reminder, I come to your place to remind you about that incredibly [irrelevant] meeting everyone including you should attend!", phone calls, mobile phone notifications, a colleage speaking on the phone right next to you, somebody screaming somewhere loud enough you can hear it even without pinpointing the source...

To provide specific metrics, I am still not able to do more than 5 or 6 50-minute pomodoros in a single 8h work shift (not cheating, any distraction means you reset the timer). And I'm usually regarded as a very focused person by my colleagues. I don't think so many people suddenly have ADD (Attention Deficit Disorder) magically. I think is just that, with so many distractions, we've created the habit of doing single-core multitasking (quickly doing context switching, and thus partially losing focus). "Just answering that email and going back to the task", "just replying xxxxx's chat", etcetera. Not counting if you check your phone with each notification, then I simply wonder how anybody can even reach a state of concentration at all.

The good news is that almost, if not all, bad habits, can be also nullified. Sometimes it is hard, because for example a toxic environment is harder to fight than a self-created "fake need". But sometimes it is easy, as eating healthier (you just start removing crappy food and slowly adding better substitutes, and doesn't feels hard to progress). But I believe that it is always in our hands, somehow, a way out of any bad habit. Even if it means a drastic change.

It took me some vacations and one month to be again almost in total control of my attention when coding. Now, most of the time I am the one choosing to check the phone only either then the pomodoro is over, or while the code is compiling, the server starting or some other task that I can't avoid waiting for. And many times, it is actually more interesting to keep reading article X or one page of book Y.


Previous entries