Software tenbagger

“Tenbagger” is a term coined by legendary investor Peter Lynch to describe stocks that provide tenfold value on the initial investment. As software engineers we make scores of decisions every day in the face of ever-evolving requirements, whose impact on the architecture might only become visible down the line. It’s nice when a relatively low-effort code change ends up providing compounding benefits over a long time horizon.

I am currently working on a critical component in a distributed system for a food-delivery app. One of its core responsibilities is to receive information from an upstream service and pass it into downstream services. The feature requirements typically follow this pattern: customers can now provide a backup phone number, which should be shown on the delivery app. So an order passing through a chain of systems can now contain a new field, which needs to be forwarded to relevant downstream services.

[Read More]

Squashing ruby on rails database migrations

Why?

There are several reasons why you’d want to squash the database migrations in your Ruby on Rails application:

  1. In a long running project you may end up with hundreds of files in your db/migrate folder over time. Carrying these legacy migrations incurs maintenance overhead. For example, when upgrading the Rails version, you may need to modify those old migrations for syntax changes.

  2. If your build process involves recreating the database to run the tests, it would need to run all of these old migrations. Running a lot of migrations would slow down the build time.

    [Read More]

Understanding a Postgres query plan

A query plan is a sequence of steps used by a database to access data. Being able to read a query plan is key to understanding the performance of an SQL query. While tuning a query we need to know how the rows are being fetched from the tables? Are the indexes being used? What is the cost of joining to tables? A query plan provides with an answer for all of these questions.

[Read More]

Database integration tests for a Spring application

Suppose you are tasked with writing tests for a Spring and Hibernate application. This application uses a mix of native queries, HQL or entity associations to fetch data from the database. If you choose to mock the DAO or entity layers, you leave a significant portion of the code untested. In such cases data integration tests can provide the most correct feedback. But you do you configure your application to run integration tests?

[Read More]

The small pleasures of programming

It’s not just pulling off a complex engineering feat that makes programmers love their jobs. There are small pleasures to be had even in your day to day tasks, if you look for them.

Seasoned programmers know the thrill of recognising the possibility to introduce an abstraction over duplication. A task as simple as renaming a variable can be the difference between obscurantism and lucidity. It’s the boy scout principle in action. Making your code a bit more pleasant to revisit. The joy one derives in these simple improvements is akin to Amélie’s les petits plaisirs.

[Read More]

Representing natural numbers in lambda calculus

One of the joys of reading SICP is that apart from the main subject matter, we come across many tangential topics that are interesting in their own right. One such topic is mentioned in Exercise 2.6: Church numerals. Named after the mathematician Alonzo Church, Church numerals are a way of representing natural numbers in lambda calculus. But what is λ-calculus?

From a programming perspective, λ-calculus can be thought of as the smallest universal programming language. It lacks some of the common features that one would expect in a programming language like, primitives, booleans, numbers etc. In this language, variable substitution and functions are used as the building blocks to express everything else. Even numbers! In this post we will get a glimpse of how this is achieved.

[Read More]

Using thread dumps to analyse deadlocks

In a multi-threaded Java application, a deadlock occurs when two threads wait forever attempting to acquire locks that are held by each other. Here’s a simple example to simulate a deadlock:

public class Deadlock {
    private Object lock1;
    private Object lock2;

    public Deadlock(Object lock1, Object lock2) {
        this.lock1 = lock1;
        this.lock2 = lock2;
    }

    public void methodA() {
        System.out.println("trying to acquire lock1 from - " + Thread.currentThread().getName());
        synchronized (lock1) {
            someLongRunningTask();
            methodB();
        }
    }

    public void methodB() {
        System.out.println("trying to acquire lock2 from - " + Thread.currentThread().getName());
        synchronized (lock2) {
            someLongRunningTask();
            methodA();
        }
    }

    private void someLongRunningTask() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[]args) {
        Object lock1 = new Object();
        Object lock2 = new Object();

        new Thread(() -> new Deadlock(lock1, lock2).methodA()).start();
        new Thread(() -> new Deadlock(lock1, lock2).methodB()).start();
    }
}
First thread calls methodA and acquires lock1. Second thread calls methodB and acquires lock2. Then the first thread calls methodB while at the same time the second thread calls methodA. Both are trying to acquire a lock that is already held by another thread, so neither can proceed further.

[Read More]
Java 

Setting up a JavaScript project in 2017

Creating a front-end JavaScript project can be a daunting task due to the sheer volume of choices available while deciding the tech stack. First, you need to decide the JavaScript framework or library for your project. Do you plan to use the latest ES2015 language features in your code? If yes, then you need a transpiler because your browser probably doesn’t support them yet. Then you require a bundling tool to get your code loaded in the browser. You may want to minify the code for faster load time. To automate all these steps, you need a build script. You may want to deploy your project on a local web server during development. Some setup is required for that. Finally, you need to include some testing framework in your project to write unit tests.

[Read More]

Hystrix – a simple use case

Hystrix is a fault tolerance library that is very useful for managing failures in a distributed environment like microservices. Suppose we have a service A dependent on service B, which is in turn dependent on service C.

A -> B -> C

Let’s say a call is made from A to B. To serve this request, B needs to call C but there’s a communication failure between them. If the call from B to C is wrapped in Hystrix mechanism, we prevent the failure being propagated to A. Because B couldn’t fetch the actual information from C, Hystrix gives us the option of declaring a fallback value to be used in this case, if feasible.

[Read More]

Running time intensive operations in parallel with RxJava Observables

Recently I delved into the RxJava library. In this post I will demonstrate how RxJava Observables can be used to execute two long running tasks in parallel, so as to reduce their overall execution time.

While we can create threads for this purpose, an additional benefit of using Observables is that it provides a convenient way of collecting the results of the parallel tasks. With threads, this can get pretty complicated. Let’s consider a situation where we have a consumer class that depends on the result of two or more expensive independent tasks.

public class Producer1 {
  public List<Integer> produce() {
    List<Integer> list = new ArrayList<Integer>();
    
    for(int i=0; i<5; i++) {
      System.out.println("Producer1 - " + i);
      try {
        Thread.sleep(1000);
      } catch(Exception e) {}
      list.add(i);
    }
    return list;
  }
}
public class Producer2 {
  public List<Integer> produce() {
    List<Integer> list = new ArrayList<Integer>();
    
    for(int i=0; i<5; i++) {
      System.out.println("Producer2 - " + i);
      try {
        Thread.sleep(1000);
      } catch(Exception e) {}
      list.add(i);
    }
    return list;
  }
}

[Read More]
Java