Sunday, November 23, 2014

Refactoring code along the lines of the DRY principle by leveraging the power of Ruby blocks and lambdas

In my early days as a ruby programmer, I used to always look for good examples through which I could understand Blocks and lambdas in Ruby. I did understand them after some research but I guess the connectivity of a real life e.g., was somewhere missing to help me remember how can one use them always. That's how I relate to this post and here's an attempt to help drive home the concept of Ruby lambdas and blocks for beginners at least to some extent. This has been tried and tested on Ruby-1.9.3p484

Here we'll try to explore how one could leverage the power of Blocks and Lambdas to make your code look more clean by refactoring one's code along the lines of better adhering to the Don't Repeat Yourself(DRY) principle.

Below is the original code of a singly linked list before any refactoring is done -


Refactoring 1 - 

Problem Context - Methods list_count(returns the number of linked list elements)  and list_elements(list the linked list elements) basically traverse through the entire linked list including the last node and both have a duplicated linked list traversal condition @current_pointer != nil .

To do - Remove the above duplication

Solution - Blocks to the Rescue! 

Adding blocks - If you have a look at the list_elements and the list_count methods they have duplicated for the lines 35-39(excepting line 37) and 45-49(excepting line 48). This doesn't adhere to the DRY principle and hence requires further refactoring. 

Below is a screen shot of what gets changed. You can have a look at this commit which shows the full modified version of the code as part of the first refactoring.


End Result - Lesser lines of code.

Refactoring 2 -

Problem Context - If you observe carefully, you'd find the other traverse_list method has the linked list traversal condition @current_pointer,next_node != nil and they are used to add a new node to the linked list at the end through the add_in_end method and the same is used in the get_tail method to get the last node. With the above condition, the current pointer stops at the last node but on the other hand with the condition @current_pointer != nil used by the list_count and list_elements method use the current pointer goes past the last node to satisfy the specific method requirement. The question now is, can we still remove any further duplication? The answer is yes.

Solution - Introducing Lambdas because we can't use past multiple blocks to methods in Ruby 1.9 . Read this link for more info.

Below is a screen shot of what gets changed. You can have a look at this commit which shows the full modified version of the code as part of this refactoring.


End Result - More concise solution adhering to the DRY principle.

Credits to the Pickaxe book by Dave Thomas for the learnings and to Avinasha for recommending this book.

P.S: This code has scope for further refactoring. I have just taken two sample use cases in an attempt to try and explain Blocks and Lambdas in Ruby.

Saturday, November 22, 2014

Think simple and Look within as a way to solve problems

There are so many times in life that we think we look outside for the solution of certain challenges we come across or certain things that we may encounter in day to day life. Looking outside helps, but not always.

Solution of many problems is within. Recently, I came across two experiences that makes me echo this thought and which make realize how much I got to improve on this way of doing things as well.

Experience 1 -

Problem/Concern - I always found it difficult to keep track of so many tweets from the different folks I follow on twitter on a day to day basis, I was wondering how to get around this.

What I used to do -
1) To some extent after some amount of exploration, I figured out the way of doing this is using the 'lists' feature in Twitter. That helped to some extent.
2) Not satisfied, I still was experiencing the problem so I used to keep thinking 'outside' for a better way of doing this.

A better solution - Although I don't have a complete solution yet, but the below point has helped me tackle this problem better at least to some extent.
1) Often one might be tempted to follow new folks on twitter, it's also equally important to regularly 'unfollow' those tweeple whom you think aren't adding that much value. I know this might be 'common sense' as one would call it, but it's just the way I at least thought of it initially was - may be I need to use some external service(some third party website) or similar stuff on those lines to manage my tweets better. 

Moral - The solution was within Twitter itself. Think Simple :). Think Within..

Experience 2 -

Problem/Concern -  To set a context, I'm a web developer who uses Ruby on Rails, a framework that's used to make websites. I find it sometimes difficult to keep a track the development log in the terminal for any new action I perform as a end user through the web interface of the application whenever there is a background process running within the application which may be for instance is constantly polling something for real time updates that would eventually be displayed on the UI(User Interface) .

What I used to do -
1) So I use an editor called Sublime Text for day to day development. Their search functionality is pretty powerful, so I used to go into the development log and find may through the log to find the things executed as part of the most recent action executed on my part from the UI.
2) I used to do a 'rake log:clear' to clear the log often so that my search can retrieve faster results.
3) Sometimes, in the past I used to even comment out that piece of code that runs a command which triggers the functionality to regularly check for updates. I was doing this in the local box so  I took this approach. I do realize now, it's not the ideal way of doing things especially when you have automated tests in place which might probably link your background process related functionality with what you'd be newly implementing.

A better solution -
1) Simply do a 'Ctrl + C' to stop tailing the dev log soon after you've executed your action from the UI and you'll have the most recent set of actions to explore from the terminal itself. This prevents you from digging out the solution from elsewhere. Isn't that a faster way of doing things? I didn't think of it at least.

Moral - Don't look for something outside(looking into the editor) which involves more effort(searching, cleaning up) when things can be simply achieved within the same terminal itself.

Overall Moral - Think Simple. The solution is within, not without :). 

Credits for the better solutions go to suggestions by Avinasha Shastry.

P.S:- Pardon me for the technical jargon if you don't understand much from this feel free to give me a shout or use google to help you understand the problem 2 better. I've made an attempt to make problem 2 to be understandable by any lay man.

Also, I'd be really happy to hear from folks who have been able to find a better solution to Problem 1, if any better solution exists.

Cheers.