Showing posts with label open-source software. Show all posts
Showing posts with label open-source software. Show all posts

Showdown at Unobtanium—for SCIENCE!

Hello, my fellow mad scientists. If you attended my talk at Showdown at Unobtanium, thank you for being part of a fantastic audience—the enthusiasm you fed back to me was infectious and inspiring. Make things and tell me about it!

Please join us at Polyglot Programmers of Austin,  our co-working study group for learning a new programming language (including your first). Breadboards are as welcome as keyboards. Also, I'll be there, happy to answer your Arduino questions.

Some details about my small robot friend, to amuse you. My costume was an homage to Agatha Clay (and her clank) of the Girl Genius comic book. I posted some pictures of the clank's construction process. What makes it fidget is a servo motor on its back, driven by an Arduino in my purse, running an Arduino sketch I wrote (source code).

You might appreciate the Nerd Nite wrapup from the last time I spoke on this topic. There are useful links in there, pertinent to the presentation you saw at the Showdown, specifically the slide deck that contains links to resources for learning more.

Some of you talked to me about presenting to your students at your schools. Yes, please! Get in touch.

Thanks for being awesome. Make fantastic things.

Hello, Nerds. Hello, World. Hello, Arduino.

Thank you to Nerd Nite Austin for a fantastic venue, and my thanks to all of you who were there, creating a palpable enthusiasm for Making Stuff! What a hoot. Resources for ya...

The slidedeck: Hello, Arduino

Samples of my Arduino code are on GitHub, because I like to think out loud in code.

A description of the blinky-eyeball Halloween costume

That "hang out and code with other people learning to code" study group is Polyglot Programmers of Austin, our next meeting is tomorrow, and you should totally join us.

Lest you need some motivation for making nerd presentations of your own, check this out. Some months back, I presented at a Dorkbot meeting at the ATX Hackerspace. Afterwards, someone approached me with "I don't know if you remember me, but..." And kapow! Timewarp! Here was my friend from nerd camp, whom I hadn't seen in 20 years! Wow! We've had a blast catching each other up. Then, I'm presenting at Nerd Nite tonight, and after that, another friend from nerd camp comes up and says hello.

Dude, I'm telling you. Take your awesome hobbies, go to nerdy things and present your awesomeness, and fantastic nerdy friends whom you miss will discover you and reconnect with your life. What a delightful unexpected benefit.

An Object Lesson in Binary Compatibility

A riddle for you, friends: When is changing a method from return void to return Something a breaking change?

If you already know the answer, then why hadn't you told me? Could've saved me a fair bit of embarrassment. Ah well, maybe I missed your call.

First, a story


I had the opportunity to contribute to the HtmlTags open-source project1. They needed some unit test coverage, and I <3 unit testing and wanted to try my hand at contributing to open-source software. As I got my bearings, I got more confident and started to reach beyond the unit test project into refactoring the application code.

That's when I found the AddStyle and AddJavaScript methods. Their friends returned an HtmlTag, but they returned void. They would be easier to test if they returned an HtmlTag, but that's not a good justification for changing a method. But they would be more consistent if they behaved like their neighbors, and that is a sufficient justification to consider it.

HtmlTags is a library meant to be consumed by other applications. It was already in use in the wild. Therefore, it was important not to change its API. It had to work like it always had, else we'd cause considerable grief to the developers using our code. I've been the consumer of a service that made breaking changes to its API, and I have choice things to say about the team that saddled me with that noise.

I thought really carefully. I was contemplating changing the return type of a public method in an in-use API. But all those uses would be calling it as if it returned nothing, and you can invoke a method without using its return value. This would be just like that. I asked a coder-buddy for advice. We convinced each other: What harm could it do?

What about the riddle?


Here we come to the answer to the riddle. If you're changing a library that will be called by other applications, then there are many seemingly harmless changes that are actually breaking changes, including changing a method's return type. When the consuming assembly is compiled, it is built with instructions to find a method named Whatever that returns void, but the changed assembly's manifest contains only a method named Whatever that returns string. No match.

Computers. They're so literal.

To fix it, you merely need to recompile the consuming application, but you don't discover the problem until assemblies are loaded at run-time, an annoying time to discover exceptions. I coded up a simple example that illustrates the problem. Feel free to follow along at home.

See the problem in action


Make two separate solutions, a class library called MessageOutputter and a console application called ConsoleMessager that references MessageOutputter. First, build MessageOutputter with a return void method.

namespace MessageOutputter
{
  public class Outputter
  {
    private string _message = "This is the outputter, version 1.";

    public string Emit()
    {
      return _message;
    }

    public void UpdateVersion(string versionNumber)
    {
      _message = string.Format("I've been altered by the UpdateVersion method. I am version {0}.", versionNumber);
    }
  }
}


UpdateVersion modifies a private field but does not return a value. Compile that solution and put its dll into a lib folder from which you will reference it in ConsoleMessager. Open the ConsoleMessager solution and add a reference to the MessageOutputter.dll. Write a method that uses the MessageOutputter.

namespace ConsoleMessager
{
  class Program
  {
    static void Main(string[] args)
    {
      var outputter = new MessageOutputter.Outputter();
      Console.WriteLine("Calling the outputter:");
      Console.WriteLine(outputter.Emit());
      Console.WriteLine("Asking the outputter to update, then calling it again.");
      outputter.UpdateVersion("Updated 1");
      Console.WriteLine(outputter.Emit());
      Console.Read();
    }
  }
}


The UpdateVersion method is called, not expecting a return value. Build and run the ConsoleMessager.



Return to the MessageOutputter solution and modify the UpdateVersion method to return the message after it modifies it.

namespace MessageOutputter
{
  public class Outputter
  {
    private string _message = "This is the outputter, version 2.";

    public string Emit()
    {
      return _message;
    }

    public string UpdateVersion(string versionNumber)
    {
      _message = string.Format("I've been altered by the UpdateVersion method. I am version {0}.", versionNumber);
      return _message;
    }
  }
}


Now UpdateVersion returns a string. Build the solution and copy its new dll back into the lib folder, and into the Debug or Release folder under ConsoleMessager/bin, so that the ConsoleMessager will run with your new version of the dll. Run ConsoleMessager and you will encounter the error:
Unhandled Exception: System.MissingMethodException: Method not found: 'Void MessageOutputter.Outputter.UpdateVersion(System.String)' at ConsoleMessager.Program.Main(String[] args)




The MissingMethodException indicates that ConsoleMessager, when looking within the MessageOutputter library, could not find an UpdateVersion method that returns void. Reopen the ConsoleMessager solution. Before you even build, IntelliSense will tell you that UpdateVersion returns a string now. Build ConsoleMessager and run it again, to see that it works successfully.



Wiser now


No one raked me over the coals—in fact, my intro-to-OSS experience was thoroughly positive, and I can't wait to do more—but I know I caused some time-consuming inconvenience to my fellow devs. I have now learned that Binary Compatibility is not the same as Source Compatibility. Conflating the two is like saying, "Works on my machine." I hope this write-up can help you avoid a similar goof.

1 The nice thing about open-source projects is that everyone has the opportunity to contribute. But I had the especially good fortune to have willing help from Josh Flanagan in finding my way through my first OSS pull request.