<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><description></description><title>ruddzw.com</title><generator>Tumblr (3.0; @ruddzw)</generator><link>http://ruddzw.com/</link><item><title>Lenny’s got some competition coming…</title><description>&lt;img src="http://38.media.tumblr.com/8e8163b5625fd5dd82abe19c823bf74c/tumblr_mu2i1suB8q1qz4zzdo1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Lenny’s got some competition coming…&lt;/p&gt;</description><link>http://ruddzw.com/post/62948626503</link><guid>http://ruddzw.com/post/62948626503</guid><pubDate>Wed, 02 Oct 2013 20:44:15 -0400</pubDate></item><item><title>Time to fix the caches</title><description>&lt;img src="http://31.media.tumblr.com/82042fe0a657b328dc591b161b58a375/tumblr_mu0ffvUICj1qz4zzdo1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Time to fix the caches&lt;/p&gt;</description><link>http://ruddzw.com/post/62842115994</link><guid>http://ruddzw.com/post/62842115994</guid><pubDate>Tue, 01 Oct 2013 17:52:43 -0400</pubDate></item><item><title>Attempting to make StarLicker work on low-memory devices...</title><description>&lt;img src="http://31.media.tumblr.com/1c3990315410983fa33d8ee8862378fc/tumblr_mtr9et5rEK1qz4zzdo1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Attempting to make StarLicker work on low-memory devices #instruments&lt;/p&gt;</description><link>http://ruddzw.com/post/62368539759</link><guid>http://ruddzw.com/post/62368539759</guid><pubDate>Thu, 26 Sep 2013 19:04:05 -0400</pubDate><category>instruments</category></item><item><title>starlickergame:

The first StarLicker trailer

I’ve been...</title><description>&lt;iframe width="400" height="224" src="https://www.youtube.com/embed/7CdE30KZev8?feature=oembed" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a class="tumblr_blog" href="http://starlickergame.tumblr.com/post/51580166635/the-first-starlicker-trailer"&gt;starlickergame&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first StarLicker trailer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I’ve been working on this game for several months now, as co-founder of my company &lt;a href="http://heartonomy.com"&gt;Heartonomy&lt;/a&gt;. This is the first trailer.&lt;/p&gt;</description><link>http://ruddzw.com/post/51580898459</link><guid>http://ruddzw.com/post/51580898459</guid><pubDate>Tue, 28 May 2013 16:09:00 -0400</pubDate></item><item><title>Data Ex Machina</title><description>&lt;p&gt;We needed to start over. Our old app had reached its limits, and we were cutting down on functionality because of it. My team&amp;#8217;s old app was extremely tightly coupled with a Microsoft &lt;a href="http://en.wikipedia.org/wiki/SQL_Server_Reporting_Services"&gt;SQL Server Reporting Services&lt;/a&gt; (SSRS) server, which had been hacked up to use the web app as a data source and generate reasonably nice-looking reports, and the hackage had determined most of the architecture of the web app code. In addition, despite lots of searching, we could not find a way to get results back from the database without loading them all into memory, using our current framework. We wanted to do large data exports, so that was unacceptable.&lt;/p&gt;
&lt;p&gt;Besides, the web app was written in Java. And not good Java—the &amp;#8220;Enterprise Java Bean&amp;#8221;-filled XML-instantiated messy Java. Yuck.&lt;/p&gt;
&lt;p&gt;Building a new web app would enable us to slowly move off of the old app, using the magic of a well-configured load balancer that we already had in place anyway. Our plan was to first build the data export feature, since that would actually have some customer impact. Of course, the wonderful side-effect would be being able to ditch SSRS, which had forever plagued our developers with impossible-to-update code and confusing logic. An app free from the chains of SSRS could be written well and let us build better, more interactive reports. But first, we needed to think about those data exports.&lt;/p&gt;
&lt;p&gt;We held a naming contest, and its name from then on would be &lt;a href="http://en.wikipedia.org/wiki/Deus_ex_machina"&gt;Data Ex Machina&lt;/a&gt;, or DXM for short.&lt;!-- more --&gt;&lt;/p&gt;
&lt;h3&gt;The Search for a Good Python Framework&lt;/h3&gt;
&lt;p&gt;We were sure that we wanted to build our new app in Python, because each of us on the team had experienced firsthand the difference in productivity between Python and Java, and we knew that the amount of work that the app does is small enough that Python wouldn&amp;#8217;t become a performance problem. Since we wanted to get the technology choice right this time, we spent a little while doing some investigation as to what framework we were going to use. The frontrunners were Django, Pylons, and Tornado.&lt;/p&gt;
&lt;p&gt;I was pulling for &lt;a href="http://www.tornadoweb.org/"&gt;Tornado&lt;/a&gt;, because it seemed nice to work with, plus its default model of working was in streaming data, rather than building up an entire response and sending it to the client. Since we&amp;#8217;d have to do that exact thing with the data exports, it seemed like a natural choice. But after a little bit of time with that, it became clear that we&amp;#8217;d actually have to build our own asynchronous database driver. Our queries are extremely long-running: several seconds for simple reports, and under load, multiple minutes for complex reports. Building an asynchronous driver is surely doable, but a normal framework would be fine for us. That meant that Tornado would have to have something monstrously better than Django or Pylons for us to commit to it.&lt;/p&gt;
&lt;p&gt;Between Pylons and Django, we were having a hard time deciding which was better than the other. Each was mostly good with a few small negatives each. But when we started load testing our proof-of-concept apps to see which performed beter under load, we immediately noticed that each server had terrible performance. Somehow, our database queries were executing serially rather than in parallel. After some work, we narrowed the blame down to the database connections, rather than Python or the frameworks. We were using &lt;code&gt;&lt;a href="http://code.google.com/p/pyodbc/"&gt;pyodbc&lt;/a&gt;&lt;/code&gt; to connect to our database, a &lt;a href="http://www.vertica.com/"&gt;Vertica&lt;/a&gt; cluster, since Vertica doesn&amp;#8217;t provide a dedicated driver for any language, only ODBC and JDBC drivers. We even made a small test to show that the problem occurred with PyODBC connecting to two different databases, but not with &lt;code&gt;psycopg2&lt;/code&gt;, a native PostgreSQL library. We tried posting on the PyODBC newsgroup, but after a lack of response, we had just about given up on Python. We&amp;#8217;d have to go to Java after all.&lt;/p&gt;
&lt;h3&gt;One Last Hope&lt;/h3&gt;
&lt;p&gt;But wait! What about &lt;a href="http://www.jython.org/"&gt;Jython&lt;/a&gt;? Sure, it only has compatibility up to Python 2.5, but that&amp;#8217;s better than nothing. Both Django and Pylons were supposed to work under Jython, so we gave that a try. Luckily for us, switching our proof-of-concepts to run on Jython went fairly smoothly. They performed admirably under load, and dutifully streamed CSVs of data out to our load testing script.&lt;/p&gt;
&lt;p&gt;So, we were left with two decisions. First: Django or Pylons? Pylons was more used within the company, so that would have been the default choice. However, no one else was using Jython, so that throws out the shared knowledge argument. I liked Django a bit more, even though we wouldn&amp;#8217;t be using a lot of its core features like database model management. In the end, Django won out simply because it seemed like there was a larger community of people using Django on Jython than Pylons on Jython. And now, though it wasn&amp;#8217;t a factor then, Pylons has been end-of-lifed in favor of some new thing called &lt;a href="http://pylonsproject.org/"&gt;Pyramid&lt;/a&gt;, so other people who previously chose Pylons are having to rethink their decision.&lt;/p&gt;
&lt;p&gt;The last decision was whether it was worth it to go with Jython instead of Java. This was entirely subjective, but we knew that Jython was sufficiently mature for us to depend on it. We would have preferred Python, but without a way to use PyODBC, we were out of luck.&lt;/p&gt;
&lt;p class="sep"&gt;⋙&lt;/p&gt;
&lt;p&gt;Of course, over 6 months later, &lt;a href="http://groups.google.com/group/pyodbc/browse_thread/thread/282daaba55e2a4ed/e6641962e1ccec3d"&gt;the PyODBC maintainer finally did follow up on the problem&lt;/a&gt;, and someone else emailed me privately with a solution (add &lt;code&gt;Threading=1&lt;/code&gt; in the driver definition in &lt;code&gt;odbcinst.ini&lt;/code&gt;) that would have allowed us to use Python and PyODBC. By the time that happened, we had already built a few nice things that depended on JVM libraries. If we want to switch back, we&amp;#8217;ll probably have to port the functionality ourselves. Besides, life is pretty nice on the JVM.&lt;/p&gt;
&lt;p class="sep"&gt;⋙&lt;/p&gt;
&lt;h3&gt;Update: September 2012&lt;/h3&gt;
&lt;p&gt;Thanks to the &amp;#8220;fix&amp;#8221; I listed on the PyODBC group, we were finally able to make time to test out the theory and confirm that the lack of &lt;code&gt;Threading=1&lt;/code&gt; was the culprit. The continual lack of energy in the Jython community led us to want to move back to CPython. We were missing out on several libraries that were only available for CPython, and even more internally built libraries that had to be forked and modified to work with Jython, which doesn&amp;#8217;t support Python 2.6 or 2.7 syntax features. So, as of September 2012, we removed all the JVM libraries we depended on (not many), and switched over to deploying with CPython 2.7, using PyODBC. We&amp;#8217;re deploying virtualenvs instead of WARs and using mod_wsgi instead of modjy. And we couldn&amp;#8217;t be happier with the situation.&lt;/p&gt;</description><link>http://ruddzw.com/post/51073220264</link><guid>http://ruddzw.com/post/51073220264</guid><pubDate>Wed, 13 Jul 2011 00:00:00 -0400</pubDate></item><item><title>What Java is Missing</title><description>&lt;p&gt;Java&amp;#8217;s syntax has been sitting dormant for years. I started writing Java over six years ago, and the major addition since then, as far as I can tell, are generics and the &amp;#8220;for each&amp;#8221; loop. I&amp;#8217;m happy to have these, most of the time, but the more I program in other languages, the more things I miss when I&amp;#8217;m back in Java. Some things, like pattern matching for function arguments, I&amp;#8217;m never going to get. They just don&amp;#8217;t fit into the Java syntax, much less the way that Java&amp;#8217;s programming model works. But there are a few things that would be easy enough to integrate into Java that it&amp;#8217;s time to put them in.&lt;!-- more --&gt;&lt;/p&gt;
&lt;h3&gt;List and Map Literals&lt;/h3&gt;
&lt;p&gt;This is one of the simplest features of other languages, because lists and maps (or dictionaries, or hashes) are built in as basic types. Unfortunately for Java, these fundamental types are tucked away in the java.util package. It&amp;#8217;s not like these are ever unavailable, but it is a serious problem that to use the types, you have to import them. And then there&amp;#8217;s the problem of multiple implementations of each. A Map is just an interface. It might be a HashMap, a TreeMap, or some other custom implementation. A List is also an interface, and in fact it&amp;#8217;s a subinterface of Collection, and Iterable. Do we ignore the other Collections such as Sets and Queues?&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s assume a literal that essentially means an ordered collection and start from there.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;["Alice", "Bob", "Charlie"]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This follows the example of many other popular languages to create a list. However, with Java, we don&amp;#8217;t have the option of just having the compiler choose a type for us. We&amp;#8217;ve got to specify it directly.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;new ArrayList&amp;lt;String&amp;gt;["Alice", "Bob", "Charlie"]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Instead of creating an empty ArrayList using parentheses to invoke the constructor, we use this new square-bracket list notation. The great thing about this notation is that it doesn&amp;#8217;t have to only specify a list. We can use the exact same syntax to specify a Set:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Set&amp;lt;String&amp;gt; names = new HashSet&amp;lt;String&amp;gt;["Alice", "Bob", "Charlie"];&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s not much magic required behind the scenes. You could say that any &lt;code&gt;class&amp;lt;E&amp;gt;&lt;/code&gt; that has the &lt;code&gt;add(E)&lt;/code&gt; method could take advantage of this. Suddenly every ad-hoc list you would want to create is a one-liner rather than an (n+1)-liner.&lt;/p&gt;
&lt;p&gt;But what about maps? Maps are based on pairings rather than single items. Given what symbols are used in different places in Java, I&amp;#8217;d say that adding some parentheses would be the best choice in this case.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Map&amp;lt;String, Integer&amp;gt; grades = new HashMap&amp;lt;String, Integer&amp;gt;[("Alice", 92), ("Bob", 79), ("Charlie", 98)];&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;As long as you&amp;#8217;re a &lt;code&gt;class&amp;lt;K, V&amp;gt;&lt;/code&gt; that has the &lt;code&gt;put(K, V)&lt;/code&gt; method, you&amp;#8217;re good to use this syntax too. Java loses no expressiveness, as far as I can see, and we as the programmers finally can implement our simple data structures, without having to resort to multi-line ugly hacks. This code makes a few other things a lot more simple, as well. If you&amp;#8217;re declaring some Collection or Map as &lt;code&gt;final&lt;/code&gt;, then now your initialization code has been made significantly easier.&lt;/p&gt;
&lt;h3&gt;Tuples and Multiple Return Values&lt;/h3&gt;
&lt;p&gt;Tuples are a great feature of Python. They are at once overhyped and underused, but extremely powerful. When you&amp;#8217;re learning Python, you&amp;#8217;re likely to encounter this little gem, which allows you to swap two variables using the power of tuples:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;var1, var2 = var2, var1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Awesomeness factor? Off the charts. Actual usefulness? Mediocre at best. But the underlying functionality is important and quite handy. The way the variable swapping works, as I understand it, is that we first evaluate the right hand side. It takes the values from &lt;code&gt;var2&lt;/code&gt; and &lt;code&gt;var1&lt;/code&gt; and puts them into a tuple of length 2 (a double), indicated by the comma. Based on that tuple, it uses auto-unpacking to take the values from the tuple formed on the right hand side and assign them to the variables on the left, which is also sort of a tuple. Another way to write this with more explicit tuples would be:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;(var1, var2) = (var2, var1)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Tuples and this auto-unpacking make it easy to do all sorts of things, from extracting values of a list/tuple into separate variables, to essentially returning multiple values.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;before_comma, after_comma = "Hello, World!".split(",")&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;first_value, second_value = ["Foo", "Bar"] # Only works if the list has 2 items&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;peanut_butter, jelly = retrieve_pb_and_j()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Tuples and auto-unpacking are sorely missing from Java. Say we&amp;#8217;re building the Dee-lish Peanut Butter and Jelly Sandwich Maker 9000™ machine, and we&amp;#8217;ve decided to use Java. If we had this tuple functionality, we could just tell Java to go and get the peanut butter and jelly from the fridge like in the last Python example. Of course, we don&amp;#8217;t have that functionality.&lt;/p&gt;
&lt;p&gt;Instead, our choices with Java are relatively poor. We can tell Java to get us the peanut butter, and afterwards, get us the jelly. We can also construct a special class to hold a peanut butter jar and a jelly jar.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;class TwoGreatTastesBetterTogether {&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; private PeanutButter peanutButter;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; private Jelly jelly;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; // ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Of course, if we&amp;#8217;ve gone that far, we might as well construct a much more elaborate sandwich-makings housing. It can hold any number of sandwich ingredients. Whatever you want, however you want it. It&amp;#8217;s ready for professional kitchens!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;class SandwichIngredientsMonstrosity&amp;lt;Ingredient&amp;gt; {&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; private Collection&amp;lt;Ingredient&amp;gt; ingredients;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; // ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Yikes. I really just wanted a PB &amp;amp; J maker.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;public PeanutButter, Jelly getPbAndJ() {&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; // ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt; return peanutButter, jelly;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;// ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PeanutButter pb, Jelly j = getPbAndJ();&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ahh. Much better. It doesn&amp;#8217;t quite have the dynamic qualities of the Python implementation, but it gets the job done.&lt;/p&gt;
&lt;p&gt;Other people get this done with a generic &lt;code&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt; class. Sure, we could do that. But then we also need a &lt;code&gt;Triple&amp;lt;A, B, C&amp;gt;&lt;/code&gt; and a &lt;code&gt;Quadruple&amp;lt;A, B, C, D&amp;gt;&lt;/code&gt;. And so on. This is not a good solution. What happens when we need just one more than people have included in the standard libraries? As a rule, when choosing how many of something we support, we should strive to either support zero, one, or &lt;em&gt;n&lt;/em&gt;. Java has gotten down being able to return nothing or one thing, but returning more than one thing is the next step, not returning one thing that represents a predetermined number of other things.&lt;/p&gt;
&lt;h3&gt;First-class Functions and Lambdas&lt;/h3&gt;
&lt;p&gt;These are actually due to show up in the next version of Java. Or rather, they were until Oracle bought Sun and broke the schedule. Now they&amp;#8217;re due to ship in the version after next. But regardless, it&amp;#8217;s in the works. And thank goodness, because this is a big feature that I wouldn&amp;#8217;t try to pass off as a simple addition. Based on what we&amp;#8217;ve seen so far, this actually shows that Java is capable of more guessing than it&amp;#8217;s letting on. The syntax available so far looks something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;// Type one&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#()("No arguments").();&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#(Object argument)("My argument: " + argument.toString()).(1);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;// Type two&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#(){ return "No arguments"; }.();&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#(Object argument){ return "My argument: " + argument.toString(); }.(1);&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The first type is exactly what we&amp;#8217;re looking for in a lambda. We specify the type of the arguments, but not the return type. We just write the one-liner as an expression. The second type has much more potential. Nothing here is limiting us to one-liners. These are full-fledged functions. Java, which previously was home only to methods, now would have first class functions. The type of these things has been hidden so far, but it was shown that a thing like the following would work:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Object myFun = #(){ return "Hello, World!"; };&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If we&amp;#8217;re not lucky, the final syntax will be something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Function&amp;lt;R&amp;gt;&amp;lt;E, F&amp;gt; myFun = #(E arg1, F arg2){ return new R(); };&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If we&amp;#8217;re lucky, we won&amp;#8217;t have to specify the argument types or return types using some sort of generics:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Function myFun = #(E arg1, F arg2){ return new R(); };&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Either way, we&amp;#8217;ll now be able to pass functions around, create functions inside other functions, and generally do all sorts of other cool stuff. This would be the biggest leap in functionality for Java in a decade, far more than the minor proposals for tuples, literal collections, and literal maps above.&lt;/p&gt;
&lt;p class="sep"&gt;⋙&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s clear from the initiatives intended for Java 7, like Lambda, that Java&amp;#8217;s creators want it to prosper and gain back developer mindshare, so I just hope that they will be able to get these much-needed features in there soon. I&amp;#8217;m generally fine with Java&amp;#8217;s horribly excessive syntax, as long as it&amp;#8217;s got the features that put it on par with other JVM languages.&lt;/p&gt;
&lt;p&gt;In the meantime, it&amp;#8217;s Jython for me.&lt;/p&gt;</description><link>http://ruddzw.com/post/51071928784</link><guid>http://ruddzw.com/post/51071928784</guid><pubDate>Tue, 28 Sep 2010 10:55:00 -0400</pubDate></item><item><title>Reduce, Reuse, Recyle</title><description>&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/28bbc26622818473ef33ab6d00845a7c/tumblr_inline_mn7frm1NtQ1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a trio of suggestions that you&amp;#8217;re sure to have heard. Growing up as a kid, I heard this line all the time, from commercials, from school, from my parents.&lt;/p&gt;
&lt;p&gt;Reduce, reuse, recycle.&lt;/p&gt;
&lt;p&gt;That little triangle with the arrows for corners is burned into my mind for life. Yet, the meaning never really sunk in. To me it all boiled down to the last word: recycle. I learned to separate my normal trash from stuff like bottles, cans, jars, paper, and other things deemed recyclable. To me, that was the epitome of the whole movement.&lt;/p&gt;
&lt;p&gt;The first two Rs completely went over my head. I never gave a passing thought to how I might reduce something, or reuse it. When I filled up a paper cup with water, I gulped it down and threw it in the trash can. I can distinctly remember a few times where I would fill a cup, drink it quickly from thirst, throw it out, then go for another cup to fill up, having thrown away the first cup before I realized I was still thirsty. Even though I knew that I should have just kept the first cup, I didn&amp;#8217;t worry about it. Can&amp;#8217;t do anything about it now, after all.&lt;/p&gt;
&lt;p&gt;I never gave a thought to how I might reuse paper cups more than once, like using only one per day instead of four or five. Likewise, I never thought about reducing my use of paper cups to use, for instance, a water bottle. I could use a water bottle for months, at least. But none of that happened. As far as I was concerned, as long as I was putting my aluminum cans in a separate container, I was doing my part for the environment.&lt;/p&gt;
&lt;p&gt;And it&amp;#8217;s not just me. Plenty of other people missed the message. But recently they&amp;#8217;ve started to get it. I see people carrying water bottles around all day. The recent concern for the environment has sparked a movement that people have really gotten behind. Companies and countries now strive to be sustainable. But what does &amp;#8220;sustainability&amp;#8221; really mean? On the personal level, there&amp;#8217;s not much more I can do today to help the environment than there was 20 years ago. I think the main difference is that people are starting to get the other two Rs. Rather than just sorting their waste before they toss it in bins, now people are trying to make less waste in the first place. They&amp;#8217;re reducing and reusing. They were important all along, but people understand them now.&lt;/p&gt;
&lt;p&gt;As it turns out, the same principles make sense in the world of code. Except this time, it&amp;#8217;s not the recycling we&amp;#8217;ve all perfected.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/81732bad8f587655c7f805366f1755e2/tumblr_inline_mn7fq3A6Jj1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;In the programming world, we&amp;#8217;re masters of reuse. Laziness is a virtue. We practice and preach &amp;#8220;Don&amp;#8217;t Repeat Yourself&amp;#8221;, we actively seek out existing solutions, and we always try to build things for others to use. When 37signals extracts Ruby on Rails from one of their web apps and makes it into a full-fledged web framework, that&amp;#8217;s reuse. When a single developer writes a function for some shared functionality, that&amp;#8217;s reuse. From our companies&amp;#8217; actions to our modular code, programmers live and breathe reuse. It&amp;#8217;s something that&amp;#8217;s been drilled into us from our first years as programmers.&lt;/p&gt;
&lt;p&gt;However, just like recycling in the world of waste, that&amp;#8217;s not all you need to do. It gets you a long way, but not far enough.&lt;/p&gt;
&lt;p&gt;What about recycling? That is, what can we do to make completely new and better things out of what we have or used to have? On the best end of this, it&amp;#8217;s like when the PyPy project uses the power of Python to build a Just-in-Time compiler to be able to run a Python program faster than the standard C implementation. On the end that is achievable by programmers everywhere, it&amp;#8217;s like when you use the knowledge of the many bad design decisions you made the first time around to completely rebuild your product for version 2.0 (or 3.0, or 4.0, etc.). When you&amp;#8217;re spending days fixing simple bugs or adding simple features because of bad design decisions, or when you&amp;#8217;re spending hours spending time trying to even find out if you&amp;#8217;re going to be able to implement a simple feature, then it&amp;#8217;s time to recycle your code. Armed with the knowledge you have now, you can save yourself days, weeks, months of time by building it right this time.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s the importance of recycling. However, it has been said that it&amp;#8217;s almost always a bad idea to do a complete re-write of your codebase:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&amp;#8217;s a bit smarmy of me to criticize [Netscape] for waiting so long between releases. They didn&amp;#8217;t do it on purpose, now, did they?&lt;/p&gt;
&lt;p&gt;Well, yes. They did. They did it by making the single worst strategic mistake that any software company can make:&lt;/p&gt;
&lt;p&gt;They decided to rewrite the code from scratch.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;From Joel Spolsky&amp;#8217;s Things You Should Never Do, Part I&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You&amp;#8217;ll lose all that knowledge that&amp;#8217;s stored there in the code, supposedly. Sure, I&amp;#8217;m not disagreeing with that. Save recycling for the most desperate of times. Ask yourself if it really needs a rewrite. There are cases where it does. When the Mozilla Foundation built Firefox as a lightweight browser to supplant the heavyweight Mozilla browser, that was a good case of recycling. When Netscape recoded Netscape and ended up with a buggier Netscape, that was a bad case of recycling. In most cases, it&amp;#8217;s just time to reduce.&lt;/p&gt;
&lt;p&gt;Reducing is an exercise best practiced when you&amp;#8217;re writing the code, not fixing it. Think about whether you&amp;#8217;re making something a little too reusable. Say you&amp;#8217;re planning on supporting internationalization. It&amp;#8217;ll make your text modular, thus making your codebase simpler and easier to maintain, right? Wrong. Trick question! Turns out your code can&amp;#8217;t be exported out of the country due to proprietary encryption technology. And that&amp;#8217;s never going to change. So, unless your country suddenly becomes multilingual, you ain&amp;#8217;t gonna need it. Reduce.&lt;/p&gt;
&lt;p&gt;Sometimes you don&amp;#8217;t have the luxury of getting rid of things early on. Luckily, it&amp;#8217;s possible when you&amp;#8217;re trying to clean up your code though, too. Remember that complicated hierarchy you put into the code because you thought you&amp;#8217;d be getting clients with more complex needs? Well, it&amp;#8217;s a year into the project and you&amp;#8217;ve been dealing with headaches from that model for the entire time, and it turned out Fred figured out a way to transform any inputs into the simple format you&amp;#8217;ve been using all along. All that wasted effort for nothing. Don&amp;#8217;t worry; it was a good thought. But now it&amp;#8217;s time to simplify. Get rid of that bug-ridden complexity and patch up what you can. Then ta-da! You&amp;#8217;ve successfully reduced. Feel free to relax.&lt;/p&gt;
&lt;p&gt;If we embrace the three Rs with our code as we do with the environment, we can reap the same benefits. Reduce, reuse, recycle. It&amp;#8217;s never too late to take action.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/04d89c107e7fc40e6032c8b84b67279c/tumblr_inline_mn7fs0dBvu1qz4rgp.png"/&gt;&lt;/p&gt;</description><link>http://ruddzw.com/post/51071592431</link><guid>http://ruddzw.com/post/51071592431</guid><pubDate>Wed, 07 Apr 2010 10:48:00 -0400</pubDate></item><item><title>The Stray Space</title><description>&lt;p&gt;My task was refactoring. That is to say, I wasn&amp;#8217;t being thrown into the code to make it pretty. I wasn&amp;#8217;t just doing superficial things like fixing the names of variables and adding comments. I was making a real change! You see, a bunch of different Python modules all ran separately, and they all had a bunch of slightly different threading code that was essentially the same. So, we got the idea to factor out that functionality, and create one super-elegant abstract class that the separate modules&amp;#8217; classes can use. For kicks, we figured we&amp;#8217;d make it so we can run them all at once from a common class.&lt;/p&gt;
&lt;p&gt;Sure! Sounds good. Nothing bad I can say about this. I get to put on my smart developer hat, take this crappy code, and make it good.&lt;/p&gt;
&lt;p&gt;Then came a suggestion:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While we&amp;#8217;re in the code, maybe we should bring it up to &lt;a href="http://www.python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt; compliance!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thought it was a pretty good idea at the time. Yes! Let&amp;#8217;s do that! Then our code will be even better, right? Readable to the max!&lt;/p&gt;
&lt;p&gt;The guidelines set out in PEP 8 are actually pretty reasonable. I&amp;#8217;ve found that most Python code I&amp;#8217;ve written has naturally fallen into the guidelines, with a few notable exceptions, like a habit of writing variable names in mixedCase as opposed to lower_case_with_underscores. Most of PEP 8 is pretty standard stuff, like avoiding extra spaces around parentheses and brackets. Those sort of things.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s short too. I mean, it&amp;#8217;s more than just a few paragraphs, but it&amp;#8217;s no &lt;a href="http://www.chicagomanualofstyle.org/"&gt;Chicago Manual of Style&lt;/a&gt;. You could read it while you ate your sandwich at lunch. Brackets on rye. Mmm.&lt;/p&gt;
&lt;p&gt;So what&amp;#8217;s my problem with PEP 8?&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Nothing. No, really; no problems here. It&amp;#8217;s a good style guide. It&amp;#8217;s certainly a good standard to aspire to. When I was going through our code and working on that refactoring, all new code I wrote was done in the correct style. All the existing code in those modules was brought up to snuff. I even endeavored to make most of the lines less than 80 characters long, even though my editor defaults to something like 125. Because that&amp;#8217;s what you&amp;#8217;re supposed to do!&lt;/p&gt;
&lt;p&gt;When I finished, these Python modules were beautiful and immaculate: fully PEP 8 compliant. They&amp;#8217;ll be on display in the Museum of Modern Art this spring. I crafted the final commit message and sent it up to the repository, working perfectly and looking sharp.&lt;/p&gt;
&lt;p&gt;But those modules were the only Python code that we&amp;#8217;d decided to fix up in terms of PEP 8. Everything else was to be left alone. I was disappointed, but I understood. I tried to get on with my life. But having spent a few days in the land of beautiful code, I noticed that coworkers&amp;#8217; checkins started to seem a little… off.&lt;/p&gt;
&lt;p&gt;Someone&amp;#8217;s tuple had no spaces after the commas. Someone else&amp;#8217;s dictionary-ending curly brace was on the next line. One might say that it looked better that way, but in my heart I knew they were wrong. After all, my &lt;a href="http://github.com/jcrocholl/pep8"&gt;PEP 8 checker&lt;/a&gt; said so! Each violation of the style guide was like a shot through my chest. These poor, misguided coworkers. They just don&amp;#8217;t know any better. I have to teach them somehow. I know! I&amp;#8217;ll just go fix their code for them!&lt;/p&gt;
&lt;p&gt;And I did. A few times I went to a file to make a tiny one-line bugfix, and ended up with a diff that scrolled off the screen. The meaningful change was buried in a sea of whitespace changes. But that was okay, I told myself, because now that file was tasteful and aesthetically pleasing. It was the right thing to do, right?&lt;/p&gt;
&lt;p&gt;I suppose I realized that something was wrong after reviewing one particular changeset. One developer had checked in a one-liner: they added an explanatory comment between two lines of code. But it just so happened that the hash mark that began the comment was indented one extra space. A stray space had wiggled its way into a commit by accident.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/dc5ea770b74f0e25e87d0cf6aa7f1ffb/tumblr_inline_mn7fjeFMhf1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;No, I thought. No, no, no. I couldn&amp;#8217;t deal with that extra space. It was so totally off! It broke the visual flow of the code!&lt;/p&gt;
&lt;p&gt;But I knew I couldn&amp;#8217;t just check in a change to get rid of that space. It wasn&amp;#8217;t even on a line of real code!&lt;/p&gt;
&lt;p&gt;Hmm. Time for a little introspection. Let&amp;#8217;s maybe do an exercise with whys.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;#8217;m very unhappy with these circumstances.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I can&amp;#8217;t make the change to remove the extra space.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;People would think it&amp;#8217;s weird to be bothered by such a nitpick.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because most people don&amp;#8217;t care very much about those small bits of style.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because such small style nitpicks don&amp;#8217;t affect how the code works or even its readability.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah-ha! An epiphany! It turns out that the reason is simple: once you get past a certain point, code style just doesn&amp;#8217;t matter. The purpose of code style guidelines is to make sure that everyone can read and understand a common codebase. To be so strict with adherence to guidelines, as I had been, is ridiculous. It&amp;#8217;s even more so for a language like Python, which reads like pseudocode no matter how sloppily you write it.&lt;/p&gt;
&lt;p&gt;We developers love to get caught up in the little things like code style. But the right way to go about it is not to tape the guidelines above your monitor with rays of light made of yellow construction paper surrounding it. Your style guide is not the final word. Just read the thing and get on with writing code. Your fellow developers will thank you.&lt;/p&gt;</description><link>http://ruddzw.com/post/51071400809</link><guid>http://ruddzw.com/post/51071400809</guid><pubDate>Mon, 29 Mar 2010 10:44:00 -0400</pubDate></item></channel></rss>
