Tuesday, April 16, 2013

How to Be Useful

 

How to Be Useful is an interesting little book that recaps the highlights of success literature in the 20th century. I read it in parallel with Rework, which takes a very 21st century approach to business and work, and struck an interesting contract.  Some of Paul Graham's essays such as The Power of the Marginal also came into my mind as counter-arguments.  The initial snag of this book for me was the quirky cover and fetching title. How to Be Useful: A Beginner's Guide to Not Hating Work. Well, I consider myself a beginner, I certainly hope to be useful, and I definitely don't want to hate work, so this seemed like the book for me!

I had a wonderful and rich childhood and education (both of which prepared me well for software engineering) but I had little previous exposure to the office and the corporate institution, so this book was a helpful aggregate of others' hard-won (and occasionally gimmicky) thoughts on the subject. I also found relevant the experiences the author included from her own time in publishing, which seems to be far more ruthless and careerist than software, but similarly structured.

The structure of the book is interesting. The chapters follow a chronological progression in the time of the literature being examined. They also roughly follow a progression in the duration of employment at one position, from making striking first impressions to firing yourself in preparation for moving onwards and upwards.

The main resolution I took from the reading is that if you take how special and unique and interesting you are and shove it for a bit, and get busy to solving other people's problems and making their lives easier, professional success hopefully follows.
  • On Being a PoseurThis chapter makes a solid argument for it being morally sound and commendable to pursue a successful career, separate from base material desires, and to earnestly strive with all your capabilities, not just "hard work", for the things you want to achieve. It also criticizes the ironic detachment and disdain young and educated people sometimes have for professional life. Why try to act like you don't care about the things you care about? There isn't enough time for irony.
  • Dodging the Great Failure ArmyAn interesting chapter that focuses on Andrew Carnegie and the dawn of white-collar work. The bit that spoke to me the most was that while we are each multi-faceted and endlessly fascinating people, of great individual worth and virtue, you perhaps shouldn't be your uninhibited natural self in your professional position. To quote: "Forget yourself, he essentially said, and maybe try being somebody else a few hours a day. Maybe somebody better than you."
  • Party Tips for the Nouveau Riche
    The best ready advice from this chapter was that acting questions both makes you a better conversationalist and less overbearing to your co-workers, it's a good way to find your bearings in an organization.
  • On Near Universal Self-Absorption
    "Why talk about what we ant?  That is childish. Absurd.  Of course, you are interested in what you want.  You are eternally interested in it.  But no one else is."
  • The Master Mind
    This chapter discusses building a valuable circle of friends.  "Once you've found people with whom you can openly, sincerely discuss what you wish for, you spend less time dwelling on the pedestrian events of the day, or the smell of your cubicle neighbor's tuna sandwiches, and more time talking about things you actually want to bring into existence."
  • Checking Yourself at the Door
    On the advantages of dressing in upper-middle class styles: "While everyone else wrung their hands about how bad, how very sad, it was that all America was conforming, these thinkers started toying with the notion that blending in actually has its advantages.  Indeed, it has a kind of subversive power."
  • When It's Not Just About You
    Anecdote: "The downside to meritocracy is that those born on third base think they hit a triple, and everyone else is subject to self-loathing."
  • Interlude (Why Most Everything from the 1970's Doesn't Help)
    Shortly: everything written then presumed people were dumb.  And presuming that your audience is dumb never made for a quality product.
  • Self-Deprecation
    This chapter advertises self-deprecation as a useful tactic, especially for surviving "So where did you go to school" type conversations.  I like to think that this isn't necessary in 2013, but it may be.
  • On DefenseOne of my goals in life is to remain fearless enough to admit my errors freely and move to correct them directly.  Intellectual honesty above much else.  This chapter advertises a similar ethic.
  • The Uses of No
    As a software engineer, I love the concept of "firing yourself".  I think that the highest professional goal a programmer should shoot for in a given position is writing such excellent software, tests, tooling, and documentation that you can simply walk away from your duties and have them keep themselves running.  How much more courageous and less petty than making yourself necessary.

Sunday, January 15, 2012

YTinstant

I made a clone of ytistant to learn more about client side scripting.

You can play with it here or get the source here

Not sure how permanent these heroku links are...

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.