Monday, October 15, 2012

Prime Factors Kata in Scala

I like running through the Prime Factors Kata when learning a new language to help uncover the language's power. I've done this before in Clojure and now it's Scala's turn. Scala is interesting in that it attempts to merge the best aspects of both object-oriented and functional languages. 

The steps I took follow. Each is separated by a horizontal line with changes from the previous iteration in red. The factors of four caused modifications to the algorithm that allowed the next two tests to pass without further changes. It was test-driven using ScalaTest.


test("Factor of one is empty list") {
  assert(List[Int]() === primeFactors(1))
}

def primeFactors(n: Int) = {

  List[Int]()
}

test("Factor of two is two") {
  assert(List(2) === primeFactors(2))
}

def primeFactors(n: Int) = {
  if (n > 1) {
    List(2)
  } else {
    List[Int]()
  }
}

test("Factor of three is three") {
  assert(List(3) === primeFactors(3))
}

def primeFactors(n: Int) = {
  if (n > 1) {
    List(n)
  } else {
    List[Int]()
  }
}

test("Factors of four are two and two") {
  assert(List(2, 2) === primeFactors(4))
}

def primeFactors(n: Int) = {
  def primeFactors(n: Int, candidate: Int): List[Int] =
    if (n <= 1) List[Int]()
    else if (n % candidate == 0) candidate :: primeFactors(n / candidate, candidate)
    else List(n)

  primeFactors(n, 2)

}

test("Factors of six are two and three") {
  assert(List(2, 3) === primeFactors(6))
}

test("Factors of eight are two, two, and two") {
  assert(List(2, 2, 2) === primeFactors(8))
}

test("Factors of nine are three and three") {
  assert(List(3, 3) === primeFactors(9))
}

def primeFactors(n: Int) = {
  def primeFactors(n: Int, candidate: Int): List[Int] =
    if (n <= 1) List[Int]()
    else if (n % candidate == 0) candidate :: primeFactors(n / candidate, candidate)
    else primeFactors(n, candidate + 1)

  primeFactors(n, 2)

}

The end result is the last code snippet and all of the tests. 

However, as I mentioned above, Scala is a unique language that allows both imperative and functional styles. Though the functional style is preferred, in the spirit of completeness, I thought I'd show what the end result would look like imperatively.


def primeFactors(n: Int) = {
  var primes = List[Int]()
  var candidate = 2;
  var x = n

  while (x > 1) {

    while (x % candidate == 0) {
      primes = candidate :: primes
      x /= candidate
    }
    candidate += 1
  }

  primes

}

As you can see, the imperative version isn't as clean and forced me to create a local variable just so I could mutate it. The nice thing about Scala, though, is that it let's you slowly dip your toe into a different programming paradyme instead of jumping in head first. 

Thursday, September 20, 2012

Test Before > Test After

By now, I hope we can all agree that unit tests are a good idea. I recently gave a presentation on why I think testing before writing production code (TDD) is better than testing after.


Code Quality

Only writing code to fix failing tests yields:
  • Better tests
  • Testable code
    • Decoupled
    • Fast
  • Less rework
  • High test coverage
    • Less debugger
  • Simple
    • Less gold-plating


Continuous Integration

Minimizing time in Red and committing on Green yields:
  • Compiling, tested code every ~10 minutes
  • Ability to revert to last Green quickly


Improved Interfaces

Intelligent test names and coding from client's perspective yields
  • Self-documenting code with clean, natural interfaces

GetLog().Debug().Message("My message.");
Log(Priority.Debug, "My message.");


void Debug_LogsDebugMessage() {
  Log.Debug("My message.");
  // Some assert
}


Testing after is work, TDD is fun!

Friday, August 3, 2012

Save Hours and Make Life Easier with these Free Apps

Inspired by the Lifehacker Pack for Windows, I created my own list of tools I use on a daily basis. I've listed  Linux alternatives to the Windows-only tools, but I haven't used a Mac since grade school and I didn't want to blindly recommend anything.
  1. Google Chrome - Web browser available on most desktop and smart phone platforms. Allows bookmark, extension, and open tab syncing between devices and a wide range of extensions. You can also enable Google Instant in the address bar from the Settings menu. It's called Chromium in Linux. But if you're using Linux you already knew that.
  2. Launchy - Instead of going the Start menu to launch applications, you just press Alt-Space and begin typing the name of the app. Supports plugins as well. Linux alternative: GNOME Do.
  3. Picasa - Photo editor from Google that syncs nicely with Google+. Plug-ins for social networks that people actually visit exist too.
  4. Ditto - Clipboard manager that saves the last 500 items you've copied (don't worry, they're searchable). Now you can copy multiple sections of text and paste them individually with a single hot-key press. Linux alternative: Parcellite.
  5. Sublime Text - Beautiful, cross-platform text editor that is 1000x more powerful than Notepad. Windows-only alternative is Notepad++.
  6. Phrase Express - Text expander that allows you to type a short phrase and have it expand into whatever you want. Great for any repetitive typing task you have in code, e-mail, Word documents, etc.
  7. Paint.NET - Less powerful, but free alternative to Photoshop.
  8. 7-Zip - Open source Winzip alternative that supports many more file formats.
  9. Snipping Tool - Great utility that comes with Windows 7 that allows you to capture a screenshot of any portion of the screen you want.
  10. Droplr - Drag-and-drop your newly created snip or any other file to this web app and share the link with anyone. Simple.
  11. Sumatra PDF - Lightweight Adobe Reader replacement that's much faster.
  12. Revo Uninstaller - Utility that uninstalls programs and deletes remnants that the Windows uninstaller leaves behind.
  13. CCleaner - Utility that deletes temporary files and fixes registry issues to speed up your computer (and it's not one of those scam programs as seen on TV).
  14. Teracopy - Utility that allows pausing and error recovery of file transfers.
  15. WinMerge - Quickly compare two versions of a text file to see which lines differ and merge changes between them.
  16. Rescue Time - Track which window or website has focus so you can see where you're spending (or wasting) your time.
  17. Clover - Tabbed Windows Explorer interface modeled after Google Chrome. It even has a lot of the same shortcuts. Windows only.
If you have other great Windows, Linux, or Mac tools, leave a comment below.

Tuesday, July 10, 2012

Extreme Makeover: Fresh Hot 100 Edition

In my previous post I explained a new web app I created called Fresh Hot 100 that shows only the songs that are new to Billboard's Hot 100 list since the last time you visited. Here's how it looked last week:
Before
After going through some Codecademy tutorials and searching around the web, here's what it looks like now:
After
Probably still ugly to people that actually know what they're doing, but I'm happy with where it's at. I started by adding a full-screen background image with help from CSS-Tricks. Then I got a favicon from findicons.com and made a number of changes behind the scenes...so that it actually works.

With every new project I work on I wonder more and more where developers would be without Google and StackOverflow.

Monday, July 2, 2012

Fresh Hot 100

I check Billboard's Hot 100 chart each Thursday to keep my playlist up-to-date. It was time consuming, however. Here were the steps I'd go through:
  1. Go through entire list searching for new songs since previous list
  2. Copy new song's title and artist
  3. Paste into GrooveShark, listen to it, and add it to my playlist if I liked it
Obviously, step 1 takes the longest. What I really want is just a list of the songs that weren't on the list last week. That's where Fresh Hot 100 comes in. It's a simple web app I created that just displays the songs that are new to the Hot 100 list since the last time you visited. Clicking on a song opens a Grooveshark  search in a new tab. It's not the prettiest web site, but give it a try and let me know what you think.

Thursday, June 28, 2012

Android Development: Casino Strategy v2.0

The first feature I wanted to add after I published v1.0 was the ability to change between Blackjack strategy cards by swiping rather than selecting from a menu. I found an example of a View Pager that was exactly what I needed. Modifying it to fit my app was trivial. Note: since I'm developing using API 7, I needed the SDK Tools in order to get the View Pager working.

My next idea was to add a "Share" button so if the app helped users win, they could tell their friends. It turned out to be much easier than I thought and this Stack Overflow answer explains how to add a Share Intent.

That took care of Blackjack, but since the app is called Casino Strategy, I figured it needed more casino games. I started by adding a new Activity with a list of games for the user to select. I wanted this new Activity to launch on start-up and and the answer lies in intent filters.

In AndoidManifest.xml:
<activity
   android:name=".MainActivity"
   android:label="@string/app_name" >
   <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>
<activity
   android:name=".BlackjackActivity"
   android:label="@string/app_name" >
</activity>

To switch to the other activities, the new src/MainActivity looks like this:
public static final int BLACKJACK = 0;
private final Map<Integer,Class<?>> mIntentMap = new HashMap<Integer,Class<?>>();

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   mIntentMap.put(BLACKJACK, BlackjackActivity.class);
   setListAdapter(new ArrayAdapter<String>(this,
         android.R.layout.simple_list_item_1, getResources()
               .getStringArray(R.array.games_array)));
   ListView lv = getListView();
   lv.setTextFilterEnabled(true);
   lv.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView<?> parent, View view,
         int position, long id) {
         Class<?> cls = mIntentMap.get(position);
         if (null != cls) {
            Intent intent = new Intent(CasinoStrategyActivity.this, cls);
            if (null != intent) {
               startActivity(intent);
            }
         }
      }
   });
}

To populate the list adapter, I'm using a string array. With only one game it's overkill, but it will soon make sense.

In res/values/strings.xml:
<string-array name="games_array">
   <item>Blackjack</item>
</string-array>

My second favorite casino game is Craps so it was next. Rather than creating a fancy graphic, the optimal strategy can easily be expressed in text. Adding a new game is a few easy steps:
  1. Add a new Activity class to the src folder
  2. Register that new Activity in AndroidManifest.xml
  3. Add a new <Integer, Class> pair to the map in MainActivity.java
  4. Add a new string to games_array
Here are some of the interesting parts:

In src/CrapsActivity:
public class CrapsActivity extends GameActivity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.text_view);
      setText(R.id.text_view, R.string.craps);
      setText(R.id.text_view_title, R.string.craps_title);
   }
}

In res/layout/text_view.xml:
<TextView
   android:id="@+id/text_view_title"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:textSize="22sp" />
<TextView
   android:id="@+id/text_view"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:textSize="18sp" />

Notice that CrapsActivity extends GameActivity instead of Activity. Since my Share Intent is used by all games, I moved it to a base class that Blackjack and Craps extend.

I added Roulette in an almost identical way as Craps. Casino Strategy is available on Google Play. Give it a try and let me know what you think.

Wednesday, June 27, 2012

Farewell to John Deere

Copied below is the e-mail to my John Deere coworkers. It's a bittersweet goodbye, but I'm excited for my future with Dwolla.

All,

After 6 years, I’m leaving John Deere for a position at a Des Moines startup. Saying goodbye to a job I love with people I admire at an organization that has been kicking so much ass lately is decidedly not easy. Unfortunately, I don’t have a juicy story about epic betrayal, a bare-knuckle brawl with a coworker, or the burden of Squish test failures sending me over the edge. I was given every opportunity to advance and grow and will forever be indebted to this organization and its people. But experiencing a startup has been a dream of mine and though it may be risky, sometimes you have to touch the fire to see if it’s hot. And, more importantly, another Hackathon is coming up and I want to retire undefeated. Rocky Marciano, not Balboa.

I started at Deere as an intern in the summer of 2006, back when ISG...I mean IVS…err AMS had about 40 people. At that time, I had one semester of programming experience in C and didn’t know what an object, a debugger, or polymorphism was. To me, “testing” meant compile, run, poke around until it broke, fix, repeat. So I very literally learned everything I know about “the real world” and developing software from bothering the hell out of all of you.

I started to list the people that had a profound impact on my personal and professional development throughout the 2600, 1800, CommandCenter, 2630, and GSix projects, but at around 40 names I started humming that music they play during long-winded acceptance speeches at the Oscars. Nonetheless, to all of you, I give my sincerest of thanks. I also can’t tell you how appreciative I've been of the respect and support given as news of my departure spread – it’s something I won’t soon forget.

And that’s the thing – yes, John Deere is an excellent company, the Agile culture is fast-paced and exciting, and my projects were world changing. But at the end of the day, it’s the people, the relationships I’ll miss the most. So please do stay in touch with tweets or posts; I won’t be that far away!
@therockstorm, +Rocky Warren

It’s been my pleasure working with all of you. Farewell, thank you, and long live GSix!

Rocky Warren