Tuesday, May 10, 2011

Google I/O

On the train back to Philadelphia from the Google I/O Extended
conference in NYC. Props to Google NYC for hosting us for the streaming session and showing us around.

The Google NYC offices in the Port Authority building in Chelsea are
neat. I'm a sucker for the converted warehouse look, so it appealed to
me straight away. They still had alot of hustle and bustle getting the
space put together and remodeled, and expanded into new parts of the
building. One architectural feature I found funny was that their main
common spaces/auditoriums/rec rooms were located in the loading docks
for their (still working) truck elevators.



There was a big focus on Android graphics and HTML5 capabilities at the
sessions they showed us, which was really encouraging. I'm curious
about the capabilities of their RenderScript. It seems like the
documentation and examples are rather sparse, but it is some kind of
OpenGL wrapper + CUDA approximation that allows for high-performance
rendering or compute (simulation, encoding/decoding) that can run on
either the GPU or CPU as is appropriate.

Rather than Dalvik, then use an LLVM intermediate representation that is
targeted to the CPU's or GPU's available at run-time, which reminds me
of the Apple OpenGL emulation system using LLVM. This, plus the fact
that anyone that can is using LLVM as their back-end, really makes me
think I should pick it up. One nice RenderScript feature is that their
compiler automatically generates Java .class files for you that make
binding from your Android app quite painless.

I'm a little sad that Google chose to rebuild this stack rather than
support OpenCL and build a similar abstraction on top of it; I'd be
curious to hear the rationale. I don't think RenderScript will find for
larger software systems (serious physics engines, math libraries)
without more of a cross-platform nature; it's a pity they couldn't have
leveraged such that already exists for OpenCL, which promises alot of
the same benefit of heterogenous platform support.

Another good talk I saw was the Android ProTips. He actually ran over
alot of the same points on watching battery, connectivity, and docking
state that were covered in CIS542, Embedded Systems. He also showed
some really nice tricks using PassiveLocationProvider to take advantage
of Location updates that other apps requested to keep yourself
up-to-date.

Really, the number of system events that can be captured
and handled using Intents is really impressive, and one of my favorite
features of Android as a platform. I thought I was really clever when
we used them to capture document opening for SEASPrint, but apparently
that's just best practice.

Another neat Android library I learned about today in passing is
FileObserver, which is a low-level and powerful utility that I wasn't
really expecting. It's just a wrapper for the Linux inotify library,
but it let's you do neat things like the shader preview tool I talked
about last fall.

It's probably not that great a tool for general IPC since Android
applications view of the filesystem is really restricted, and there are
already higher-level tools like Intents to pass media and messages
between applications, but I can see it being used in content development
to push out asset changes to the phone during development for
interactive preview. Noone likes reinstalling an app to see changes.



At the reception after Google I/O, I bumped into one of Google's engineers for
Google Body, which uses alot of WebGL to render some really high resolution
datasets. I'd been curious about streaming 3d assets into the browser, so he
was really great to talk to.

He had some great points about the tradeoffs in streaming, storing, and
decompressing data when your host code runs in Javascript and your
rendering runs in accelerated OpenGL. This is especially difficult
since in Javascript you can't access custom native libraries for
compression/decompression or asset preparation. One option is using
browser builtin's like Gzip or Deflate content-type encoding to handle
your compression for you.

Test Driven Development: by Example

On the way back home Sunday, I also read most of Test Driven
Development
by Kent Beck, who is an author I have heard referenced alot
but never read.

Good quote: "Every programming practice encodes a value system,
explicitly of implicitly"

--Kent Beck

I used a fair bit of TDD on the mail server project, as well as
conformance testing, system testing, stress testing, and a dash of
regression testing. The SMTP protocol logic especially was developed
incrementally and test first.

The book was alright, the first step-by-step example was
a little wandering but eventually enlightening. I actually liked the
end of the book more, where he gives a large review of test patterns, as
well as design patterns and refactorings as applied to TDD.

One of the sections I enjoyed most was "How do you know if you have good
tests?". For me, one of the greatest benefits of TDD isn't that you
are left with tons of test artifacts that you can use for verification,
refactoring, or maintenance. It's that you can continually,
incrementally, and easily fire up and exercise your code base in little
chunks.

In this section, Kent Beck points out that bad tests can be an
indication of bad design in the production code. If you can't get your
code in a test hardness because of external dependencies of filesystems,
servers, or databases, it isn't the fault of unit-testing as a
discipline; your production code has too many dependencies. Similarly
if you feel you are instantiating 2/3rds of your code base to run one
object. Because unit tests exercise chunks of the codebase separately,
they verify that you really do have a modular design, and provide alot
of motivation to extract interfaces and encapsulted complicated and
concrete implementations.

This spat of reading on software engineering has really gotten me to
thinking about how to backport these techniques to languages less
focused on encapsulation and dynamic polymorphism (read: C). I might do
a series on modern and modular design techniques in plain-old C. It'd
be stuff most professional developers probably know about, but that
wouldn't show up in K&R.

Seven Languages: Io

I took the train from home in Upstate New York to New York City today to
go to the Google I/O streaming sessions tomorrow, and it's a beautiful
day along the Hudson. I took the opportunity to work through the Io
chapter of Seven Languages.

Io is a prototype language, meaning that to create new objects, one just
clones an existing object, called a prototype, rather than instantiating
a class. I found this to be a simple model that makes reflection very
simple and natural. There is no reason to have, for example, Python
meta-classes, when you don't even have classes! To "inherit"
functionality, you clone your base object, add some functionality
dynamically, and then clone from your new prototype.

Another feature of Io I found distinguishing was message passing as a
means to call methods on objects. I had used messages before, but only
in Objective-C. I don't know if I was just doing it wrong, but message
passing in Objective-C basically amounted to normal functions calls with
a weird syntax, less compile-time checks, and named parameters.

Message passing in Io was much more obviously potent. Message passing
in Io is clearly sending a chunk of data to an object which may (or may
not) result in the execution of a method at some point. For example, to
pass parameters in function calls in most languages, the callee
evaluates expressions in the parameters, pushes the arguments and return
address onto the stack, and jumps into the callee.

This means that if you tried to write a function in C like

return_type if(cond, then_code, else_code)

That evaluated condition then returned one of the 2 branches, you would
have big problems with side-effects because both sides of the branch
would be executed before entering the if function.

In Io, the code in both of those clauses is simply passed in as part of
the message arguments. The callee can check the condition then execute
the side that they wish to. This could be done in C by wrapping that
code up in some kinda of data like a function-pointer + context, but in
Io it's automatic. Similarly, message passing can trivially handle
things like co-routines and asynchronous, deferred, or delayed
invocation, because they very nicely bundle up that act of calling a
method.

One annoyance is that there isn't much syntactical support for the
collections classes. They still offer all the expected features as well
as nice transformation operations like map and select, but it still
requires a little more imperative "add this to a list, then this, then
this" rather than really nice declarative collections processing.

Sunday, May 8, 2011

Seven Languages: Ruby

Since I finished my final projects for the semester, I've gone
on quite a reading binge. One book I started working my way
through is Seven Languages in Seven Weeks. This is a neat
introduction to a slew of languages that focuses on their
quirky, unique aspects.

I think the list is Ruby, Io, Scala, Haskell, Prolog, Erlang, and
Clojure, so their is a good mix of functional, declarative,
object-oriented, and actor-based concurrency languages, as well as a
good spread from static to dynamic. In fact, their may be a scatter
plot in the making there.

The book starts with Ruby. I believe Ruby is the easiest of the
languages to learn, but I was still interested because I want to pick
up CoffeeScript, which borrows much from it. I was really impressed
with the interactions between blocks, the collections classes, and the
IO system.

Python supports some inkling of this, but I found the Ruby
support much more fundamental to the language. I've always disliked
writing for loops for the purposes of collections processing, and Ruby
really does away with this. They also support ranges and slices in a
much more unified way that Python

One thing I just saw a nibble of, but which interested me was the
language-integrated support for Regex matching, ala Perl. While some
of the implicit globals for string processing ($. is the line number of
the last input read?) were a little gross, I thought this was really
nice. I'd be interested to see how elegant a more general context-free
grammar parsing framework could be. I couldn't find a way to run Ruby
one-liners from the command-line, which is a pity because I've been
looking for a reason not to learn awk, and this seemed promising.

I was a little thrown off by the highly dynamic nature of Ruby. Ruby
supports things like open classes and overriding method_missing. These
are really powerful, as Seven Languages mentions, for things like
database adapters and XML frameworks, but making them efficient at
runtime seems daunting. It seems like they would really defeat alot of
JIT compilers, that try to do things like find consistent implicit
class structures. Most code I write has fairly stern performance
requirements, so I'm not sure it's the right language for me.

Next, on to Io!

Saturday, May 7, 2011

Clean Code Review

Today I read most of Clean Code by Bob Martin. The forward describes the book as being divided into 3 sections: guidelines, case studies, and "code smells" (negative heuristics). It also clearly cautions again reading sections 1 and 3 and skipping 2. Clearly, I went ahead and did just that. If that invalidates any of my review, so be it. I felt it was valuable nonetheless.

One of this main tenets, which I find myself agreeing with, is that functions and classes should be small. And then they should be smaller. While it sounds silly, I think applied consistently and combined with great identifiers, it can make code really simple to read.

For example, he recommends against nested scopes inside functions. This means that while, if, and fors should consist only of a single line, which is either a statement, or a function call. Great names for these functions leave little surprise about what they do, and the contents are basically what you would expect.

This interplays nicely with the principle he espouses of only stepping down 1 level of abstraction in a function call. Each function can deal with a single responsibility by stepping down 1 level of abstraction and perform a few simple non-nested steps. Any more complication, or deeper layers of stepping, requiring extracting another function.

One benefit of all this function extracting, which I hadn't thought of before, is that it is fruitful ground for extracting classes. Suppose you have a longish function that performs a sequence of steps on some local data. You extract those steps out into methods and make the local data instance variables. The original function now calls the extracted methods.

However, you now have a little wad of instance data which is accessed only by a few methods. This is perfect ground for extracting a new class and moving those methods to it. I've used this a few times in my own code without really thinking about it, and been really pleased with the results.

Overall it's really nice book, and a very fast read (especially if you skip the case studies). While the author is clearly a heavy Java developer, I still felt like I got good insight out of it, and I am definitely not a big Java guy.

Monday, May 2, 2011

The Passionate Programmer

Recently I've been reading The Passionate Programmer by Chad Fowler. It's been a fast and entertaining read so far, and borrows a lot from Peopleware. It has a really interesting emphasis on personal and career development, rather than how to complete a project or task successfully.

One point he drives is to really focus on your business value as a programmer. This means really being aware of how much you cost and how much value you produce. As a technical professional who loves what they do, it is really easy to become preoccupied with technical details and problems. However, this doesn't necessarily contribute to the bottom like or to the customer's/manager's perception of that contribution.

Along with this is a call against technical elitism and specialization. "I'm only X and Y expert and it's not my job to handle Z" doesn't help you do your job, which is to solve those problems if they need to be solved. I feel like this extends not only to different technical areas but also to non-technical areas like responding to customers or understanding your business's finance.