Ruby Strings – How to Put String With Single Quotes in Single Quotes

I set up a series of Ruby unit tests to better explore SED.  Basically, I invoke it as follows:

def sed_result(input_str, sed_str)
     %x[echo #{input_str} | #{sed_str}]
end

It worked well, until I did this:

assert_equal("howdy\n", sed_result("howdy from Texas", "sed 's/\([a-zA-Z]*\).*/\1/'"))

Assigning the latter string to a variable in ruby produces a different string, because strings in double quotes are processed: “sed ‘s/([a-zA-Z]*).*/01/'”

For example, when I want to do string interpolation, I have double quotes instead of single quotes as follows:  “The value of foo is #{foo}” to the string “The value of foo is bar”.  This time, I don’t want any processing of the string, but want to pass it as is.  Thus, I need to use single quotes, except my string contains single quotes. What to do?

Well, the following use of %q[] is the same as using single quotes, and worked well:


assert_equal("howdy\n", sed_result("howdy from Texas", %q[sed 's/\([a-zA-Z]*\).*/\1/']))

Additionally, you can use %Q[] in place of double quotes.

Advertisements

Spawning a Process in Ruby

A good way for me to learn code-related technologies is to write unit tests.  It helps to work through the nuances, and gives me something I can go back to refresh myself as needed.

Right now, I have been going through SED, which does not have an associated unit test framework.  To test this, I want to use Ruby and then spawn a process to execute SED and then get the results back for the assert_equal call of all my tests.  I want to do this while avoiding the overhead of using files and file redirection (where possible).

I obviously can’t use Kernel::exec, as that will replace my currently running process and end my testing real quick.  I want to do the following:


     system("echo #{input_str} | #{sed_str}")

Where input_str is the input SED is processing, the sed_str is the SED command str.

Of course, I can’t do this as this is two processes being piped together.

If I use read and write files, I can do the following:


     system("#{sed_str} output.txt")

In the end, I got it to work as follows:


def sed_result(input_str, sed_str)
     %x[echo #{input_str} | #{sed_str}]
end

There are other options to look into – IO.pipe, IO.popen and Open3 (among others).  But I have a lot of SED unit tests to write first!

Talent is Overrated and Deliberate Practice

Recently on the This Week in Tech podcast, I listened to Jason Calicanis extol the book Talent is Overrated.  I picked it up on Audible and listened to it back and forth from work for the past two weeks.

The major premise of the book is that we often grow up with the myth that people either have a talent or they don’t, and that that is what their determines their successful (or its corollary – you must have a great inborn talent and practice).   It vigorously tears down this myth in regard to Mozart, and then Tiger Woods.  In a nutshell, sustained practice is what determines your level of success.  And not just any practice – deliberate practice, which is often not very fun.

It reminded me of “Asians are intrinsically better a math” myth that is debunked in Malcolm Gladwell’s Outliers.  A hard work culture that results in lots of hard work and practice in math, a discipline that requires a lot of practice.  I have shared this with my daughter many times vis-a-vis math as she studies to get into college and become a doctor.  But have I shared it with myself enough?

How many times have you worked with a programming wonderboy and attributed it to a natural talent that very few people have?  How often have you let yourself off the hook due to this?

This last year has been an intense year of deliberate practice for me.  Outside of work, I spend 15-20 hours a week studying computer science – learning new languages, mastering old ones, new OS’s, techniques, technologies, etc.  It has been a lot of deliberate practice, and my skills are far superior to what they were a year ago.

I have also noticed that the more I study, the easier it is to pick up new concepts I come across.

In addition, I have developed an absolute passion for programming that I had not experienced in a while.  All of this is leading to more deliberate practice and greater proficiency, as well as widening of the areas I am interested in and studying.

My latest thing is going through the Ruby Quizzes from Pragmatic Programmers.  I am not doing it to learn Ruby, but to write better Ruby.  The exercise in writing the best Ruby code I can, comparing it to example, and making changes it making me a much better Ruby developer.  I am learning about my strengths and weaknesses as a developer, and focusing on improving those weaknesses instead of doing the same old thing over and over.

Clean Code

I listened to “Uncle Bob” Robert Martin talk about Software Craftsmanship on either the Software Engineering Radio or Pragmatic Programmer podcast.  It got me thinking.  I have been studying a lot of programming languages and technologies lately, but when was the last time I focused on pure coding itself?  I was a like a painter learning about oils, acrylics and water colors – but it was time to focus on the cross-cutting techniques of painting applicable in any medium.

So I picked up his book – Clean Code, and summarized the contents to be able to repeatedly refer back it.  A number of the things he covered I already knew from an earlier study group on Martin Fowler’s Refactoring book.

Understanding it intellectually was not going to be enough so I picked out one of the quizzes from the Ruby Quiz (Pragmatic Programmers) and tried to apply it.  At the same time, I also decided to do full “Orthodox TDD”, where I did not do any development until I had a failing test.  I worked through some design alternatives up front, and then proceeded with the one I liked.

It was slow going.  I tried to be as true to the book as possible, and then meant a lot of refactoring as I thought of new ways to create cleaner code based upon the book.  As much as I like Ruby, Java is definitely an easier language to refactor (but thank heavens for all the unit tests – a necessity in Ruby).  I have seen a book out there on Refactoring in Ruby, and I may pick that one up.

But slow going is okay.  When you study martial arts, you are supposed to go slow as you apply the techniques.  With practice, speed comes later on top of perfect technique.  In this practice scenario, I was doing just that.  This was the major reason I was doing this on a home project as opposed to work, where speed is obviously more important.

More challenging than I expected was creating extremely well named entities – a lot of rename refactoring took place.  Nonetheless, the number of comments I had in my code was extremely small – it was unnecessary as the naming told the story.  I tried to follow his newspaper model of letting my code tell the story in various levels of detail – this worked out well in the end.  Plus, the lack of comments that were not there that typically were “because they are supposed to be” made the code much easier to understand.  It was better, and liberating.

I did struggle with some things.  The breaking down of all the methods into small methods ended up with a lot of lower level methods.  While the methods were extremely cohesive, there were a lot of them.  A good signal to me that I had broken them down into too many sub-methods was the extreme difficulty I had in creating names for them to show their intent without using any type of synonyms.  Based upon that, I recombined some of the methods.

I also struggled with his advice on not using return codes or error codes.  In his statement, if your method performs a state change on the object and returns a return code, it is doing both a state change and a query, violating the cohesiveness of the method.  By throwing an exception instead, the method is more cohesive and the consumer can write less complex code.  Plus, if you refactor complex methods into multiple more cohesive methods, having to check for return codes permeates through each invocation, increasing code bloat.

Nonetheless, this seemed to run against Joshua Bloch’s advice in Effective Java on using Exceptions only for exceptional conditions as well as the overhead associated with them.  I also did not like having to create a new Exception class as this seemed to increase the necessary mental model for code.

Then, I thought on the pattern typically found in Enumerators – a cohesive querying hasNext() method along with a next() method that either returns the next entity or throws an exception if one is not found.  How many API’s had I seen lately where they had been modified to offer a similar query method, or offer variations of methods that either returned an error code or threw an exception.  I am seeing the value, but I am continuing to work through this.

Overall, this is an excellent book to study.  I will continue to apply it as I work with other technologies at home to improve my general coding abilities.

Shell Script with SED and Last Line Missing

I wrote a shell script that used SED to make context-specific changes along with copying files (among other things).  Out of the six scripts only one of them consistently experienced a problem – the last line was missing in all of the copies.

I wondered if there was some kind of dependency between the steps where something wasn’t getting properly written out, but that seemed odd for Unix.  I tried to do line by line comparisons to find the error in my shell scripts.  Finally, I came up with a different solution – simply add an additional blank line to the file to be copied.  After that, everything worked fine.

It wasn’t until I was studying SED in more detail yesterday that I realized that this was a necessary step.  SED seemed to ignore transforming or working with the last line of input that did not end with a newline.   I find this odd – if the last line of a file does not end with a newline, SED will ignore it?  There has to be more to the story than that.

Anyway, I am about halfway through my study with SED and will blog on that and then move on to AWK.

Clean Code and the 5S Principles

I recently listened to “Uncle ” Bob Martin giving a podcast on Software Craftsmanship on Software Engineering Radio, and decided to pick up his book Clean Code – A Handbook of Agile Software Craftsmanship.  I was struck by the forward by James O. Coplien of Denmark on the 5S Principles and how they tied to maintenance instead of production in Total Productive Maintenance (TPM).  Furthermore, these principles as applied to the maintenance floor apply equally well to software:

  • Seiri (organization). You need to be able to find things easily.  In software, proper naming helps you find things easily.
  • Seiton (tidiness; systematize). Everything has its appropriate place.  Code should be where it is expected to be, and if not, refactor to get it there.
  • Seiso (cleaning; shine). Keep the workplace clean for easier thinking (think grease, wires, etc.).  In code, leaving commented-out code and inappropriate comments increases mental clutter that has to be overcome.
  • Seiketso (standardization). The group agrees on how to keep the work place clean.  Consistent coding standards and patterns apply here.
  • Shutsuke (self-discipline). Having the internal discipline to follow the practices and to reflect on one’s work.

If you take a moment to really think about these parallels between the factory maintenance floor and the code we have to work in, these practices that reduce mental clutter on the factory floor apply equally well to developers working with code.  Less clutter means higher productivity and later mistakes.  For me, it was like a light bulb turned on.

One of his major points is that in coding, we spend 90% of our time reading, and only 10% of our time writing.  Thus, what we do to improve the efficiency of reading carries further weight.  Unfortunately, we are measured (subjectively or objectively) in terms of writing productivity, passing the costs on to fellow programmers later on.

It reminds me of what I wrote earlier while musing on Steve Krug’s Don’t Make Me Think as applied to web site design and usability.  By writing clean code, we require later developers to not have to think more deeply than necessary when reading and using our code by reducing misdirection and mental clutter.

I’m on page 21 of the book now, and looking forward to working through it in continuing to improve my own software craftsmanship.

Fluent Interfaces in Ruby

I had a chance to look at what Neal Ford had to write on Fluent Interfaces in his book The Productive Programmer.  Granted, I heard him cover it before at one of his presentations at the No Fluff Just Stuff conference in Reston, VA.

Basically, fluent interfaces have setter functions return self (or this in Java).  By doing this, you can chain the setters together into what looks more like a composed english sentence instead of multiple single-line setter statements.  I find it easier to code and read code written in this manner (particularly in the jQuery style).

Sitting here watching Olympic couple’s figure skating with my wife, it seems like the perfect time to put some example ruby code together for this (as well as the Self Yield spell from Paolo Perrotta’s Metaprogramming Ruby):

class Car
    attr_accessor :speed, :wheels, :direction

    def initialize
        self
    end

    def moving_at(mph)
        self.speed = mph
        self
    end

    def with_wheel_count(count)
        self.wheels = count
        self
    end

    def heading_toward(toward)
        self.direction = toward
        self
    end

    def display
        puts "speed is #{speed}"
        puts "moving in direction #{direction}"
        puts "number of wheels is #{wheels}"
    end
end

car = Car.new.moving_at(65).heading_toward("NE").with_wheel_count(4).display

attr_accessor would not have returned the object instance, requiring a different line for each mutator.