Thursday 17 July 2014

Writing Clean Code

Been awhile since my last post!

The last weeks have been refining our skill at using Ruby On Rails and going back to the basics. Most of this week has been about refining our codes and writing them cleanly, to make sure we have good conventions in terms of our writing code, and being able to go back and refactoring them.

This week we had 3 apps to practice writing clean code on. We had several sources to guide us this week.

First we had a video conference shown to us by Sandi Metz. She spoke about the design principles of SOLID object oriented code design; Very helpful to get a good foundation on how to start writing code. It aims to act as a guideline where to start writing the code and a set of principles to keep in mind.

  • Single Responsibility - no more than 1 reason for classes to change and the class should have only one responsibility
  • Open/Close - modules should be open for extension but closed for modification
  • Liskov Substitution - Objects should be substitutable by instances of its subclasses without affecting the program
  • Interface Segregation - Don't make a class depend on methods its objects might not use, and specific interfaces are better than a single general purpose interface
  • Dependency Inversion - Depend on abstractions, not concretions.High level modules shouldn't depend on low-level modules, and both should depend on abstractions.

On the second day we had a video from Aloha Ruby Con 2012 featuring Thoughtbot's Ben Orenstein speaking on refactoring from good to great. His talk highlights the importance of shifting methods to classes and minimizing the size of methods as much as possible. It's important to consider when your code can be shortened or refactored after you first make it. Methods should be written clearly and be as succinct as possible, and where variables are often repeated or passed around constantly it is usually best to shift the methods or variables to classes. That way, there are shorter classes, shorter methods and they are targeted and compartmentalized. This is an important concept to grasp to write clean code.

On Wednesday, we saw a talk by Avdi Grimm in Ruby Midwest 2011, speaking of confident code. The important message of the talk was that when writing code, we should 'tell, don't ask'. Code we right should have as little case statements and queries onto the properties of variables as much as possible, or else we run into the issue of 'timid code'. We need to adhere to duck typing - where we treat objects as what they are without having to ask what they are. This is exceptionally important with NilClasses, which is probably the most common cause for a query onto the class for the variable. In short, we should avoid 'if class == nil' statements, and simply handle NilClasses as if we expected them to come, or any other class that might come down our program. It's an important philosophy to grasp, where we own and understand our code. In the case of timid code, we would ask or approach the code carefully, which implies we don't understand or own the code we've written. or are reading.

Avdi's particular talk was very fascinating, and it was incredibly helpful in overcoming a programming challenge we had that day to query for hotels from a database, which I'll describe here. This particular blog post by Avdi describes the Null Object and their level of falsiness.

Between all these talks, we had a good grounding to stand on to start work on several programming challenges aimed at improving how we write code cleanly and how to refactor them after the fact, along with the process of handling pull requests.

For our programming challenge, we have to load up a CSV file that contains a table of various hotels/properties (I refer to them as properties, in case the list contains hotels, motels, inns, etc.), and the app will inquire the user for the name of a hotel they're looking for. It will print to the user details on the hotel if it is found, and when there is no property with a name they've written, it will tell the user no such property exists.

We have the main class, PropertyQuery which is what the user will be interacting most frequently. It takes in a properties variable on initialize, which should contain the table that should be read up by another class that returns the data. It is stored in the instance variable @properties. Afterwards, the instance of the class calls for the basic query process to be called in the method ask_user_for_query.

First, we'll look at how the class PropertyReader takes in and processes the table file. After the data is processed, it'll take the data and pass it to PropertyQuery.new as  This is the .csv file:


Very simply, it has the hotel name, the city it's located in, the phone number, and the number of single or double rooms. This information needs to be passed into the PropertyReader class instance:

In this class, it takes in the file when an instance of PropertyReader is created and passes it to instance variable @file. It fills in @properties with new Property instances (see below) using the foreach method called with headers set to true as an option to take in the .csv file by row with the first row being for headers.

Each row is taken in as a hash with the headers being the keys, and the items in the rows being the values. Each row is a new instance of Property containing this key-value pair. While it is entirely possible to write up code to avoid using a new class altogether and creating individual hashes to fill @properties with instead, it's highly inefficient. We'd have to make explicit references to a specific hash shoveled into the @properties array or even worse call .each on it (which is very ineffective if the hash has a lot of records). Not to mention, we'd have to pull out the keys to obtain the values of particular item in the array we're looking for, and it makes it very difficult to read and conceptualize, and clogs up the code or class with so many additional methods and lines.

One of the things we learned during the 3 talks is that coders are often very timid or afraid to push their methods and code onto new classes. New classes actually make it very easy and saves up space (a huge plus) and improves readability, and enforces the tell, don't ask policy. We'll be able to take better grasp of our code by being able to define our own methods and properties onto our instances of classes. The thing about instance of classes is, they are very malleable. By shifting our thought process from simply compartmentalizing our code into single, large classes and onto classes as a collective, we're capable of confidently wielding the code we write as we see fit.

So to recap: we've made new instances of Property, which don't even need a variable name associated with them (a unique identifier based on object ID is created for every new instance). And these instances contain a hash of information (keys being the headers on the CSV file, values being the respective values associated to a single property like the name, city, etc.). These are all shoveled into an instance variable @properties within an instance of PropertyReader. Now, what can we do with these instances of Property? We want to be able to access their information, and by nature we can't access methods normally available to hashes when we have the instances outside the class (due to the hashes being in instances of Property). So how would we access them in another class' method? First, we define getter methods within Property, like so:


By having these methods on hand, we can call name on instances of Property to obtain the value of "Hotel", which is the name of the hotel. Or phone for the phone number of that Property instance. But recall that we are shoveling these instances into an instance variable within PropertyReader...


Which means that we'll need to be able to pass that array of instances containing a hash onto our main PropertyQuery class. For that reason, we call attr_reader on it to have a getter method we can use in our PropertyQuery:

Look at line 29-32 in particular. We load up a new instance of PropertyReader that takes in our .csv file, then it uses the command read_file on the instance to obtain and shovel the data into @properties within it; and then when we load up a new instance of PropertyQuery, we pass in property_reader.properties (a getter method we obtain when we used attr_reader on @properties). This gives us access to the array of instances of Property for use as our argument in PropertyQuery. Finally, on initialize, this gets passed into our instance variable @properties. Ultimately, this gets used in the method on line 24.


When this program is run and the data is loaded up into a PropertyQuery instance, the users are asked to put in the hotel name. Their query is passed into find_result, and their query is checked if it exists within our array of Property instances using .detect. With .detect, each item in the array is checked for a true condition and returns what was found. And here, with our instances we can use our defined .name method to obtain the value of the Hotel key in our instance. The first match is passed off as true and that will tell us we've found our hotel, returning that instance of Property. Earlier in the method definitions for PropertyQuery, the next step after query_for_property was to run .display, which is also a method for instances of Property to show all details for the property found.

However, note the || OR condition in the detect. Assuming there's no matches, then .detect will naturally return nil. But in this case, NullProperty.new is run in case the first half of the .detect command returns false, instead of just returning nil.

A timid programmer, as Avdi might define it would put an if statement to check if the return was nil. That's 3 lines at the minimum to check if @properties.detect returned Nil or NilClass! So what does NullProperty.new do in this case?


In short, this NullProperty class contains a method, display. Keep in mind that with instances of Property, we have a method for display too - but that does something vastly different. And PropertyQuery was written with the intention of doing .display following the find_result method was run - so no matter the result of @properties.detect, we'll always run .display on whatever we get - and instance of Property, or an instance of NullProperty.

This way, instead of going to ask and thus coming up with a case condition when we run into Nil in our query, we've managed to take control of Nil when it comes up (inevitably) in the user query. For that reason, the method find_result in PropertyQuery can only have one line.

By being able to use Class instances in this way we can be far more flexible and save a lot of lines. Our methods become far shorter and smaller, it becomes better to read (compared to the alternative we might've had to face), and it becomes less dependant on each other. By being less dependant, we're able to refactor this code if necessary without breaking another part of the code. This follows a fair bit of the Tell, don't ask philosophy and shows duck-typing - treating classes for what they are and not asking if they are of a particular class.

Next up in the exercise is to be able to use fuzzy searching with Regexp so we're able to find or suggest hotels that make partial matches in the name - in fact, remember the Zombies challenge I wrote about almost two months ago? The code is probably a bit of a mess, and it could definitely use a cleaner, effective rewrite - and now that I know about Regexp for fuzzy searching, I might even be able to cut down the code substantially to find matches or duplicate terms in the zombie dictionary...

I'm constantly reminded google searching, docs and other people are incredible help to find information and new tips. Videos, books and blogs are huge resources, and I really have grown to appreciate them.

So hopefully, this blog post comes up and helps you out somewhere down the line! Thanks for reading. :) Feel free to comment and let me know if there's a gap or something I misunderstood, too! I appreciate it.

Link to Git Repo: Here

Monday 7 July 2014

Foraying into JavaScript

Today begins the day where we learn JavaScript. My experiences with JavaScript are numerous, though how fruitful it is varies. At times, they go great. Othertimes, they don't. My biggest JavaScript run-ins are a somewhat-unfinished mod for Skyrim using the CreationKit's JavaScript-based papyrus, or when I tried to make Android apps. JavaScript is fairly difficult and compared to Ruby, a lot less 'face-value readable'.

So our first exercise in learning how to apply JavaScript to webpages is to make a very simple calculator and guessing game. Straightforward, very simple. And below are the notes I took as we were going through it as a class.



JavaScript gives us the power to make dynamic things happen on the client side. Where Rails and the Rails stack processes and renders views server-side, but java-script tells the user to render on the client. Browsers all accept JavaScript. ECMAScripts organize JavaScript and standardize it. It allows the user to interact with the Document Object Model, or the DOM. We can send smaller requests to the server via JavaScript instead of large chunks of whole views so it becomes more dynamic.

By default, a submitted form in HTML with no direction will send a get request to itself with the params. It won't actually send anything; but the params itself need to be obtained through the URL - which is the name field in the input tags:

    <input type="number" name="left">

This will make a query-param get request with left having a value of what we had put in, with all params separated by ampersands:

    /calculator.html?left=5&operator=*&right=3

--
HTML has a callback for forms, called onsubmit, which allows us to call javascript function. JavaScript functions can be passed around and will not run until called. Callbacks listen for events and will do an action when it happens. To prevent the forms from doing it's defalt behaviour for submit (as described abve - get request to itself), we can use return false in the onsubmit form.


To begin writing javascript in the html file, we can use <script> tags in the header.

To define a function in JavaScript, we define it with function:

    function calculate() {
       
        }

Where parameters are required, all functions must contain a param bracket (). All variables in the function need to be defined by 'var' then the name of the variable, and then to obtain params from the elements on the website we can call getElement on document. Specifically, we can getElementById (for example, our input type friend called left), thus:

    var left = document.getElementById("left").value

But we have to make sure that we defined "left" as an ID in the form itself:

    <input type="number" name="left" id="left">

In addition to being able to define and store param variables, we can also log them:
    console.log(left)

When we do:

    if (operator == "+") {
        console.log(left + right);
    }

We'll be adding the var left with var right. However, they might come out as strings:

    log:
    3 + 2
    32

Which doesn't work for us. We have to typecast them (basically, turn them into integers in this case). Type casting in JScript basically parses in a parameter to a constructor and makes a number object:

    var left = Number(document.getElementById("left").value;

And now we re-run the submit:

    log:
    3 + 2
    5

If we wanted to do live debugging, we can put in a debugger statement:

    <script>
            function calculate(){
            var left = Number(document.getElementById("left").value);
            var right = Number(document.getElementById("right").value);
            var operator = document.getElementById("operator").value;

            debugger;

            }
    </script>

It will pause the script as it is running upon reaching the debugger. It allows us to debug whenever it makes a request for a parameter or call anything in that context. Very useful.

Javascript will allow us to append or add dynamically to the view. So if we want to display the results of our calculation. To where we want our calculation result:

    <p>Result: <span id="result"></p>

We also have to make sure that we specify the variable and get the element by its ID:

    var result = document.GetElementById("result");

And then we also have to allow the variable to change the value of a particular element in our calculation itself by calling innerHTML on the variable:

    if (operator == "+") {
    result.innerHTML = left + right
    }

And that should do it!


Complete gist here .