brunops

  • Are you able to write your code in less lines?

    06 Feb 2013

    Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

    -- Antoine de Saint-Exupéry

    Are you able to write your code in less lines? I’m always asking myself this question. I consider it to be a great way to improve coding skills, I mean, yeah right, you’ve got your stuff working, but, are you able to improve it? I’m not saying to sacrifice legibility towards less lines, but instead, to face it as an exercise, to test your own abilities. A way to dig deep into your programming language syntax peculiarities.

    As soon as I started programming, I considered less code as better code. I sure changed my mind about that now, as you can see in Get better by challenging yourself, but I still think this is a great way to really understand how statements work and interact with each other.

    What are you talking about? Ok, let’s see an example. Consider a C code to loop through a string and print its characters

    First our declarations, they won’t change

    #include <stdio.h>
    #include <string.h>
    
    int i, strSize;
    char *str = "my string";
    
    strSize = strlen(str);

    First attempt

    // Easy problem, give me two minutes..
    
    i = 0;
    while (i < strSize) {
      printf("current letter: %c\n", str[i]);
      i++;
    }

    Okay, that’s a great loop, congratz, but… Are you able to write your code in less lines?

    // Pfff, that's easy, I was just playing, check out..
    
    for (i = 0; i < strSize; ++i) {
      printf("current letter: %c\n", str[i]);
    }

    So you did a for loop, so cute, isn’t it? Can you write less?

    // Of course I can write less, can you read it?
    
    i = 0;
    while (i < strSize && printf("current letter: %c\n", str[i++]));

    LESS!

    // Eat that one lined while, you #%$"&@%!
    
    while (*str && printf("current letter: %c\n", *str++));

    They’ll all output the exact same result! My point is, lots of concepts are required to do this piece of unreadable code, like: more than one statement inside a loop condition, pointer arithmetic, operators precedence, and so on!

    There are many things you can learn, like:

    • an empty, infinite, for loop
    • for loops with more than one inicialized varible or increment statement inside it, separated by commas
    • nasty pointers arithmetics
    • call functions inside functions inside functions.. in a way to shrink 10 lines into one

    I’m not saying to ship this ugly code as final, but to practice. Stuff you can understand and that other people won’t, or at least have a hard time figuring it out. Suddenly you’ll find yourself able to shrink codes to a point its legibility is still unaffected, but mostly important, you’ll learn many different ways of doing the same thing, thus, evolving.

    And remember: There is more than one way to do it! TIMTOWTDI

    » Read full post
  • Get better by challenging yourself

    23 Jan 2013

    I consider legibility to be one of the main goals of a code. Maybe your boss won’t agree with me at a first glance but, believe me, he should. Hours and hours of development are spent recklessly only to understand what another simple minded, careless programmer did. And sometimes it’s worse, because this programmer was you a couple of days ago.

    » Read full post
  • Random quote

    27 Dec 2012

    The seek for perfection without moderation is frustration

    » Read full post
  • JavaScript and Lookbehinds

    27 Dec 2012

    I’ve been poking around with some redirects that I needed to perform with RewriteRules in Apache configuration. This story deserves its own post, and I hope to post it soon. So, long story short, I had to deal with some complex regular expressions (regexes). The regex started simple, but soon grew bigger when covering other scenarios and trying to keep it in only one expression.

    I basically had a couple scenarios that I wanted my regex to match (or not), and needed to keep testing it, as any minor change could compromise the whole test suite. “That’s simple”, I thought, “I’ll create a super JavaScript code that will perform all my tests at once”. It started pretty well, I had to figure out how Apache treats urls and deal with the RewriteConds, but not a major problem. And after that I was able to simulate its behavior and check the results on a <irony>nice, extremely awesome, super stylized HTML table</irony>, really great, right?

    Basic HTML for the tests:

    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Test Cases</title>
        <script src="http://bit.ly/jqsource"></script>
        <style type="text/css">
          tr.pass {
            background: #72DA72;
          }
          tr.failed {
            background: #EB5C5C;
          }
          body {
            font-family: "Courier New";
          }
          table {
            border-collapse: collapse;
          }
          table, tr, td {
            border: 2px solid black;
          }
          tr:first-child td {
            font-weight: bold;
            background: #CCC;
          }
          td {
            padding: 5px;
          }
        </style>
      </head>
    
      <body>
        <table id="tests">
          <tr>
            <td>#</td>
            <td>Test Case</td>
            <td>Should match?</td>
            <td>Status</td>
          </tr>
        </table>
    
        <script src="testCasess.js"></script>
      </body>
    </html>

    JavaScript to Simulate Apache RewriteConds and Perform tests:

    var testCases = [
      { text : "node",                             shouldMatch: true  },
      { text : "/node",                            shouldMatch: true  },
      { text : "/node/30",                         shouldMatch: true  },
      { text : "node/30",                          shouldMatch: true  },
      { text : "nODe/30?param=123",                shouldMatch: true  },
      { text : "el-GR/node",                       shouldMatch: true  },
      { text : "el-GR/nODe",                       shouldMatch: true  },
      { text : "/test?q=node",                     shouldMatch: true  },
      { text : "/test?paramq=node",                shouldMatch: false },
      { text : "/test?p1=1&p2=2&p3=c&q=node&p5=6", shouldMatch: true  },
      { text : "/test?q=node/add",                 shouldMatch: true  },
      { text : "/taxonomy",                        shouldMatch: false },
      { text : "/taxonomy/term",                   shouldMatch: true  },
      { text : "/taxonomy/term/10",                shouldMatch: true  },
      { text : "/test?param=taxonomy/term/10",     shouldMatch: false },
      { text : "/test?paramq=taxonomy/term/10",    shouldMatch: false },
      { text : "/test?q=taxonomy/term/10",         shouldMatch: true  },
      { text : "/en/user/login",                   shouldMatch: true  },
      { text : "/user/logout",                     shouldMatch: false },
      { text : "/test?q=user/logout",              shouldMatch: false },
      { text : "/test?q=user/logout/bla",          shouldMatch: false },
      { text : "/test?q=user/logout/bla?aa=1",     shouldMatch: false },
      { text : "/some/big/path?q=user/10",         shouldMatch: true  },
      { text : "/some/big/path?q=/user/10",        shouldMatch: true  },
      { text : "/node-something/will/not/match",   shouldMatch: false },
      { text : "/something-nOde/will/not/match",   shouldMatch: false },
      { text : "/only/NoDE/will/match",            shouldMatch: true  },
      { text : "/admin/",                          shouldMatch: true  }
    ];
    
    // Anonymous auto executing function
    
    (function($) {
    
      // document ready
    
      $(function() {
        runTests();
      });
    
      var requestUriRegexes = [
        /^(.*\/)?user(\/(?!logout).*)?$/im,
        /^(.*\/)?(node|admin|taxonomy\/(autocomplete|term))(\/.*)?$/im
      ];
      var queryStringRegexes = [
        /\bq=(.*\/)?user((?!\/logout).*)/im,
        /\bq=(.*\/)?(node|admin|taxonomy\/(autocomplete|term))(\/.*)?/im
      ];
    
      // Run tests and format result in a table
    
      function runTests() {
        $.each(testCases, function(i, e) {
          var test      = this,
              status    = assertText(test),
              statusMsg = status ? getPassMsg() : getFailedMsg();
    
          $('#tests').append(
            $('<tr></tr>').addClass((status ? 'pass' : 'failed')).append(
              '<td>' + i + '</td><td>' + test.text + '</td><td>' + test.shouldMatch + '</td><td>' + statusMsg + '</td>'
            )
          );
        });
      }
    
      function getPassMsg() {
        return '<span class="pass">PASS</span>';
      }
      function getFailedMsg() {
        return '<span class="failed">FAIL</span>';
      }
    
      function assertText(elem) {
        var pass = false,
            requestUri  = elem.text,
            queryString = '';
    
        // Treat query string the same way as Apache
    
        var queryStringExists = requestUri.indexOf('?') != -1;
    
        // Define request URI and Query String
    
        if (queryStringExists) {
          var queryString = requestUri.substr(requestUri.indexOf('?') + 1),
              requestUri  = requestUri.substr(0, requestUri.indexOf('?'));
        }
    
        // Store result in "pass" variable
    
        $.each(requestUriRegexes, function() {
          pass |= this.test(requestUri);
        });
    
        // Apply same patterns on the query string
    
        if (queryStringExists) {
          $.each(queryStringRegexes, function() {
            pass |= this.test(queryString);
          });
        }
    
        // Log errors in console on fail
    
        if (!(pass == elem.shouldMatch)) {
          console.log('---------------[FAIL]');
          console.log(elem);
          console.log('requestUri: ' + requestUri);
          console.log('queryString: ' + queryString);
        }
    
        return pass == elem.shouldMatch;
      }
    
    })(jQuery);

    First 18 tests and results

    First 18 tests and results

    At first it was okay, and I managed to perform pretty much all of my tests using it. I know that I could (maybe should) have used a test library for it, like Jasmine, buy hey, it’s cool to reinvent the wheel once in a while, just to get the feeling that you can.

    This kind of tests don’t garantee that everything will work once rewriten to Apache rewrite rules, as they were only a simulation. So I still had to test it again on Apache once it was ready. Just to make sure… after all, regular expressions are pretty much the same everywhere, correct?

    Then, I continued to perform all my tests, trying out different odd combinations of possibilities. So, I was in the exercise of breaking my code, fixing the regex, breaking the code again, fixing the regex once more, and so on and so forth… Suddenly, I needed to use a lookbehind constructor in my regular expression to cover my tests. This is the point when things start to get weird.

    I had my regex set up an ready to roll, I had the great Regular-Expressions.info opened, things looked right, expressions should work, but they simply didn’t. I was trying to figure out why a simple expression as /(?<=a)b/ig.test(“ab”) didn’t match. Didn’t even have a correct syntax!

    Then, it hit me. In a glimpse of lucidity, I remembered that once upon a time, when studying a bit of regular expressions, I may have read that some regex flavors do not support everything. So googling a bit, I’ve ended up in the Lookarounds Section. As we can see, our dear friend JavaScript does not support lookbehinds. No one is perfect.

    I didn’t want to discard all my cool test suite that I’ve coded with such care. So I start searching for workarounds on how to simulate lookbehinds in JavaScript. I have found some solutions over the web, but nothing really worked well for me. And then, I realized that simulating over a simulation, is not what I call trustworthy.

    Time for a different approach. I would have to discard all my code, but that happens. The approach should be something that we really can put some confidence on. I couldn’t find anything really helpfull at first, so I got a bit demotivated..

    I forgot it for a while and started browsing random stuff, when I decided to check out the Yeoman project. Reading a bit, I’ve found about PhantomJS, and then, CasperJS. And here is where the story start getting interesting.

    And that’s the next subject. Automated unit testing using CasperJS. Hopefully, with less story, and more coding.

    » Read full post
  • Cool .bashrc File

    13 Dec 2012

    While working in Ubuntu, I feel my bash terminal as my home. Afterall, I spend a big part of my time there, so I need it to be nicely enjoyable.

    Here’s my .bashrc with my own configurations. It is a collection of configurations that I’ve found over the interwebz, and the lastest version can be found in my Gist.

    It’s a tweaked version of the .bashrc found here.

    I added the cowsay with the a fortune as well, so every time I open a new terminal I get a nice quote. Awesome.

    .bashrc result snapshot

    How cool is the cow?

    #### GIT &amp;&amp; PS1
    
    #  SETUP CONSTANTS
    
    #  Bunch-o-predefined colors.  Makes reading code easier than escape sequences.
    
    
    # Reset
    
    Color_Off="\[\033[0m\]"       # Text Reset
    
    
    # Regular Colors
    
    Black="\[\033[0;30m\]"        # Black
    
    Red="\[\033[0;31m\]"          # Red
    
    Green="\[\033[0;32m\]"        # Green
    
    Yellow="\[\033[0;33m\]"       # Yellow
    
    Blue="\[\033[0;34m\]"         # Blue
    
    Purple="\[\033[0;35m\]"       # Purple
    
    Cyan="\[\033[0;36m\]"         # Cyan
    
    White="\[\033[0;37m\]"        # White
    
    
    # Bold
    
    BBlack="\[\033[1;30m\]"       # Black
    
    BRed="\[\033[1;31m\]"         # Red
    
    BGreen="\[\033[1;32m\]"       # Green
    
    BYellow="\[\033[1;33m\]"      # Yellow
    
    BBlue="\[\033[1;34m\]"        # Blue
    
    BPurple="\[\033[1;35m\]"      # Purple
    
    BCyan="\[\033[1;36m\]"        # Cyan
    
    BWhite="\[\033[1;37m\]"       # White
    
    
    # Underline
    
    UBlack="\[\033[4;30m\]"       # Black
    
    URed="\[\033[4;31m\]"         # Red
    
    UGreen="\[\033[4;32m\]"       # Green
    
    UYellow="\[\033[4;33m\]"      # Yellow
    
    UBlue="\[\033[4;34m\]"        # Blue
    
    UPurple="\[\033[4;35m\]"      # Purple
    
    UCyan="\[\033[4;36m\]"        # Cyan
    
    UWhite="\[\033[4;37m\]"       # White
    
    
    # Background
    
    On_Black="\[\033[40m\]"       # Black
    
    On_Red="\[\033[41m\]"         # Red
    
    On_Green="\[\033[42m\]"       # Green
    
    On_Yellow="\[\033[43m\]"      # Yellow
    
    On_Blue="\[\033[44m\]"        # Blue
    
    On_Purple="\[\033[45m\]"      # Purple
    
    On_Cyan="\[\033[46m\]"        # Cyan
    
    On_White="\[\033[47m\]"       # White
    
    
    # High Intensty
    
    IBlack="\[\033[0;90m\]"       # Black
    
    IRed="\[\033[0;91m\]"         # Red
    
    IGreen="\[\033[0;92m\]"       # Green
    
    IYellow="\[\033[0;93m\]"      # Yellow
    
    IBlue="\[\033[0;94m\]"        # Blue
    
    IPurple="\[\033[0;95m\]"      # Purple
    
    ICyan="\[\033[0;96m\]"        # Cyan
    
    IWhite="\[\033[0;97m\]"       # White
    
    
    # Bold High Intensty
    
    BIBlack="\[\033[1;90m\]"      # Black
    
    BIRed="\[\033[1;91m\]"        # Red
    
    BIGreen="\[\033[1;92m\]"      # Green
    
    BIYellow="\[\033[1;93m\]"     # Yellow
    
    BIBlue="\[\033[1;94m\]"       # Blue
    
    BIPurple="\[\033[1;95m\]"     # Purple
    
    BICyan="\[\033[1;96m\]"       # Cyan
    
    BIWhite="\[\033[1;97m\]"      # White
    
    
    # High Intensty backgrounds
    
    On_IBlack="\[\033[0;100m\]"   # Black
    
    On_IRed="\[\033[0;101m\]"     # Red
    
    On_IGreen="\[\033[0;102m\]"   # Green
    
    On_IYellow="\[\033[0;103m\]"  # Yellow
    
    On_IBlue="\[\033[0;104m\]"    # Blue
    
    On_IPurple="\[\033[10;95m\]"  # Purple
    
    On_ICyan="\[\033[0;106m\]"    # Cyan
    
    On_IWhite="\[\033[0;107m\]"   # White
    
    
    # Various variables you might want for your PS1 prompt instead
    
    Time12h="\T"
    Time12a="\@"
    PathShort="\w"
    PathFull="\W"
    NewLine="\n"
    Jobs="\j"
    
    # cow saying your fortune (how awesome is that?)
    
    fortune -s | cowsay
    
    #show current project and branch
    
    GIT_PS1_SHOWDIRTYSTATE=false
    
    if [[ ${EUID} == 0 ]] ; then
      sq_color=$BRed
    else
      sq_color=$BBlue
    fi
    
    export PS1="\n$sq_color\342\224\214\342\224\200\$([[ \$? != 0 ]] &amp;&amp; echo \"[$BRed\342\234\227$sq_color]\342\224\200\")[$IBlack\t$sq_color]\342\224\200[\[\033[01;37m\]\u$sq_color]\342\224\200[$BGreen\w$sq_color]\n$sq_color\342\224\224\342\224\200\342\224\200&gt; $BRed\$("__git_ps1") $sq_color\$ $Color_Off"
    
    unset sq_color

    In order to work properly, it requires git, fortune and cowsay installed.

    It’s easy to notice that most of the colors definition are not used at all, but I like to keep all color definitions, so I’m able to change anything whenever I feel like.

    » Read full post