This is the ninth in a series of blog posts I’ve been working on during COVID isolation. It started with the idea of refreshing my systems design and software engineering skills, and grew in the making of it.

Part 1 describes ‘the problem’. A mathematics game designed to help children understand factors and limits which represents the board game Ludo.

Part 2 takes you through the process I followed to break this problem down to understand the constraints and rules that players follow as a precursor to implementation design.

Part 3 shows how the building blocks for the design of the classes and methods are laid out in preparation for understanding each of the functions and attributes needed to encapsulate the game.

In Part 4 we get down to business… producing the game using the programming language PHP with an object orientated approach.

Part 5 stepped it up a notch and walked through a translation of the code to object orientated C++.

Part 6 delves into the world of translating the code into object-orientated Java.

In Part 7 the same code is then translated into Javascript.

In Part 8 I slide into the sinuous world of Python and learn a thing or two about tidy coding as I go.

Now in the final of my first-round translations I explore the intriguing world of Ruby.

Get in touch on Twitter at @mr_al if you’d like to chat.


Ruby

Available on GitHub at: https://github.com/mr-alistair/ootest-py

I decided to have a look at Ruby as a gateway to understanding something a little different – the Liquid scripting language used in Shopify eCommerce sites. Liquid is written in Ruby, and so it made sense to understand the underlying framework and syntax.

Besides, our family dog is named Ruby, and she’s a legend of a #floof. What’s not to love?

Figure 1 – Ruby the family #floof, enjoying a coffee and a chat with me. [Photo credit: Alan Moyle at Photobat]

Ruby is a relatively contemporary language, Japanese in origin and descended in part from Python, Eiffel, BASIC and other favourites. As a result, the grammar and syntax are interesting.

The analogy that comes to mind is that of Sign Languages for the hearing/speaking impaired. There is not a single, common signing language – there are local variants that have matured over time. For example, American and British Sign Language share a large percentage of their structure with French Sign Language, but with enough local nuance and turn of phrase to be fundamentally different. The way in which you structure a sentence in Sign Language is different to what how it may be spoken, though. This is Ruby, in a nutshell.

As with Python, there was a bit of a learning curve. I’m going to summarise it here, as once I got into the rhythm of porting the code, it went along better than I expected. This was probably my fastest conversion – which after five previous attempts, you would kinda hope for.

  1. Import vs require – The Ruby equivalent of ‘import’ is ‘require’, or more specifically, ‘require_relative’ when loading a library/module that is in the same folder as your code.
  2. Don’t @ me – Whereas PHP uses a dollar sign [$] to indicate a variable, Ruby uses the @ symbol. However, when using variable objects that have been passed to a Class method, the @ is not required. For example:

A simple trick was this – when executing code, if an @ had been left off of a variable object name, the compiler assumed there was a method of that name to be found, and would fail. This was a cheats way of finding untidy code.

3. Get me the attributes – Ruby has a handy function named attr_accessor which exposes the attributes of Classes within other Classes, similar to a ‘getter’ method in other languages. I discovered this the hard way (is there any other?) when trying to figure out why I could not read or write to the p_pieces attributes of instances of the Player Class from the Game Class.

attr_accessor gets past having to create separate getter Classes, and could be limited to only apply to specific attributes, like so:

4. New things – The noun-verb grammar of Ruby took some adjustment. Whereas in other languages you would instantiate a new Class object by assigning a variable with new Objectname(), in Ruby it became:

…to create a new array of p_pieces and then assign a new instance of Marker to it. This in turn would trigger the initialize method to instantiate the Class object.

Extending that array – and adding four more Markers – used the now-familiar push function, like so:

5. Bracketing without parentheses – As you can see from the code snippet above, Ruby does not terminate lines with punctuation – no semi-colons to be seen, here. However, it does re-introduce one of our friends who was missing from Python – an ‘end’ statement to show the termination of an iteration or conditional. I respect this – it’s very Japanese. Not overly verbose, neat and orderly.

6. Random made simple – Generating random integers was disturbingly simple. I’m just going to leave this method here, as it’s self-explanatory. Didn’t even need to ‘require’ anything to get it to work.

7. String parsing – There must only be a finite number of ways that a string can be assembled that includes several variable strings and constants. I thought I’d found them all until I came to Ruby, which introduced the # and curly bracket { , like so:

Basically, enclosing a variable or method call inside of #{} inserts the value or result accordingly.

8. Looking inside – The search-in-an-array function was also quite elegant. This seemed to be the way with more contemporary languages, as per PHP and Python. To return a Boolean testing for the existence of x_temp_value in array x_temp_magic_numbers:

9. How long is a piece of Array? – after some esoteric results from previous languages’ calls to determine array length, it was (unsurprisingly) fairly elegant to find that Ruby actually gave you what you were after… the actual number of items in an array which had been populated.  Using this as an iteration upper-boundary looks like this:

(and yes, that is an old-school ‘newline’ character being piped to output. Be still my beating heart.)

All that glitters

The verdict? I didn’t mind it. A few weeks later I used my new-found Ruby skills to fix something in Liquid which would have otherwise confused the hexadecimal out of me. It takes some getting used to, but having gotten into a rhythm of code translation and with the online assistance of those-who-have-gone-before, it’s pretty approachable.

NEXT POST… The next challenge came in testing some basic comparisons – which language executed the algorithm the best? The results were… unexpected, and led me down a deep dark warren of data analysis.