Translate

Archive for the 'Code' Category

5 Object Oriented Programming Principles learned during the last 15 years

Wednesday, February 1st, 2012

It was about 15 years ago when I first created my first class.

I went from thinking of Object Oriented programming as this awesome paradigm I should know about, I remember having all these mental models of what objects where and learning all this new vocabulary that I really didn’t fully grasp until years later when I was designing and implementing bigger more complex systems.

At first I remember looking at objects as a collection of functions that kept a common reference to keep internal states and missing out on all the great features of inheritance and abstract classes. Looking at “interfaces” and using them like a recipe without really knowing their true power, I look at the past and I was so limited, hopefully I’ll look at this post 15 years from now and think the same.

There’s lots of books out there on best programming practices you should follow, on this short post I’ll share with you 6 principles that I follow that I promise you will make your code behave really well, less bug prone, simple and elegant when it comes to Object Oriented design. This advice will probably apply better if you code in a language like Java or C#, I’m not sure if you can say these principles will apply 100% to other OO languages (for instance those that allow multiple inheritance)

1. DRY principle.
This is one of the most preached ones, and I will also preach it. DO NOT REPEAT YOURSELF. Really, don’t. It ALWAYS comes to bite you in the ass if you have repeated code. Only repeat yourself if it’s too hard to not do so or if you’re absolutely sure that you won’t repeat yourself a third time, but I promise you that third time will come if it’s not for you for the next guy maintaining that code.

The obvious benefit of not repeating yourself is that you get to maintain code only in one place, the added benefit will be that your code will almost start being written by itself like a perfect equation as it grows. DRY code will be reusable, maintainable and the other principles I’ll talk about are related to the DRY principle in one way or another.

2. Keep the scope at the minimum, be as private as possible.

Keep your variables as close to your local scope as possible. This will save you many headaches, will protect you from bugs in logic because you did something to a variable in place where it shouldn’t have been in the first place, and it will keep things simpler.

This also tells you that your classes should expose as little as possible. Keep your variables local, if they can’t be local, try to keep them as private members, if they have to be used by extending classes keep them private, only use public when you really know it’s ok to make something public and that nobody is going to break the behavior of your object if they play with things at any point in time.

Keeping scope at a minimum can also prevent issues on longer lived objects like singletons that might be accessed by different objects. If you abuse the use of object properties you could have one object changing the internal state of the object while another tries to do something and you’ll get unexpected behavior, this tends to happen a lot in multithreaded environments where programmers are not careful and forget objects might be accessed by different threads/clients at the same time, tight scopes will protect you.

3. Be functional
Sometimes you’ll be tempted to be lazy and not pass parameters on a method and think that you’re so clever by changing an internal property of an object so that another function in the object will then get it. Big mistake buddy. This can be equivalent to that advice from functional programming languages where you’re told that using global variables are a bad idea.
Yes, we have object properties for several reasons, but if the logic of a method depends on the state of a variable, you might as well be explicit and pass it in the method.

This is in a way related to keeping scope at the minimum, and to some extend related to the advice some give of keeping your objects as immutable as possible.

4. Only abstract classes are worth extending.
If you have control over the class you are about to extend (if it’s in your codebase) before you extend that class take a look and make sure that it’s an abstract class. Abstract classes are MEANT to be extended, so you can be safe that you’re doing the right thing here.

If you’re extending a non abstract class, you should probably be composing it instead. If you don’t have access to the code of the class you are extending, things could not behave as expected when you extend, not all programmers are as thoughtful as you are.

5. Keep Object lifetime as short as possible.
This goes back to keeping scopes tight and trying to avoid singletons as much as possible (as convenient as they might be), in the case of java the JRE has a better time collecting garbage and will save you from memory leak headaches. Put those factories to work.

Feel free to disent and share your favorite principles, If you’ve coded long enough I’m sure you tend to think about these things too and I’d love to learn from your experiences.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Javascript: Capitalize Text Like In This Title

Thursday, January 5th, 2012

On this one, we’ll show of the dynamic nature of javascript and we’re going to make all strings have a new method called “capitalize()”.

So you can do stuff like this:

console.log("this text should look nicer now".capitalize());
>> This Text Should Look Nicer Now

Here’s the magic code you’ll need to add somewhere on your javascript files and all strings will have a new capitalize() method.

String.prototype.capitalize = function(){
	   return this.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } );
};
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

javascript: Format a number to display thousands US style (#,###,###,###)

Thursday, January 5th, 2012
/**
 * Format a number to display thousands like in the US -> 1000000 => 1,000,000
 * @param number
 * @returns
 */
function formatThousands(number) {
	return Math.max(0, number).toFixed(0).replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
}
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

javascript: Get N random elements from a List

Thursday, January 5th, 2012
/**
 * Walks linearly through the list to find an element.
 * returns true if it's found.
 */
function elementIn(collection, element) {
	for (var i=0; i < collection.length; i++) {
		if (collection[i]==element) {
			return true;
		}
	}
	return false;
}

/**
 * Returns a new list of n random elements taken out of myList.
 */
function getNElementsAtRandom(myList, n) {
	var toGo = n;
	var result = [];
	var indexesUsed = [];

	while (toGo > 0) {
		index=-1;

		do {
			index = Math.floor(Math.random()*(myList.length));
			console.log(index);
		} while (elementIn(indexesUsed, index));

		indexesUsed.push(index);
		result.push(myList[index]);
		toGo--;
	}

	return result;
}
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

BFS vs DFS Graph Search Algorithms in Python

Tuesday, November 15th, 2011

Here are implementations of iterative BFS and DFS search algorithms in Python.

These are just to illustrate the slight difference in implementation of these algorithms.

Basically, if you want to go deep, with DFS, you can use a queue on which you’ll be adding the next elements to explore as you traverse the graph.
If you want to scan around the current node, you can use a stack so that you keep looking at the closest elements before you move forward.

These functions use and return a list of visited nodes. If you want to make this a little more efficient, you can mark nodes as visited using a dictionary, or if the nodes themselves can have a property added to them, you can use that instead so you don’t have to do a linear search every time you want to know if a node was visited or not. I left it like that again, to just focus on the algorithm itself and not in the performance optimizations.

Source

GRAPH = {1 : [2,3], 2:[4,5], 3:[6], 4:None, 5:[7,8], 6:None, 7:None, 8:None}

def BFS(start, target, GRAPH):
  'Use a QUEUE to search.'
  print "Source:",source,"Target:",target
  queue = [start]
  visited = []

  while len(queue) > 0:
    x = queue.pop(0)

    if x == target:
      visited.append(x)
      return visited
    elif x not in visited:
      visited = visited+[x]
      if GRAPH[x] is not None:
         'add nodes at the END of the queue'
         queue = queue + GRAPH[x]

  return visited

def DFS(start, target, GRAPH):
  'Use a STACK to search.'
  print "Source:",source,"Target:",target
  stack = [start]
  visited = []

  while len(stack) > 0:
    x = stack.pop(0)

    if x == target:
      visited.append(x)
      return visited
    elif x not in visited:
      visited = visited+[x]
      if GRAPH[x] is not None:
         'add nodes at the top of the stack'
         stack = GRAPH[x] + stack

  return visited

print "BFS Path",BFS(1,7,GRAPH)
print "DFS Path",DFS(1,7,GRAPH)
print "="*80
print "BFS Path",BFS(1,3,GRAPH)
print "DFS Path",DFS(1,3,GRAPH)

Output

$ python graph.py
BFS Path Source: 1 Target: 7
[1, 2, 3, 4, 5, 6, 7]
DFS Path Source: 1 Target: 7
[1, 2, 4, 5, 7]
================================================================================
BFS Path Source: 1 Target: 3
[1, 2, 3]
DFS Path Source: 1 Target: 3
[1, 2, 4, 5, 7, 8, 3]
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

NSIS: StrContains function – Find the index of a sub string.

Wednesday, August 31st, 2011

Recently I was out of internet and I needed to implement a function that would search if a String was part of another String for an NSIS installer.
Here’s my rendition of such a function. Once I came back online I found out about StrStr, but here’s another option that gives you as output the starting index on the bigger string (aka Haystack) if the smaller string (aka Needle) is found. Otherwise, it returns -1.

; ------------------------------------------------
; StrContains
; Returns starting index of where a string is contained inside another string (case sensitive)
; Usage: !insertmacro StrContains ${HayStack} ${Needle} ${Output}
;
; Parameters:
;   HayStack - The string that could contain the substring you're looking for
;   Needle   - The string you are looking for
;   Output   - -1 if the needle is not in the haystack, or the offset where it exists.

Var HaystackOffset ;current offset on haystack to copy NeedleLength characters into HayStackBuffer
Var HaystackLength ;size of the big string
Var MaxHaystackOffset ;maximum offset we can reach
Var NeedleLength ;length of string we're looking for
Var HaystackBuffer ;substring we get on each iteration

!macro StrContains Haystack Needle Output
  ;we'll be repeating this operation until we've reached
  ;HayStackLength - NeedleLength

  ;Get the lengths of the strings.
  StrLen $HaystackLength ${Haystack}
  StrLen $NeedleLength ${Needle}
  StrCpy $HaystackOffset 0

  ;Determine what's the maximum offset we can use to search for the substring
  IntOp $MaxHaystackOffset $HaystackLength - $NeedleLength
  IntOp $MaxHaystackOffset $MaxHaystackOffset - 1

  ;Make sure needle is not bigger than haystack
  IntCmp $NeedleLength $HaystackLength LoopStart LoopStart DidNotFindIt

  DidNotFindIt:
  StrCpy $HaystackOffset -1
  Goto Finish

  ;Start of substring comparison loop
  LoopStart:
  ;copy the substring to a buffer
  StrCpy $HaystackBuffer ${Haystack} $NeedleLength $HaystackOffset

  ;It's pretty cool if you uncomment this.
  ;MessageBox MB_ICONINFORMATION|MB_OK "[Loop] Buffer: [$HaystackBuffer] Offset: [$HaystackOffset]"

  ;If we're done, we return the current haystackoffset
  StrCmpS $HaystackBuffer ${Needle} Finish FigureOutNextStep

  ;Did we reach the end, or can we move a bit more
  FigureOutNextStep:

  ;Move offset 1 character to the right and see if we can keep going
  IntOp $HaystackOffset $HaystackOffset + 1
  IntCmp $HaystackOffset $MaxHaystackOffset LoopStart LoopStart DidNotFindIt 

  Finish:
  StrCpy ${Output} $HaystackOffset
!macroend
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

twitterAutoLinks: jQuery extension to replace twitter @names for links to their respective pages.

Tuesday, August 2nd, 2011

Save the following on a .js file, preferably named jquery.twitterAutoLinks.js

/** Auto replace all Twitter nicknames for links */
$.fn.twitterAutoLinks = function() {
  return this.each(function() {
    var html = $(this).html();
    $(this).html(html.replace(/\B@([\w-]+)/gm, '<a href="http://twitter.com/$1" target="_blank">@$1</a>'));
  });
};

Usage

After importing the jquery.twitterAutoLinks.js file (make sure it’s after you’ve imported jquery itself), you’ll use the extension as follows.

<script type="text/javascript" language="Javascript">

    $(document).ready(function() {
      //say you're running a wordpress blog and you want to do this for your posts
      $("div.entry").twitterAutoLinks();
    });

</script>
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Have the latest HAProxy as a Ubuntu Service

Wednesday, April 6th, 2011

So you need to use HAProxy and you love the convenience of binary packages on repos, but when you install the version HAProxy available in the repos you realize that it is way too old for what you need.

Then you download the latest HAProxy, compile it, configure it, but it’s a bit of a pain in the ass to not have the convenience of having haproxy be automatically restarted as a service like those available on /etc/init.d

This post teaches you how to have haproxy as a Ubuntu/Debian service.

First copy or symlink this script to your /etc/init.d/ folder (you’ll need root permissions to do this)

#!/usr/bin/env bash
# haproxyd
# Script to start|stop|restart haproxy from /etc/init.d/
# By Gubatron.

HAPROXY_PATH=/path/to/haproxy-X.Y.Z
HAPROXY_DAEMON=$HAPROXY_PATH/haproxy

test -x $HAPROXY_DAEMON || exit 0

set -e

function getHaproxyPID() {
  PID=`ps aux | grep 'haproxy -f' | grep -v "grep" | awk '{ print $2 }'`
}

case $1 in
  start)
        echo "Starting haproxy..."
        $HAPROXY_DAEMON -f $HAPROXY_PATH/haproxy.cfg
        ;;
  restart)
        echo "Hot restart of haproxy"
        getHaproxyPID
        COMMAND="$HAPROXY_DAEMON -f $HAPROXY_PATH/haproxy.cfg -sf $PID"
        echo $COMMAND
        `$COMMAND`
        ;;
  stop)
        echo "Stopping haproxy"
        getHaproxyPID
        COMMAND="kill -9 $PID"
        echo $COMMAND
        `$COMMAND`
        ;;
  *)
        echo "Usage: haproxyd {start|restart|stop}" >&2
        exit 1
        ;;
esac

exit 0

This script, on it’s own can be used as

./haproxyd start
./haproxyd restart
./haproxyd stop

But you want this script registered on all the right runlevels of the operating system.

With Ubuntu/Debian there’s a utility called update-rc.d to register /etc/init.d/ scripts very easily.

Once the script above is available on /etc/init.d do the following

cd /etc/init.d
sudo update-rc.d haproxyd defaults

The script should now be registered on all the right runlevels and you should be able to invoke it as a service like

sudo service haproxyd <command>
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

NSIS CharAt Macro

Monday, March 21st, 2011

Lord knows why the NSIS folks didn’t add a CharAt function to their API.
In case you need it to parse a string, here’s a Macro that makes StrCpy work like a CharAt function

;Get a character inside a string given an index.
;Usage: CharAt String Index Output
!macro CharAt InputString Index Output
 StrCpy ${Output} ${InputString} 1 ${Index}
!macroend

To use the CharAt “function” (macro in this case), do as follows:

!insertmacro CharAt "Hello World!" 1 $0
;$0 will have the letter 'e' inside.
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)

Get a randomly weighted key in a Map/Dictionary/Associative Array

Tuesday, March 15th, 2011

Here’s a very useful function to retrieve a randomly weighted key from an associative array in PHP.

Sometimes you need to fetch random elements from a collection but you need some elements to have a little more chance than others to be fetched (business rules or whatever…)

srand(time()); //dont call this inside the function or you'll get same result always
function getRandomWeightedKey($weighted_elements, $default_key) {
  $weighted_ranges = array();
  $weight_offset = 0;

  //if you know weights are not gonna change you could
  //move this part of the code to another place and cache it
  //for better performance. Specially if you have a lot of weighted elements
  foreach ($weighted_elements as $key => $weight) {
    $weighted_ranges[]=array('key'=>$key,
                             'range'=>array(intval($weight_offset),intval($weight_offset+$weight)));
    $weight_offset += $weight;
  }

  //get a random number between the 0 and the maximum
  $r = rand(0,$weight_offset);

  foreach ($weighted_ranges as $range) {
    if ($r >= $range['range'][0] && $r < $range['range'][1]) {
      return $range['key'];
    }
  }

  //this shouldn't happen but Mr. Justin Case.
  return $default_key;
}

//how to use it. (weights don't necessarily need to add to 100,
//but it helps me to visualize things basing weights on 100
$weights = array("a" => 25, "b" => 25, "c" => 50);

$randomKey = getRandomWeightedKey($weights, "c");

It should be trivial porting this code to the language of your choice. Enjoy.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)


  • Categories

  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
  • March 2010
  • February 2010
  • January 2010
  • December 2009
  • October 2009
  • September 2009
  • July 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • April 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007
  • February 2007
  • January 2007
  • December 2006
  • November 2006
  • October 2006
  • September 2006
  • August 2006
  • July 2006
  • June 2006
  • May 2006
  • April 2006
  • March 2006
  • February 2006
  • January 2006
  • December 2005
  • November 2005
  • October 2005
  • September 2005
  • August 2005
  • July 2005
  • June 2005
  • May 2005
  • April 2005
  • March 2005
  • February 2005
  • January 2005
  • December 2004
  • November 2004
  • October 2004