April 27, 2014 7:20 PM

Knowing and Doing in the Wild, Antifragile Edition

a passage from Taleb's 'Antifragile' that mentions knowing and doing

Reader Aaron Friel was reading Taleb's Antifragile and came across a passage that brought to mind this blog. Because of "modernity's connectivity, and the newfound invisibility of causal chains", Taleb says, ...

The intellectual today is vastly more powerful and dangerous than before. The "knowledge world" causes separation of knowing and doing (within the same person) and leads to the fragility of society.

He wondered if this passage was the source of the title of my blog. Knowing and Doing predates Taleb's book by nearly decade, so it wasn't the source. But the idea expressed in this passage was certainly central to how the blog got its name. I hoped to examine the relationship between knowing and doing, and in particular the danger of separating them in the classroom or in the software studio. So, I'm happy to have someone make a connection to this passage.

Even so, I still lust after naming my blog The Euphio Question. RIP, Mr. Vonnegut.


Posted by Eugene Wallingford | Permalink | Categories: General

April 23, 2014 3:29 PM

Simple Tests

As Corey Haines tells us, it really can be this simple:

def assert_equal(expected, actual, message)
  if expected != actual
    raise "Expected #{expected}, got #{actual}\n#{message}"
  end
end

Don't let the overhead of learning or using a test harness prevent you from starting. Write a test, then write some code. Or, if you prefer: Write some code, then write a test.


Posted by Eugene Wallingford | Permalink | Categories: Software Development

April 22, 2014 2:56 PM

Not Writing At All Leads To Nothing

In a recent interview, novelist and journalist Anna Quindlen was asked if she ever has writer's block. Her answer:

Some days I fear writing dreadfully, but I do it anyway. I've discovered that sometimes writing badly can eventually lead to something better. Not writing at all leads to nothing.

I deal with CS students all the time who are paralyzed by starting on a programming assignment, for fear of doing it wrong. All that gets them is never done. My job in those cases is less likely to involve teaching them something new they need to do the assignment and than to involve helping them get past the fear. A teacher sometimes has to be a psychologist.

I'd like to think that, at my advanced age and experience, I am beyond such fears myself. But occasionally they are there. Sometimes, I just have to force myself to write that first simple test, watch it fail, and ask myself, "What now?" As code happens, it may be good, or it may be bad, but it's not an empty file. Refactoring helps me make it better as I go along. I can always delete it all and start over, but by then I know more than I did at the outset, and I usually am ready to plow ahead.


Posted by Eugene Wallingford | Permalink | Categories: General

April 21, 2014 2:45 PM

The Special Case Object Pattern in "Confident Ruby"

I haven't had a chance to pick up a copy of Avdi Grimm's new book, Confident Ruby, yet. I did buzz by the book's Pragmatic Programmers page, where I was able to pick up a sample chapter or two for elliptical reading.

The chapter "Represent special cases as objects" was my first look. This chapter and the "Represent do-nothing cases as null objects" chapter that follows deal with situations in which our program is missing a kind of object. The result is code that has too many responsibilities because there is no object charged with handling them.

The chapter on do-nothing cases is @avdi's re-telling of the Null Object pattern. Bobby Woolf workshopped his seminal write-up of this pattern at PLoP 1996 (the first patterns conference I attended) and later published an improved version in the fourth Pattern Languages of Program Design book. I had the great pleasure to correspond with Bobby as he wrote his original paper and to share a few ideas about the pattern.

@avdi's special cases chapter is a great addition to the literature. It shows several different ways in which our code can call out for a special case object in place of a null reference. It then shows how creating a new kind of object can make our code better in each case, giving concrete examples written in Ruby, in the context of processing input to a web app.

I was discussing the pattern and the chapter with a student, who asked a question about this example:

    if current_user
      render_logout_button
    else
      render_login_button
    end

This is the only example in which the if check is not eliminated after introducing the special case object, an instance of the new class, GuestUser. Instead, @avdi adds an authenticated? to the User and GuestUser classes, has them return true and false respectively, and then changes the original expression to:

    if current_user.authenticated?
      render_logout_button
    else
      render_login_button
    end

As the chapter tells us, using the authenticated? predicate makes the conditional statement express the programmer's intent more clearly. But it also says that "we can't get rid of the conditional". My student asked, "Why not?"

Of course we can. The question is whether we want to. (I have a hard time using words like "cannot", "never", and "always", because I can usually imagine an exception to the absolute...)

In this case, there is a lingering smell in the code that uses the special case object: authenticated? is a surrogate for type check. Indeed, it behaves just like a query to find the object's class so that we can tailor our behavior to receiver's type. That's just the sort of thing we don't have to do in an OO program.

The standard remedy for this code smell is to push the behavior into the classes and send the object, whatever its type, a message. Rather ask a user if it is authenticated so that we can render the correct button, we might ask it to render the correct button itself:

    current_user.render_button

...
class User def render_button render_logout_button end end
class GuestUser def render_button render_login_button end end

Unfortunately, it's not quite this simple. The render_logXXX_button methods don't live in the user classes, so the render_button methods need to send those messages to some other object. If the user object already knows to whom to send it, great. If not, then the send of the render_button message will need to send itself as an argument along with the message, so that the receiver can send the appropriate message back.

Either of these approaches requires us to let some knowledge from the original context leak into our User and GuestUser classes, and that creates a new form of coupling. Ideally, there will be a way to mitigate this coupling in the form of some other shared association. Ruby web developers know the answer to this better than I.

In any case, this may be what @avdi means when he says that we can't get rid of the if check. Doing so may create more downside than upside.

This turned into a great opportunity to discuss design with my student. Design is about trade-offs. Things never seem quite as simple in the trenches as they do when we learn the rules and heuristics of design. There is no perfect solution. Our goal as programmers should be to develop the ability to make informed decisions in these situations, taking into account the context in which we are working.

Patterns document design solutions and so must be used with care. One of the thing I love about the pattern form is that it encourages the writer to make as explicit as possible the context in which the solution applies and the forces that make its use more or less applicable. This helps the reader to face the possible trade-offs with his or her eyes wide open.

So, one minor improvement @avdi might make in this chapter is to elaborate on the reason underlying the assertion that we can't eliminate this particular if check. Otherwise, students of OOP are likely to ask the same question my student asked.

Of course, the answer may be obvious to Ruby web developers. In the end, working with patterns is like all other design: the more experience we have, the better.

This is a relatively minor issue, though. From what I've seen, "Confident Ruby" will be a valuable addition to most Ruby programmers' bookshelves.


Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development

April 17, 2014 3:30 PM

The "Subclass as Client" Pattern

A few weeks ago, Reginald Braithwaite wrote a short piece discouraging us from creating class hierarchies. His article uses Javascript examples, but I think he intends his advice to apply everywhere:

So if someone asks you to explain how to write a class hierarchy? Go ahead and tell them: "Don't do that!"

If you have done much object-oriented programming in a class-based language, you will recognize his concern with class hierarchies: A change to the implementation of a class high up in the hierarchy could break every class beneath it. This is often called the "fragile base class" problem. Fragile code can't be changed without a lot of pain, fixing all the code broken by the change.

I'm going to violate the premise of Braithwaite's advice and suggest a way that you can make your base classes less fragile and thus make small class hierarchies more attractive. If you would like to follow his advice, feel free to tell me "Don't do that!" and stop reading now.

The technique I suggest follows directly from a practice that OO programmers use to create good objects, one that Braithwaite advocates in his article: encapsulating data tightly within an object.

JavaScript does not enforce private state, but it's easy to write well-encapsulated programs: simply avoid having one object directly manipulate another object's properties. Forty years after Smalltalk was invented, this is a well-understood principle.

The article then shows a standard example of a bank account object written in this style, in which client code uses the object without depending on its implementation. So far, so good.

What about classes?

It turns out, the relationship between classes in a hierarchy is not encapsulated. This is because classes do not relate to each other through a well-defined interface of methods while "hiding" their internal state from each other.

Braithwaite then shows an example of a subclass method that illustrates the problem:

    ChequingAccount.prototype.process = function (cheque) {
      this._currentBalance = this._currentBalance - cheque.amount();
      return this;
    }

The ChequingAccount directly accesses its _currentBalance member, which it inherits from the Account prototype. If we now change the internal implementation of Account so that it does not provide a _currentBalance member, we will break ChequingAccount.

The problem, we are told, is that objects are encapsulated, but classes are not.

... this dependency is not limited in scope to a carefully curated interface of methods and behaviour. We have no encapsulation.

However, as the article pointed out earlier, JavaScript does not enforce private state for objects! Even so, it's easy to write well-encapsulated programs -- by not letting one object directly manipulate another object's properties. This is a design pattern that makes it possible to write OO programs even when the language does not enforce encapsulation.

The problem isn't that objects are encapsulated and classes are not. It's that we tend treat superclasses differently than we treat other classes.

When we write code for two independent objects, we think of their classes as black boxes, sealed off from external inspection. The data and methods defined in the one class belong to it and its objects. Objects of one class must interact with objects of another via a carefully curated interface of methods and behavior.

But when we write code for a subclass, we tend to think of the data and methods defined in the superclass as somehow "belonging to" instances of the subclass. We take the notion of inheritance too literally.

My suggestion is that you treat your classes like you treat objects: Don't let one class look into another class and access its state directly. Adopt this practice even when the other class is a superclass, and the state is an inherited member.

Many OO programs have this pattern. I usually call it the "Subclass as Client" pattern. Instances of a subclass act as clients of their superclass, treating it -- as much as possible -- as an independent object providing a set of well-defined behaviors.

When code follows this pattern, it takes Braithwaite's advice for designing objects up a level and follows it more faithfully. Even instance variables inherited from the superclass are encapsulated, accessible only through the behaviors of the superclass.

I don't program in Javascript, but I've written a lot of Java over the years, and I think the lessons are compatible. Here's my story.

~~~~~

When I teach OOP, one of the first things my students learn about creating objects is this:

All instance variables are private.

Like Javascript, Java doesn't require this. We can tell the compiler to enforce it, though, through use of the private modifier. Now, only methods defined in the same class can access the variable.

For the most part, students are fine with this idea -- until we learn about subclasses. If one class extends another, it cannot access the inherited data members. The natural thing to do is what they see in too many Java examples in their texts and on the web: change private variables in the superclass to protected. Now, all is right with the world again.

Except that they have stepped directly into the path of the fragile base class problem. Almost any change to the superclass risks breaking all of its subclasses. Even in a sophomore OO course, we quickly encounter the problem of fragile base classes in our programs. But other choice do we have?

Make each class a server to its subclasses. Keep the instance variables private, and (in Braithwaite's words) carefully curate an interface of methods for subclasses to use. The class may be willing to expose more of its identity to its subclasses than to arbitrary objects, so define protected methods that are accessible only to its subclasses.

This is an intentional extension of the class's interface for explicit interaction with subclasses. (Yes, I know that protected members in Java are accessible to every class in the package. Grrr.)

This is the same discipline we follow when we write well-behaved objects in any language: encapsulate data and define an interface for interaction. When applied to the class-subclass relationship, it helps us to avoid the dangers of fragile base classes.

Forty years after Smalltalk was invented, this principle should be better understood by more programmers. In Smalltalk, variables are encapsulated within their classes, which forces subclasses to access them through methods defined in the superclass. This language feature encourages the writer of the class to think explicitly about how instances of a subclass will interact with the class. (Unfortunately, those methods are public to the world, so programmers have to enforce their scope by convention.)

Of course, a lazy programmer can throw away this advantage. When I first learned OO in Smalltalk, I quickly figured out that I could simply define accessors with the same names as the instance variables. Hurray! My elation did not last long, though. Like my Java students, I quickly found myself with a maze of class-subclass entanglements that made programming unbearable. I had re-invented the Fragile Base Class problem.

Fortunately, I had the Smalltalk class library to study, as well as programs written by better programmers than I. Those programs taught me the Subclass as Client pattern, I learned that it was possible to use subclasses well, when classes were designed carefully. This is just one of the many ways that Smalltalk taught me OOP.

~~~~~

Yes, you should prefer composition to inheritance, and, yes, you should strive to keep your class hierarchies as small and shallow as possible. But if you apply basic principles of object design to your superclasses, you don't need to live in absolute fear of fragile base classes. You can "do that" if you are willing to carefully curate an interface of methods that define the behavior of a class as a superclass.

This advice works well only for the class hierarchies you build for yourself. If you need to work with a class from an external package you don't control, then you can't be control the quality of those class's interfaces. Think carefully before you subclass an external class and depend on its implementation.

One technique I find helpful in this regard is to build a wrapper class around the external class, carefully define an interface for subclasses, and then extend the wrapper class. This at least isolates the risk of changes in the library class to a single class in my program.

Of course, if you are programming in Javascript, you might want to look to the Self community for more suitable OO advice than to Smalltalk!


Posted by Eugene Wallingford | Permalink | Categories: Patterns, Software Development

April 11, 2014 10:29 AM

Famous Last Words

With respect for Rands, I've adapted a paragraph from one of his engineering management pieces to my experience:

You're a department chair now. Congratulations. Either you sucked at teaching and research and wanted to try a different avenue of influence, or you're fed up with every other chair you've worked for and now you're going to REALLY GOING TO SHOW US how it's done.

It's much easier to be fed up than to show people how it's really done. Trust me.

This week has been a challenge. I have faced several things that need to be done well. Most of them are, in ways, peripheral to the core mission of the department and university, but they are important to students, faculty, and external stakeholders. If they are handled poorly, the experience people have will undercut everything else we do well.

So these are the things that a department head must do well, in the trenches and with not much fanfare. They consume a lot of emotional energy an introvert like me, and they don't offer a lot of immediate, tangible rewards. But they are worth my attention.

After a number of years in this position, I have found that it's a lot easier for me to imagine knocking the ball out of the park than to make contact. I keep working at it.

In this regard, I have begun to learn to combine empathy with the proper application of a scientific mindset to how people behave. This idea is echoed in a passage from Timothy Burke:

Anything that real people do in the world is by definition interesting. By "interesting", I mean worthy of the kind of investigation that puts curiosity and honesty well before judgment.

Curiosity about individual people and honest communication are generally my best tools in the trenches. Forgetting to turn off the judgment centers in my brain never works well.


Posted by Eugene Wallingford | Permalink | Categories: Managing and Leading

April 09, 2014 3:26 PM

Programming Everywhere, Vox Edition

In a report on the launch of Vox Media, we learn that line between software developers and journalists at Vox is blurred, as writers and reporters work together "to build the tools they require".

"It is thrilling as a journalist being able to envision a tool and having it become a real thing," Mr. Topolsky said. "And it is rare."

It will be less rare in the future. Programming will become a natural part of more and more people's toolboxes.


Posted by Eugene Wallingford | Permalink | Categories: Computing, General

April 04, 2014 12:43 PM

Creative Recombination of Existing Ideas

In a post on his move to California, Jon Udell notes that he may be out of step with the dominant view of the tech industry there:

And I think differently about innovation than Silicon Valley does. I don't think we lack new ideas. I think we lack creative recombination of proven tech, and the execution and follow-through required to surface its latent value.

As he found with the Elm City project, sometimes a good idea doesn't get traction quickly, even with sustained effort. Calendar aggregation seems like such a win even for a university the size of mine, yet a lot of folks don't get it. It's hard to know whether the slowness results from the idea, the technology, or the general resistance of communities to change how they operate.

In any case, Udell is right: there is a lot of latent value in the "creative recombination" of existing ideas. Ours is a remix culture, too. That's why it's so important to study widely in and out of computing, to build the base of tools needed to have a great idea and execute on it.


Posted by Eugene Wallingford | Permalink | Categories: Computing