www.BrettDaniel.com

Null Object for java.lang.reflect.Method

The Null Object Pattern is an object-oriented programming pattern that allows one to avoid null (i.e. undefined) values by instead creating objects that do nothing.

For example, say a library defines an interface ICommand with an execute method.

interface ICommand {
    void execute();
}

If one uses null to represent undefined commands, then one would always need to check that a value is non-null prior to use.

class CommandExecutor {
    ICommand command = null;

    void runCommand() {
        if (command != null) {
            command.execute();
        }
    }
}

Such checks are verbose and easy to forget. Instead, it is better to define a NullCommand class that implements ICommand and whose execute method does nothing.

class NullCommand implements ICommand {
    void execute() {
        // do nothing
    }
}

Then, one can initialize undefined ICommand values to a new NullCommand, removing the need for null checks.

class CommandExecutor {
    ICommand command = new NullCommand();

    void runCommand() {
        command.execute();
    }
}

One limitation of the pattern is that it requires access to the application's class hierarchy. What does one do when one needs to create a null object for a class that cannot be subclassed or constructed directly?

I recently encountered this problem while working on a research project. I was writing some reflective code that passed around java.lang.reflect.Method objects. The Method class is declared final and has a non-public constructor, meaning that I could not create a corresponding NullMethod class for undefined values. Nevertheless, for the reasons described above, I wanted to avoid using null. The solution for this particular problem involved creating reflective instances of a static dummy method that adheres to the signature expected by the application.

To see how this works, let us return to the example given at the beginning of the post. Say the application uses Method objects instead of ICommand objects. In this new example, the original CommandExecutor class would look something like the following:

class CommandExecutor {
    Method method = null;

    void runCommand(Object instance) throws Exception {
        if (method != null) {
            method.invoke(instance);
        }
    }
}

This example assumes that the Method objects take no arguments other than the instance in which to execute the method and that the return type does not matter. I will discuss how to handle more complex method signatures later, but for now, we know our null objects should adhere to this simple signature and do nothing when invoked.

The following is the updated code using null object pattern. UNDEFINED_METHOD_IMPL defines the body of the null method, and UNDEFINED_METHOD returns its reflective instance. This reflective instance is the null object that one can use to initialize undefined values such as the method field.

class CommandExecutor {

    public static Method UNDEFINED_METHOD() {
        try {
            return CommandExecutor.class.getDeclaredMethod(
                "UNDEFINED_METHOD_IMPL");
        } catch // removed for space
    }
    public static void UNDEFINED_METHOD_IMPL() {
        // do nothing
    }

    Method method = UNDEFINED_METHOD();

    void runCommand(Object instance) throws Exception {
    	method.invoke(instance);
    }
}

Because UNDEFINED_METHOD_IMPL is static, the invoke call ignores the instance variable. This means the method can be invoked on any type even though it is declared in CommandExecutor.

What if the expected method signature is more complex? For example, what if the application requires methods to accept one String argument and return an object of type ICommand?

class CommandExecutor {
    ...
    void runCommand(Object instance, String arg) throws Exception {
    	ICommand command = (ICommand) method.invoke(instance, arg);
    	command.execute();
    }
}

In this case, we simply change UNDEFINED_METHOD_IMPL such that it adheres to the new signature and returns a new NullCommand. Essentially, the null object (method) returns a null object (command).

class CommandExecutor {

    public static Method UNDEFINED_METHOD() {
        try {
            return CommandExecutor.class.getDeclaredMethod(
                "UNDEFINED_METHOD_IMPL", 
                String.class);
        } catch // removed for space
    }
    public static ICommand UNDEFINED_METHOD_IMPL(String arg) {
        return new NullCommand();
    }

    Method method = UNDEFINED_METHOD();

    void runCommand(Object instance, String arg) throws Exception {
    	ICommand command = (ICommand) method.invoke(instance, arg);
    	command.execute();
    }
}

Note that a reflective instance of a dummy method is not a true null value since its methods still execute normally and return "real" values. For example, UNDEFINED_METHOD().getDeclaringClass() still returns the java.lang.Class for CommandExecutor. Therefore, this approach works well when invoking methods, but not when an application requires deep reflective exploration of Method objects.

This Java file contains the working example code.

A good concise explanation of the Y Combinator

A good concise explanation of the Y Combinator

Yesterday I went without crutc…

Yesterday I went without crutches for the entire day.

An email address can be at mos…

An email address can have at most 320 characters

Grown Up Digital

In his book Grown Up Digital: How the Net Generation is Changing Your World*, Don Tapscott examines how technology has affected the "Baby Boom Generation" (born 1946 through 1964) and the "Net Generation" (born 1977 through 1997). My father, a Boomer, and I, a Net Genner, have always been heavily involved in technology, and this book echoes many of of our conversations about how we approach technology differently. In particular, the themes from the book reminded me of three stories: one about how ubiquitous technology becomes unremarkable, another about text versus voice communication, and a third about the shift from broadcast (i.e. television and newspapers) to participative media (i.e. the web).

It was around 1998 or 1999. My father, who has always been my family's technology evangelist and sysadmin, bought a WebTV for my grandmother, and I got to test it out at home for several days. I found out years later that most people hated the system due to its clumsy interface and poor website rendering, but at the time I greatly enjoyed surfing from the couch. When my parents asked what I thought about the gift, I remember saying, "she might find it useful, but, really, having the internet isn't such a big deal." I quickly rethought this statement. Even in those pre-Google, pre-YouTube, pre-blog days, my family already checked the weather forecast, read product reviews, and downloaded software updates online. I did not intuitively grasp the novelty and power of having instant access to a world's worth of information. In Grown Up Digital, Tapscott relates several similar stories in which technology has become "like the air", an unremarkable feature of the Net Generation's environment.

One such "unremarkable feature" is the mobile phone. Last year, half of the world's population carried a mobile phone. When people leave their home, all carry at least three things: their keys, money, and mobile phone. Because of this amazing growth, I always find it jarring to watch older movies in which the protagonist must find a pay phone to warn another character of impending doom. Similarly, the information systems in classic science fiction stories (say, pre-Neuromancer) seem faint and attenuated compared to today's dense and ubiquitous media. Interestingly, this seems to contradict the Net Generation's preference for text (i.e. short message service, instant messages, and email) over voice communication. Why do we communicate through low-bandwidth channels despite having high-bandwidth methods available to us?

Grown Up Digital mentions this tendency only briefly, but it is a characteristic I have noticed often and in many contexts. I think it appears because the web is inherently built around text, URLs, pages, and XML. To illustrate, I recently got a call from a friend I had not spoken to in several months. She and I talked for several minutes. During the conversation, I mentioned two YouTube videos I had seen, and she described her rock climbing club whose website she promised to send me. Then, the topic switched to a mutual friend who, since I had my laptop next to me (natch), I noticed was on AIM at the time. I suggested we hang up and resume talking online in a chat room I started. There, I sent her links to the videos, she sent me the club website, the mutual friend entered the conversation, and all three of us continued chatting for several times longer than we had been on the phone.

Just as person-to-person communication has been transformed by mobile phones, instant messages, and email, broadcast media is being supplanted by participative media such as websites, blogs, wikis, and aggregators. I find this the most exciting aspect of new media, and Grown Up Digital spends several chapters describing its effects on learning, institutions, business, family, and politics. One important effect has been that the Net Generation watches less TV than the Boomers (17.4 hours per week versus 22.4). The difference instead goes toward online activities. Clay Shirky calculates, for example, that Wikipedia alone required something like 100 million years of human thought, cognitive energy that would have otherwise languished watching sitcoms.

The same shift appears in my family's living room. I rarely just sit and watch. Instead, I usually have my laptop open, and my sister and I often IM silently across the room while my parents sit unaware. When watching a movie, I check reviews and trivia on IMDB; when watching a nonfiction program, I read about related topics on Wikipedia. However, I work better when I can devote my attention to a task, so when I need to focus, I, unlike many Net Generation multitaskers, tend to work in silence with my email and IM clients closed.

Grown Up Digital is filled with many other stories that resonate with my personal experiences. Further, it is all backed up with deep quantitative research and detailed citations. Its breathlessly positive assessment of the effects on society are reassuring, though I am surprised that the only major downsides voiced in the work involve online bullying and risks to privacy. What about the risks to content providers not from piracy but from an economy built on advertising? How can we ensure that the "Non-Net Generation" and those without access are not left behind? Nevertheless, I cannot wait to see what all generations can accomplish online.

* Forgive the Amazon affiliate link. It is something new I'm trying. If you click the link and buy something—it doesn't have to be Grown Up Digital—I get a small percent of the purchase price. And you get my gratitude.

Website Upgrade: Now with Microblog!

I finally upgraded my two-and-a-half-year-old WordPress installation. It was surprisingly painless: just backed up, overwrote the old installation, and clicked a button. Now the site is protected from known vulnerabilities and can take advantage of newer plugins. In particular, the Twitter Tools plugin automatically imports my Twitter posts into this website's new Microblog category. Any other changes should be invisible, so let me know if something looks broken.

Update

I fixed two more problems that were bothering me:

Update #2

I also cleaned up gallery links to remove the query variable. Now, something like http://www.brettdaniel.com/gallery/?path=pictures/2008/ redirects to http://www.brettdaniel.com/gallery/2008/.

Testing microblogging from my …

Testing microblogging from my (macro)blog.

Like Turning 16 Again

While the rest of me has contended with chemo treatments, my right leg has continued to recover from surgery. I have been using a single crutch since before Christmas and can walk short distances without even that. My knee has also become flexible enough that I can finally operate the pedals in my car. On Monday I drove for the first time in three months. I used my newfound freedom for a completely mundane task: I took some letters to the post office.

Chemo, Chemo, PET Scan: Repeat as Necessary

In a miracle of scheduling, my Christmas was free of medical appointments. I finished my fourth round of chemotherapy a week before the holiday and got a third PET scan a week after. Today I spoke with my oncologist about what the scan results mean for my treatments over the next few months.

The scans show nine tumors ranging in size from 2 to 15 mm. They have remained mostly unchanged since the previous scan. I am disappointed that they did not decrease in size or number, but it is still a positive result meaning that the chemo has prevented growth. I have also avoided the most drastic side effects of the chemo (despite having long passed the recommended lifetime total dosage), so my oncologist feels that I can continue the same regimen for two more rounds.

I expect that the next two rounds will progress similarly to the previous four. The most recent is representative: I get admitted on a Monday and get five, four-hour doses of Ifosfamide (with Mesna to protect my kidneys and bladder) over five days. I feel mostly normal for the first two days, but the drugs begin to take their toll on the third. After that, food loses all its appeal, I shake uncontrollably, and my dreams become very, very strange. I go home on the fifth or sixth day, then spend two weeks recovering before the cycle starts again.

The dreams are the most unexpected side effect. I experienced nothing similar in my previous diagnoses, and my oncologist is surprised that I have such a vivid neurological reaction to drugs that normally have little affect on the brain. Here are three noteworthy examples:

  • I attempted to design and solve a crossword puzzle wrapped on the surface of a cube. Such a puzzle requires special placement of the black boxes to prevent words from cycling all the way around four faces. Also, there would be no "across" and "down" since each face would have its own independent orientation. I overcame these limitations in the dream, but I can't remember how. One day I will attempt to recreate such a puzzle.
  • I was flying through a cave with glowing green and blue walls. A small stream of water flowed among the rocks at the bottom of the cave. Its banks were lined with all sorts of trinkets: candles, broken board games, firecrackers, and half-eaten birthday cakes. Pieces would break off these items and melt into drops of oil that would float and merge on top of the water. Inside each drop was a person telling me his or her life story.
  • An artificial intelligence that directed the crosshairs in an aim-and-fire computer game somehow escaped and created a body from twisted strands of shiny red fiber. Infinitely deformable and with perfect aim, she could build nearly anything out of things she found lying around the towering neon and glass cityscape in which she found herself. These talents eventually destroyed her. She unraveled when she attempted to use her own fibers to make copies of herself. The "children" she created, however, lived on.

I could fill several books with the strange stories from less well-remembered dreams. They all seem to have deep, interwoven subplots and casts of thousands. Fortunately, the dreams and most of the acute side effects of chemo decrease two or three days after returning home from the hospital.