Pages

Saturday, March 11, 2017

Ruby Under a Microscope

Recently, I started reading Ruby Under a Microscope, by Pat Shaughnessy. Being a Ruby programmer for the last three years, I felt this is a good time to start reading it. To give you a brief idea, this book explains what happens behind the scenes while executing a Ruby program. I started just out of curiosity and without even reading any reviews online.



I am currently reading the second chapter of the book. The amount of information the book has packed into each of the chapter is really astonishing. In fact, I was able to give a 45 mins talk to my fellow programmers at Multunus just with the first chapter!

The book starts from the moment when you execute a ruby script with the command:

ruby your_script.rb
From there, it is a walkthrough on how ruby reads, tokenises, parses and compiles the program into something the underlying Ruby Virtual Machine understands. For me, this was a pragmatic recap of compiler theory from my college days. What I learned then was just theory. Here, Pat shows the actual source code which does what is meant to be done! I got a new perspective on the basic concepts like tokenising and grammar parsing just by reading the first chapter. This book gave me courage to go through the actual ruby source code written in C!

If you are a Ruby programmer, and if you care about fundamentals of computer science like compiler theory, don’t think twice. You should read this book. As I told already, I am in the second chapter of the book as of now. So far so good. I will post a detailed review with my learnings once I complete the book.

Saturday, October 10, 2015

Being Agile

This is a bit complicated than it sounds. Agile is not a set of processes that one can blindly follow. Nobody practices Agile method. It's a way of thinking about software development.

Let's start with a more formal description called Agile Manifesto. Agile Manifesto is a collection of 4 values and 12 principles to guide us through the process of software development.

Rather than dumping everything here, I'll take you through the right resources to read about it. Here is the Manifesto for Agile Development and the Principles behind Agile Manifesto. To be agile, you need to put these values and principles into practice.

Agile Methods

Agile methods are processes that follows agile philosophy. They consists of individual practices like setting coding standards, using version control etc. Of course, these practices have been around for years. But agile refines the set of existing principles by handpicking those which are aligned to agile philosophy, discarding the rest and also by bringing in some new ideas.

Every team, project and situation is unique. You might want to create your own agile method by mixing together various agile practices. But, creating a brand new agile practice from scratch is a bad idea unless you have used agile development for a prolonged period of time. Always start with an existing, proven method and refine it in lieu of starting one from scratch.



- learnings from the Art of Agile Development



Friday, August 28, 2015

Tower of Hanoi

Tower of Hanoi is a recurrent mathematical problem. In recurrence, the solution to each problem depends on the solutions to smaller instances of the same problem.

I'd solved this problem a few years ago. But now, since we talk about functional programming, I decided to solve the problem using Elixir.

Read more about the problem statement here: Tower of Hanoi.

If you want to try it interactively, go here.

Here is my solution:

defmodule TowerOfHanoi do

  def move(1, source, destination, intermediate) do
    IO.puts ["Move ", source, " to ", destination]
  end

  def move(no_of_disks, source, destination, intermediate) do
    move(no_of_disks - 1, source, intermediate, destination)
    IO.puts ["Move ", source, " to ", destination]
    move(no_of_disks - 1, intermediate, destination, source)
  end

end

I'm updating my GitHub repository (yedhukrishnan/mathematics) with more math problems. Feel free to check them out to suggest improvements or to give comments.

Saturday, May 02, 2015

Functional Programming (Part 1)

I've been talking about Elixir for a while. It's never too late, but I believe it's high time to share what I learned about functional programming and why is it important.

Let's start with the fundamental difference. In an object oriented world, we solve the problem using classes and objects. A class depicts a behaviour while an object stores a state. While solving a problem, a lot of time is wasted modelling classes and hierarchies. But in a real world, we want to get things done than spending time maintaining states. This is what makes functional programming different. While the imperative style of programming concentrates on what and how to get things done, functional programming concentrates only on what. How is it being done, we don't need to worry about that.

In functional programming, we never mutate data. We just transform them. What's the big deal if we change some existing data? Here is the simplest explanation: We don't need to worry about data inconsistencies in a multi-threaded environment. It's always ensured that nobody is going to touch the data created by us.

Friday, April 17, 2015

Recursion (Part 1)

Unlike in imperative languages, functional programming languages (including Elixir) achieve looping through recursion. Why? To explain that, let's consider C:
for(i = 0; i < 5; i++) {
  sum = sum + i;
}
Here we are modifying (mutating) the value of i as well as sum in each interation. Mutation is considered as a bad practice and functional programming languages do not encourage it. Let's see some basic examples of recursion in Elixir.

Say, we want to print the message "hello" five times. How do we do that?
defmodule Recursion do
  def print_hello(n) when n <= 1 do
    IO.puts "hello"
  end

  def print_hello(n) do
    IO.puts "hello"
    print_hello(n - 1)
  end
end

Recursion.print_hello("Hello!", 3)
# Hello!
# Hello!
# Hello!
Here, defmodule is used to define a module (group of several functions). We can have multiple definitions of the same function. In the first function when n <= 1 is a guard. This function will get executed only when the guard condition is satisfied (no wonder why it is called a guard!). When there are multiple clauses (definitions) of the same function, Elixir looks for a match and executes it when it finds one. If no matches are found, it will throw error.

In this case, when n = 3 and n = 2, the second clause will be executed. When n = 1, the first clause will get executed. 

Read more:

Wednesday, April 15, 2015

Elixir Language (Part 5)

Binaries

In the last section, we talked about representing strings as UTF-8 encoded binary. But we left a topic for this section: How a character having code point above 255 is represented in binary?

Well, we all know that a single byte can only hold a value between 0 and 255. Let's consider the string hełło. Here ł has a code point 322.

This is where UTF-8 comes into picture. It solves the problem by using 2 bytes to represent each ł, and one byte each to represent h, e and o.

iex> string = "hełło"
"hełło"
iex> byte_size string
7
iex> String.length string
5
Here, we can see that the byte size of the string is 7 while the string length is 5. The function byte_size/1 can be used to check how many bytes are actually used in the memory to represent the given string.

Read more: Binaries, strings and char lists

Sunday, December 28, 2014

Testing (Part 2)

In the previous post, we've looked at what to test. Now it's time to see how to test. There are several different aspects:

  • Regression Testing - Here, we test the result of current test with its previous results. This ensures that the bugs we fixed today didn't break the things that were working yesterday.
  • Test data - There are two types of test data: real world data and synthetic data. Both are important, because each of these tests different aspects and behaviour of the system.
  • Exercising GUI Systems - Testing GUI required special testing tools. Some of them record the events and play whenever required, while some others are based on a script. Writing code that is decoupled from GUI helps us to write better tests, because we can test the backend without interacting with the GUI.
  • Testing the Tests - How do we test the tests? The easiest way is to introduce bugs intentionally in the tests and see if they complain. 
  • Testing Thoroughly - How do we know if we have tested our code thoroughtly? The answer is we don't, and we never will. But we can use coverage analysis tools to keep track of it.

- summary of Ruthless Testing, from The Pragmatic Programmer: from Journeyman to Master