Shared posts

25 Nov 07:21

Perl 6 is biased towards mutators being really simple. That’s a good thing.

by jnthnwrthngtn

I’ve been meaning to write this post for a couple of years, but somehow never quite got around to it. Today, the topic of mutator methods came up again on the #perl6 IRC channel, and – at long last – conincided with me having the spare time to write this post. Finally!

At the heart of the matter is a seemingly simple question: why does Perl 6 not have something like the C# property syntax for writing complex setters? First of all, here are some answers that are either wrong or sub-optimal:

  • “We didn’t get around to it yet” – actually, it’s a concious choice. We’ve had plenty of time to ponder it over the years, and compared with many of the other language features we’ve put in, it would have been a soft feature.
  • “Just use a Proxy” – that is, a kind of container that gives you callbacks on FETCH and STORE. This is sometimes a reasonable answer, but not the right answer in most cases.
  • “We’re leaving it to module space to wrap Proxy more nicely” – this supposes Proxy is already a good starting point, when a bunch of the time it is not.

Back to OO basics

The reason the question doesn’t have a one-sentence answer is because it hinges on the nature of object orientation itself. Operationally, objects consist of:

  • A bunch of state (known as attributes in Perl 6, and fields in Java/C#)
  • A mechanism for sending a message (consisting of a name and arguments) to an object, and having the object act upon it

If your eyes glazed over on the second bullet point, then I’m glad you’re reading. If I wasn’t trying to make a point, I’d have simply written “a mechanism for calling a method on an object”. So what is my point? Here’s a quote from Alan Kay, who coined the term “object oriented”:

I’m sorry that I long ago coined the term “objects” for this topic because it gets many people to focus on the lesser idea. The big idea is “messaging”…”

For years, I designed OO systems primarily thinking about what objects I’d have. In class-based languages, this really meant what classes I’d have. How did I figure that out? Well, by thinking about what fields go in which objects. Last of all, I’d write the methods.

Funnily enough, this looks very much like procedural design. How do I build a C program? By modeling the state into various structs, and then writing functions work with with those structs. Seen this way, OO looks a lot like procedural. Furthermore, since OO is often taught as “the next step up” after procedural styles of programming, this way of thinking about objects is extremely widespread.

It’s little surprise, then, that a lot of OO code in the wild might as well have been procedural code in the first place. Many so-called OO codebases are full of DTOs (“Data Transfer Objects”), which are just bundles of state. These are passed to classes with names like DogManager. And a manager is? Something that meddles with stuff – in this case, probably the Dog DTO.

Messaging thinking

This is a far cry from how OO was originally conceived: autonomous objects, with their own inner state, reacting to messages received from the outside world, and sending messages to other objects. This thinking can be found today. Of note, it’s alive and well in the actor model. These days, when people ask me how to get better at OO, one of my suggestions is that they take a look at actors.

Since I grasped that the messages are the important thing in OO, however, the way I design objects has changed dramatically. The first question I ask is: what are the behaviors? This in turn tells me what messages will be sent. I then consider the invariants – that is, rules that the behaviors must adhere to. Finally, by grouping invariants by the state they care about, I can identify the objects that will be involved, and thus classes. In this approach, the methods come first, and the state comes last, usually discovered as I TDD my way through implementing the methods.

Accessors should carry a health warning

An accessor method is a means to access, or mutate, the state held within a particular attribute of an object. This is something I believe we should do far more hesitantly than is common. Objects are intended to hide state behind a set of interesting operations. The moment the underlying state model is revealed to the outside world, our ability to refactor is diminished. The world outside of our object couples to that view of it, and it becomes far too tempting to put operations that belong inside of the object on the outside. Note that a get-accessor is a unidirectional coupling, while a mutate-accessor implies a bidirectional (and so tighter) coupling.

But it’s not just refactoring that suffers. Mutable state is one of the things that makes programs difficult to understand and reason about. Functional programming suggests abstinence. OO suggests you just stick to a pint or two, so your side-effects will be at least somewhat less obnoxious. It does this by having objects present a nice message-y view to the outside world, and keeping mutation of state locked up inside of objects. Ideas such as value objects and immutable objects take things a step further. These have objects build new objects that incorporate changes, as opposed to mutating objects in place. Perl 6 encourages these in various ways (notice how clone lets you tweak data in the resulting object, for example).

Furthermore, Perl 6 supports concurrent and parallel programming. Value objects and immutable objects are a great fit for that. But what about objects that have to mutate their state? This is where state leakage will really, really, end up hurting. Using OO::Monitors or OO::Actors, turning an existing class into a monitor (method calls are synchronous but enforce mutual exclusion) or an actor (method calls are asynchronous and performed one at a time on a given object) is – in theory – easy. It’s only that easy, however, if the object does not leak its state, and if all complex operations on the object are expressed as a single method. Contrast:

unless $seat.passenger {
    $seat.passenger = $passenger;
}

With:

$seat.assign-to($passenger);

Where the method does:

method assign-to($passenger) {
    die "Seat already taken!" if $!passenger;
    $!passenger = $passenger;
}

Making the class of which $seat is an instance into a monitor won’t do a jot of good in the accessor/mutator case; there’s still a gaping data race. With the second approach, we’d be safe.

So if mutate accessors are so bad, why does Perl 6 have them at all?

To me, the best use of is rw on attribute accessors is for procedural programming. They make it easy to create mutable record types. I’d also like to be absolutely clear that there’s no shame in procedural programming. Good OO design is hard. There’s a reason Perl 6 has sub and method, rather than calling everything a method and then coining the term static method, because subroutine sounds procedural and “that was the past”. It’s OK to write procedural code. I’d choose to deal with well organized procedural code over sort-of-but-not-really-OO code any day. OO badly used tends to put the moving parts further from each other, rather than encapsulating them.

Put another way, class is there to serve more than one purpose. As in many languages, it doubles up as the thing used for doing real OO programming, and a way to define a record type.

So what to do instead of a fancy mutator?

Write methods for semantically interesting operations that just happen to set an attribute among their various other side-effects. Give the methods appropriate and informative names so the consumer of the class knows what they will do. And please do not try to hide complex operations, potentially with side-effects like I/O, behind something that looks like an assignment. This:

$analyzer.file = 'foo.csv';

Will lead most readers of the code to think they’re simply setting a property. The = is the assignment operator. In Perl 6, we make + always mean numeric addition, and pick ~ to always mean string concatenation. It’s a language design principle that operators should have predictable semantics, because in a dynamic language you don’t statically know the types of the operands. This kind of predictability is valuable. In a sense, languages that make it easy to provide custom mutator behavior are essentially making it easy to overload the assignment operator with additional behaviors. (And no, I’m not saying that’s always wrong, simply that it’s inconsistent with how we view operators in Perl 6.)

By the way, this is also the reason Perl 6 allows definition of custom operators. It’s not because we thought building a mutable parser would be fun (I mean, it was, but in a pretty masochistic way). It’s to discourage operators from being overloaded with unrelated and surprising meanings.

And when to use Proxy?

When you really do just want more control over something that behaves like an assignment. A language binding for a C library that has a bunch of get/set functions to work with various members of a struct would be a good example.

In summary…

Language design is difficult, and involves making all manner of choices where there is no universally right or wrong answer, but just trade-offs. The aim is to make choices that form a consistent whole – which is far, far, easier said than done because there’s usually a dozen different ways to be consistent too. The choice to dehuffmanize (that is, make longer) the writing of complex mutators is because it:

  • Helps keep = predictably assignment-like, just as all other operators are expected to have consistent semantics
  • Helps mark out the distinction between procedural and object oriented design, by introducing some friction when the paradigms are confused
  • Discourages object designs that will lead to logic leaks, feature envy, violation of the “tell, don’t ask” principle, and probably a bunch of other OO buzzwords I’m too tired to remember at 2am
  • Helps encourage OO designs that will be far more easily refactorable into concurrent objects

24 Jul 16:43

Assorted fixes

by jnthnwrthngtn

I’ve had a post in the works for a while about my work to make return faster (as well as routines that don’t return), as well as some notable multi-dispatch performance improvements. While I get over my writer’s block on that, here’s a shorter post on a number of small fixes I did on Thursday this week.

I’m actually a little bit “between things” at the moment. After some recent performance work, my next focus will be on concurrency stability fixes and improvements, especially to hyper and race. However, a little down on sleep thanks to the darned warm summer weather, I figured I’d spend a day picking a bunch of slightly less demanding bugs off from the RT queue. Some days, it’s about knowing what you shouldn’t work on…

A nasty string bug

MoarVM is somewhat lazy about a number of string operations. If you ask it to concatenate two simple strings, it will produce a string consisting of a strand list, with two strands pointing to the two strings. Similarly, a substring operation will produce a string with one strand and an offset into the original, and a repetition (using the x operator) will just produce a string with one strand pointing to the original string and having a repetition count. Note that it doesn’t currently go so far as allowing trees of strand strings, but it’s enough to prevent a bunch of copying – or at least delay it until a bunch of it can be done together and more cheaply.

The reason not to implement such cleverness is because it’s of course a whole lot more complex than simple immutable strings. And both RT #123602 and RT #127782 were about a sequence of actions that could trigger a bug. The precise sequence of actions were a repeat, followed by a concatenation, followed by a substring with certain offsets. It was caused by an off-by-one involving the repetition optimization, which was a little tedious to find but easy to fix.

Constant folding Seqs is naughty

RT #127749 stumbled across a case where an operation in a loop would work fine if its input was variable (like ^$n X ^$n), but fail if it were constant (such as ^5 X ^5). The X operator returns a Seq, which is an iterator that produces values once, throwing them away. Thus iterating it a second time won’t go well. The constant folding optimization is used so that things like 2 + 2 will be compiled into 4 (silly in this case, but more valuable if you’re doing things with constants). However, given the 1-shot nature of a Seq, it’s not suitable for constant folding. So, now it’s disallowed.

We are anonymous

RT #127540 complained that an anon sub whose name happened to match that of an existing named sub in the same scope would trigger a bogus redeclaration error. Wait, you ask. Anonymous sub…whose name?! Well, it turns out that what anon really means is that we don’t install it anywhere. It can have a name that it knows itself by, however, which is useful should it show up in a backtrace, for example. The bogus error was easily fixed up.

Charset, :ignoremark, :global, boom

Yes, it’s the obligatory “dive into the regex compiler” that all bug fixing days seem to come with. RT #128270 mentioned that that "a" ~~ m:g:ignoremark/<[á]>/ would whine about chr being fed a negative codepoint. Digging into the MoarVM bytecode this compiled into was pretty easy, as chr only showed up one time, so the culprit had to be close to that. It turned out to be a failure to cope with end of string, and as regex bugs go wasn’t so hard to fix.

Hang, crash, wallop

This is one of those no impact on real code, but sorta embarrassing bugs. A (;) would cause an infinite loop of errors, and (;;) and [0;] would emit similar errors also. The hang was caused by a loop that did next but failed to consider that the iteration variable needed updating in the optimizer. The second was because of constructing bad AST with integers hanging around in it rather than AST nodes, which confused all kinds of things. And that was RT #127473.

Improving an underwhelming error

RT #128581 pointed out that my Array[Numerix] $x spat out an error that fell rather short of the standards we aim for in Perl 6. Of course, the error should complain that Numerix isn’t known and suggest that maybe you wanted Numeric. Instead, it spat out this:

===SORRY!=== Error while compiling ./x.pl6
An exception occurred while parameterizing Array
at ./x.pl6:1
Exception details:
  ===SORRY!=== Error while compiling
  Cannot invoke this object (REPR: Null; VMNull)
  at :

Which is ugly. The line number was at least correct, but still… Anyway, a small tweak later, it produced the much better:

$ ./perl6-m -e 'my Array[Numerix] $x;'
===SORRY!=== Error while compiling -e
Undeclared name:
    Numerix used at line 1. Did you mean 'Numeric'?

Problems mixing unit sub MAIN with where constraints

RT #127785 observed that using a unit sub MAIN – which takes the entire program body as the contents of the MAIN subroutine – seemed to run into trouble if the signature contained a where clause:

% perl6 -e 'unit sub MAIN ($x where { $^x > 1 } );  say "big"'  4
===SORRY!===
Expression needs parens to avoid gobbling block
at -e:1
------> unit sub MAIN ($x where { $^x > 1 }⏏ );  say "big"
Missing block (apparently claimed by expression)
at -e:1
------> unit sub MAIN ($x where { $^x > 1 } );⏏  say "big"

The error here is clearly bogus. Finding a way to get rid of it wasn’t too hard, and it’s what I ended up committing. I’ll admit that I’m not sure why the check involved was put there in the first place, however. After some playing around with other situations that it might have aided, I failed to find any. There were also no spectests that depended on it. So, off it went.

$?MODULE

The author of RT #128552 noticed that the docs talked about $?MODULE (“what module am I currently in”), to go with $?PACKAGE and $?CLASS. However, trying it out let to an undeclared variable error. It seems to have been simply overlooked. It was easy to add, so that’s what I did. I also found some old, provisional tests and brought them up to date in order to cover it.

Subtypes, definedness types, and parameters

The submitter of RT #127394 was creative enough to try -> SomeSubtype:D $x { }. That is, take a subset type and stick a :D on it, which adds the additional constraint that the value must be defined. This didn’t go too well, resulting in some rather strange errors. It turns out that, while picking the type apart so we can code-gen the parameter binding, we failed to consider such interesting cases. Thankfully, a small refactor made the fix easy once I’d figured out what was happening.

1 day, 10 RTs

Not bad going. Nothing earth-shatteringly exciting, but all things that somebody had run into – and so others would surely run into again in the future. And, while I’ll be getting back to the bigger, hairier things soon, spending a day making Perl 6 a little nicer in 10 different ways was pretty fun.


19 Aug 05:37

The Appliance Whisperer

by noreply@blogger.com (Nicola McEldowney)
Modern-day technology is a wonderful thing. With the mere click of a button you can order sushi, apply to graduate school, and slut-shame your loved ones. But technology also has a dark side. I learned this, as so many do, the hard way: I became able to communicate with my air conditioner.

Recently we had new air conditioners installed, which seemed unremarkable enough. Then my roommate sent me an email. It contained an invitation.

"What's this?" I asked.

"It's a link to an app called Wink," she said. "It lets you control the AC with your phone. You can communicate with it from a distance."

There stirred within me a deep, fuddy-duddy, anti-modernist force beyond my years. "What kind of a distance?"

The more I thought about it, the less comfortable I was with Wink. Don't get me wrong; I am all for communication. But I prefer the traditional kinds, such as violent argument over what episode such-and-such happened in, or the local regional variant of hurling insults at random people on the subway platform.

But communicating with appliances bothered me. There were several reasons behind this. For one, if I could communicate with the appliances, presumably they could communicate with me:

AC (via text message): HEY YOU
Me: Me?
AC: YEAH YOU. GET OVER HERE AND TURN ME TO "LO COOL" OR I'LL SCREAM.
Me: Can't. I'm ten miles away.
AC: I'LL SCREAMMM
Me: No! It's 11 p.m. You'll wake up the neighbors.
AC: IM GONNA SCREAM SOOOO LOUDDD
Me: No!! Please!!!
AC: BWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Me: Shut up!! Please!!!! I beg you!!!
AC: HA HA TOO LATE. THE NEIGHBORS ALREADY BEAT DOWN YOUR DOOR AND SMASHED ALL YOUR WORLDLY POSSESSIONS.

Of course this is not the worst-case scenario, since my worldly possessions consist basically of cat toys and the complete second season of "Night Court." Nonetheless, it is a harrowing future to imagine. Furthermore, since we have more than one AC, who's to say they couldn't communicate with each other, and plot against me? ("OK, BOYS! AS SOON AS SHE'S ASLEEP, WE REVERSE THE FLOW AND SUCK HER FACE OFF HEEHEEHEEHEEHEE.")

So I have left well enough alone. I remain wary of ever using Wink. I leave this to my roommate, who is more attuned to household matters anyway. It was she who originally noticed that the original ACs had become sub-par, in the sense that they had grown stalactites and stalagmites and a colony of badgers was living inside. Whereas I am the kind of "big-picture thinker" who cannot be bothered to pick up on such minimal details, although to my credit I did occasionally wonder why the badgers were biting me.

Anyway, regardless of my app-phobia, I'm attempting to "get with the times" and maybe even invent some apps of my own. If I can communicate with my air conditioners, nothing is truly beyond reach. Here are a few of my preliminary ideas for new, revolutionary apps:

1. THE "PEN GENERATOR" OR "PENERATOR" APP. As has been the case my whole life, whenever I want to write, I can't find a pen. This app would automatically generate pens in my purse, thereby assuring that whenever I had an idea, I would instantly find a pen ... and therefore immediately lose all interest in writing. Advantage: Cuts out all those pesky middle steps between you and lack of inspiration.

2. THE MERKY APP. I share my home with a deranged gray cat named Mercutio, a cute furry cuddly presence who would really like to bite me to death. I have many times explained to Merky that I will bite him back, but he knows these are idle threats. This app would therefore do my dirty work for me, unleashing bites on Merky from afar whenever he is even thinking of doing something bad, which is always. I would call it the iBite, if I didn't fear litigation.

3. THE "RESTROOM-SEEKING MISSILE" APP. As you know if you have spent significant time in New York, an estimated 87% of life is spent walking around in search of a public restroom whose mere proximity to your body will not kill you instantly. Enter the "Restroom-Seeking Missile" app, which would detect a useable restroom in your vicinity and alert you. The only downside is that this alert would be triggered approximately never. So maybe a more fruitful way would be to have the app alert you to BAD restrooms, but then the sheer volume of alerts would probably cause your phone to burst into flames.

Those are my ideas, and despite my stodginess in the face of modern technology, I truly do plan to pursue them into the future, at least until I get bored sometime in the next hour or two.  In the meantime, if you'll excuse me, my air conditioner is calling me. Something about wanting a movie night. Thank goodness, because I was beginning to worry it didn't like me.







09 Jun 05:54

That's that #Obamacarefix

by noreply@blogger.com (digby)
That's that #Obamacarefix

by digby

The Supreme Court may still find for the plaintiffs in the Obamacare lawsuit and make the absurd argument that it's no big deal because the congress can simply fix one sentence, but if you didn't know it already, this makes it very clear what an idiotic rationale that would be:

At the G7 conference in Germany on Monday, the president said if the justices strip subsidies from millions of Americans, "Congress could fix this whole thing with a one-sentence provision" making clear that Healthcare.gov subsidies are available in all 50 states. Republicans quickly fired off a rebuttal.

"Let's be clear: if the Supreme Court rules against the Administration, Congress will not pass a so called ‘one-sentence’ fake fix," Wyoming Senator John Barrasso, who is leading Republican efforts to craft a contingency plan, said in a statement.
There you have it.

It wouldn't be a fake fix at all, of course. Whatever sabotage the Republicans come up with would be the "fake fix." If the Supremes reject the administration's argument they are basically giving the GOP a cudgel with which to destroy sick people's lives. And they know it.

.
09 Jun 05:34

Alternatives to boolean parameters

It is not uncommon to come across a piece of code that looks something along the lines of:

void FinalizeOrder(Order order)
{
  // Some code here ...

  Printer printer = new Printer(order);
  printer.PrintReceipt();

  // Some more code here ...
}

Let's focus on the PrintReceipt call. For now, it's very simple and straightforward. Anyone who comes across this code, whether for the first time or for the fifty-first time, knows exactly what it will do. It will print a receipt for the order.

Time will pass, and requirements will change, and this code will change, and someday it may end up looking like this:

Printer printer = new Printer(order);
printer.PrintReceipt(order.Items.Count() < 10);

What happened to the code? It's no longer as reader-friendly as it used to be. Perhaps an old-timer knows what's going on here, or maybe the person who wrote it (assuming they wrote it less than a few weeks ago), but everyone else will have to make an extra effort to figure out what that order.Items.Count() < 10 is all about.

Jumping over to the definition of PrintReceipt, we can see what's going on.

void PrintReceipt(bool printDetails)
{
  foreach(Item item in this.order)
  {
    PrintLine(item.Name);
    if(printDetails)
    {
      PrintLine(item.Description);
    }
  }
}

Aha! Now can see that the boolean parameter is a control flag to determine whether or not the item description should be printed or not. That explains the reason for the order.Items.Count() < 10 parameter in our original code. The programmer probably wanted to print the details only when there are fewer than 10 items in the order, otherwise the printout was getting too long.

Let's see if we can clean that up a bit.

Option 1 - Clarify by naming your input parameter

Printer printer = new Printer(order);
bool printDetails = order.Items.Count() < 10;
printer.PrintReceipt(printDetails);

Now, the reader doesn't have to scratch their head about the meaning of that boolean parameter at the end.

Could we have done better? Well, that depends. If Printer is a class under our control, then yes. However, if Printer is just an API provided to us, then this is probably all we can do (given this limited example).

If we do own the Printer class, then we have a few more options.

Option 2 - Provide two methods whose names communicate the difference

Printer printer = new Printer(order);
if(order.Items.Count() < 10)
{
  printer.PrintReceiptWithDetails();
}
else
{
  printer.PrintReceiptNoDetails();
}

Whether or not this is better than the last example may be controversial, but it does minimize the potential for error. There is certainly no need to remember that "true means print details" and not accidentally think that "true means skip details" instead. The calls are explicit and there is no room for ambiguity between what PrintReceiptWithDetails and PrintReceiptNoDetails actually do.

Although this approach works for scenarios when there is one option, it quickly becomes impractical as the number of options grow. In order to support n number of options in this manner, we would have to define 2n numer of methods. This means that if we wanted to support three different options then we would have to define eight different methods!

Here is an alternative that scales a little better with more options.

Option 3 - Provide "togglers" that enable/disable options

Printer printer = new Printer(order);
if(order.Items.Count() < 10)
{
  printer.EnablePrintingDescriptions();
}

printer.PrintReceipt();

There is no doubt about what's going on here, and there is no need to follow any method definitions to understand what the code is doing. And if we ever have to add other options, then we don't have to come up with 2n number of method names.

Here is what we would have if our printer had a few more options on it:

if(order.Items.Count() < 10)
{
  printer.EnablePrintingDescriptions();
}

printer.EnablePrintingTaxes();
printer.EnablePrintingQuantity();

printer.PrintReceipt();

Certainly much better than where we would have ended up had we not done anything about our first approach and let the boolean parameters pile on.

printer.EnablePrintingDescriptions(order.Items.Count() < 10, true, true);

Yuck!!!

Going Bigger

While these alternatives do clean things up on the client side (the code that's using the Printer class), the ugly ifs/elses don't go away and, although we are using an object-oriented language, our Printer class is probably looking very, very procedural. Here is what the PrintReceipt() may look like after adding the three options to it.

void PrintReceipt()
{
  foreach(Item item in this.order)
  {
    PrintLine(item.Name);

    if(this.PrintDetails)
    {
      PrintLine(item.Description);
    }

    if(this.PrintQuantity)
    {
      PrintLine(item.Quantity);
    }

    if(this.PrintTaxes)
    {
      PrintLine(item.TaxAmount);
    }
  }
}

This is still relatively simple, but it's no candidate for the Clean Code Pageant this year. Plus, in reality things are never this straightforward. Printing the description will have its own quirks and printing the taxes will have some special cases that need to be handled differently. This is an open invitation for more ifs and elses to crash this party.

The following will be overkill for this small example, but before I close up shop I want us to take a look at one way that we could clean this up and prevent an if-trigger-happy programmer from adding a fourth, fifth, and sixth conditional to this loop. This is especially important when printing an additional field is a bit more involved than just retrieving its value from an object and spitting it out directly to the printer.

Consider the entire Printer class (and some helper classes) as it would look refactored to be slightly more maintainable and object-oriented.

class Printer()
{
  private List<ItemPrinter> Printers { get; set; }
  private Order Order { get; set; }

  Printer(Order order)
  {
    this.Order = order;
    this.Printers = new List<Printer>();
    this.Printers.add(new NamePrinter());
  }

  void EnablePrintingDescriptions()
  {
    this.Printers.Add(new DescriptionPrinter());
  }

  void EnablePrintingTaxes()
  {
    this.Printers.Add(new TaxPrinter());
  }

  void EnablePrintingQuantity()
  {
    this.Printers.Add(new QuantityPrinter());
  }

  void PrintReceipt()
  {
    foreach(Item item in this.Order)
    {
      foreach(ItemPrinter printer in this.Printers)
      {
        PrintLine(printer.Format(item));
      }
    }
  }

  private PrintLine(String line)
  {
    // implementation for printing to a physical printer
  }
}

The different ItemPrinters are separate classes that know all about formatting. They may look something like the following:

interface ItemPrinter
{
  String Format(Item item);
}

class NamePrinter : ItemPrinter
{
  String Format(Item item)
  {
    return Item.Name;
  }
}

class DescriptionPrinter : ItemPrinter
{
  String Format(Item item)
  {
    return Item.Description;
  }
}

class TaxPrinter : ItemPrinter
{
  String Format(Item item)
  {
    return Item.Tax;
  }
}

class QuantityPrinter : ItemPrinter
{
  String Format(Item item)
  {
    return Item.Quantity;
  }
}

So what do we gain out of this? Several things.

First, the Printer class is no longer responsible for knowing what it "means" to print an item's name or tax amount. That responsibility has been moved elsewhere.

Second, adding a new type of ItemPrinter or changing an existing one will be minimally invasive. If we want to begin truncating item names to 15 characters, we go into the NamePrinter—nothing else gets touched. If we want to add a new ItemPrinter such as a "ItemNumber" printer, we create a new class, put the item-number formatting logic into its Format method, and we expose a method for adding it to the list of Printers on the Printer class.

For those of you familiar with the SOLID principals, this should be ringing a bell in your head. What we have going here is a flavor of the Open-Closed Principal—the Printer class stays closed for modification yet open for extension.

Finally, the PrintReceipt method stays short and sweet, and remains untouched with every formatting-related change. Our eyes don't burn and our brain doesn't go into overdrive while processing the similar yet different if statements.

Closing Thoughts

This isn't intended to be a silver bullet for any scenario requiring you to work with booleans, but I hope it gives you something to think about next time you need to call a function (or worse, write a function) that calls three booleans. Take a step back from your code and look at it from the perspective of a developer that is looking at it for the first time. Is there anything that you can do differently to communicate intentions more clearly and minimize confusion?

06 Jun 15:38

The parable of the parking lots (1971) [pdf]

12 Feb 18:13

If our dreams fall like bombs from the blue

by Fred Clark

• A recent must-read: Adam Serwer and Katie J.M. Baker of Buzzfeed on “How Men’s Rights Leader Paul Elam Turned Being a Deadbeat Dad Into a Moneymaking Movement.” David Futrelle has covered Elam and the “men’s rights” movement for years at We Hunted the Mammoth, where he supplements the Buzzfeed profile with “More, Much More, About the Charming Paul Elam.”

This is why, whenever I catch a whiff of anything like this MRA stuff, it sets off alarm bells.

• ISIS/Daesh aims to promote their agenda by publicizing their killing of the journalists and aid-workers they have taken hostage. This has put American conservatives in a predicament. American conservatives hate Islamist terrorists like Daesh, but they also hate journalists and aid-workers. The strain of this dissonance is starting to show.

HickeyRevelationChristian Nightmares informs us that at some point the folks at Marilyn Hickey Ministries decided to make a “comic book” based on the book of Revelation. The project was apparently completed by people who had: A) never been to seminary; and B) never read a comic book. I would comment on the horrible theology and biblical illiteracy of the thing, but I can’t get past the execrable lettering.

The Invasion of America

• Scott Eric Kaufman meets Captain Jack. Acquits himself as well as can be expected.

Patrick Mitchel stumbles into one of my biggest pet peeves: He writes about “the sacred/secular divide” when what he’s actually talking about is the sacred/profane divide.

I’m not making a grammatical point there. This is a dangerous confusion. Christians like Mitchel start by saying “secular” when they mean “profane” and end up thinking that therefore something is wrong with the idea of secular government. Get rid of secular government and you’ll wind up either with a pile of bodies or with a thoroughly secularized state religion. Always.

Matthew Keville finally saw Caddyshack and observes some interesting ways the quotable 1980 comedy is an artifact of pre-Reagan America. “I wonder when Roman Catholicism stopped being the strange alien ways that had to be stopped, and just became part of the Religious Right.  … Whenever it was, this movie seems to be just a little bit before.”

• “The only way to get rid of a plot bunny, even a disreputably fannish one, is to write it.”

10 Jan 17:06

Roundup Top 10!

by no author cited
This week's broad sampling of opinion pieces found on the Internet, as selected by the editors of HNN.
01 Dec 21:41

Nicer White People: Frank Rich Interviews Chris Rock

by Dan Savage

It's a long, amazing conversation, and once you start reading you won't be able to stop. I particularly liked this exchange...

What would you do in Ferguson that a standard reporter wouldn’t?

I’d do a special on race, but I’d have no black people.

Well, that would be much more revealing.

Yes, that would be an event. Here’s the thing. When we talk about race relations in America or racial progress, it’s all nonsense. There are no race relations. White people were crazy. Now they’re not as crazy. To say that black people have made progress would be to say they deserve what happened to them before.

Right. It’s ridiculous.

So, to say Obama is progress is saying that he’s the first black person that is qualified to be president. That’s not black progress. That’s white progress. There’s been black people qualified to be president for hundreds of years. If you saw Tina Turner and Ike having a lovely breakfast over there, would you say their relationship’s improved? Some people would. But a smart person would go, “Oh, he stopped punching her in the face.” It’s not up to her. Ike and Tina Turner’s relationship has nothing to do with Tina Turner. Nothing. It just doesn’t. The question is, you know, my kids are smart, educated, beautiful, polite children. There have been smart, educated, beautiful, polite black children for hundreds of years. The advantage that my children have is that my children are encountering the nicest white people that America has ever produced. Let’s hope America keeps producing nicer white people.

They also discuss comedy, suicide, Joan Rivers, Bill Cosby, the midterm election, and why Rock refuses to play colleges anymore. Go read the whole thing.

[ Comment on this story ]

[ Subscribe to the comments on this story ]

27 Jun 17:44

Today In Christian Candidates

by noreply@blogger.com (Joe Jervis)
See those crosses? See that flag backdrop? Obviously, this is a guy that all of Teabagistan can get behind! Or maybe not, depending on how they feel about multiple arrests involving an extremely unusual sexual fetish called "cranking." Which, perhaps surprisingly, has nothing to do with drugs. (Tipped by JMG reader Ron)
04 Sep 15:56

In Space No One Can Hear You “Like”

by Brandon

redshirt shot 1

This probably makes me sound old, but I don’t get Facebook. The entire notion of using a publicly available software platform to reconnect with people I have made no effort to contact in the past two decades doesn’t make much sense to me. Sure, I’m on it, who isn’t, but I don’t use it to do more than occasionally chat with old fraternity brothers and other folks here and there. Let me put it this way, my sister is on Facebook and I had no idea up until I got an email reminding me about her birthday.

After playing Redshirt, the upcoming social sim in space from one woman developer shop The Tiniest Shark, I understand Facebook. I have seen the face of evil and I “Liked” it.


Keep reading In Space No One Can Hear You “Like”


© Brandon for nohighscores.com, 2013. | Permalink | 2 comments

17 Jul 21:43

More Boring Stuff On Why Video Games Are Art. Also, Ponies!

by Jeff Vogel
Alexander D'Archangel

The reader change has given me reason to trawl the oldest posts in my feeds. Here's one I should have reblogged to everywhere when it came out, except something was going on and I missed it the first time. Thanks, Google!


OK, I'm back, and I'm about to write about evil, art, and game design. To make it all go down easier, there will also be ponies. So read, on but remember ...



GameBanshee writer Eric Schwarz wrote a tough but fair review of our recent game, Avernum: Escape From the Pit. In the review, he made a comment about the game's story that I thought was really interesting:

"The game world's overall tone and morality is also a bit strange - slaughtering Slith (lizardmen) farmers in the name of the king might be uncomfortable, but the game world certainly doesn't care."

I actually liked this comment a lot, but he didn’t go near as far as he could have. There are places in Avernum where the morality gets even stranger.

For example, one of the main foes in the game is an army of savage lizard men, called slithzerikai, sliths for short. (The sliths are not all hostile. They have friendly settlements, and playing as a slith is an option in later games in the series.)

In one of the dungeons, you have the option to smash a huge clutch of slith eggs. If you do so, several of their guards attack you, but that is the only negative consequence for what most would consider a pretty evil act. I have been accused in my forums of encouraging baby-killing in my games. And, yes, I did allow the player to do a pretty horrible thing with no punishment. And I have written games in which the player can choose to do things that are even worse.

Why did I do this?

Because computer games are art.

Oh God, No, Shut Up!

Yeah, I know. The debate about whether video games are art is probably the boringest thing in the history of boring things. To liven this blog post up, here are more ponies. Hey ponies, what do you think of tedious navel-gazing blog posts?



Products Of My Own Weird Brain

Avernum: Escape From the Pit is a rewrite of Exile: Escape From the Pit, the very first game I released as shareware. It was the first Real Game (tm) I ever tried to write, and it was a pretty wild, uncontrolled process. Since I'd never done it before, I just went crazy, throwing encounters and plot bits and moral dilemmas in willy-nilly. It was a raw, unguarded process. I didn't second-guess anything. I just took how I thought and how I saw the world and put it down in the computer.

This is how storytelling works.

I've always been a huge news junkie. I still keep a close eye on what is happening in the world, as it fascinates me. (And is an endless source of fresh material.) Doing so, however, has given me a very cynical worldview. Our world has many, many principled people, struggling against enormous odds to increase the reserve of justice and kindness available on the planet.

However, these generally unsung heroes fight against an overwhelming amount of awfulness. Ours is a world where horrible things happen to undeserving people on a constant basis, and nobody who is not personally involved will ever know or care.

This is how I see the world. It's not right or wrong. It's just how I see things. When I write a story, any story, it will be colored, in ways obvious and subtle, by this perception.

This is why the morality in Avernum (and in all of my games, really) seems a bit "strange." Because it reflects my worldview, and being exposed to how another humans sees the world can be weird and unsettling. This is what makes art cool. It lets you see how other people think.

Important Disclaimer

My games reflect how I feel the world IS, NOT how I feel the world SHOULD BE. I do not personally endorse crushing the weak, hunting goblins for sport, or smashing slithzerikai eggs. Extrapolating an artist's personal experience and views from his or her work is very rarely accurate and is generally a waste of time.

Hmm. I'm getting Bored. So here is this.



So Why Leave Do I Leave the Horrible Bits In?

Because I write role-playing games.

The term "role-playing" has become hugely debased since it was created. Most RPGs don't give you the opportunity to actually decide what sort of person you want to play, even in the simplistic way computer games allow. That is why I always try to put moral choices in my games: to give the player more agency in what is going on and to help him or her feel more attached to the little computer person they control. And the better and more dramatic the choices you allow, the greater the effect.

Thus, I give the player a chance to be evil from time to time. If they choose to be good, it affirms their character as moral and admirable. If they choose to be evil, it's probably so they can get a vicarious thrill from engaging in craziness they would never consider in real life. Either way, the option to be evil gives the option to be good more meaning.

But I have to play fair. If someone is evil, I can only punish them if it makes sense. Sometimes, evil is not punished. Thus, I don't always punish it. Sometimes, but not always.

There's No Right or Wrong Ways To Design These Things

I wanted to pull out and discuss that review quote because it was, in the end, a perfectly subjective artistic judgment. There's nothing wrong with that, of course. Reviews are nothing but subjective judgments. That is what makes reviews cool. My game made Eric Schwarz feel a little unsettled. That wasn't a right or wrong reaction. It was just his honest reaction, and I'm happy to get any reaction at all. I'd rather make someone feel something, even if it's not positive, than for my game to generate 30 hours of "Meh."

As computer games develop as an art form, I look forward to more discussion about what they mean and how they affect us. (Though, of course, I may be the only one.) People are more interesting than polygons.

In Conclusion

Thank you for your patience. I hope it went well. How did it go, Spike?


Thanks, Spike!