45

It's another one of those "5" years. I'm now halfway to 90. 90 sounds old, but once upon a time, 45 sounded old too.

The year has not been easy. We lost my maternal grandmother, Ann Woods, in August. I have many good memories of time spent with her up in North Dakota.

My brother announced that he and his wife were getting a divorce. Again, not happy news, but we have to accept it. The end-of-year family get-togethers have seemed incomplete without my sister-in-law.

However, even with those events, this year has been a pretty good one for me.

Professionally, things have been better than usual. I developed Real Professional mobile apps for iPhone/iPad and Android. These apps have over 30,000 users, and they have been well received. Most applications I've developed during my career had only a few dozen users, so this larger reach gives me a sense that I can have some sort of effect on the world.

I've wanted to make iPhone and iPad software since I was 12 years old. Unfortunately, iPhones and iPads didn't exist back then. I'm glad that the devices are finally here, and that they pay me to work with them.

One resolution I've made for the coming year is to spend at least one hour per day working on personal programming projects. I gave up programming "for fun" a few years ago when work was burning me out, but now my interest has been rekindled.

I started meditating almost-daily about 12 months ago. For this, I credit 5by5's Dan Benjamin, who mentioned his meditation practice on several podcasts. I'm no zen master, but I do feel less stress and it's easier to ignore all the little problems in my life. I only have a mental breakdown two or three times a day now.

The optometrist prescribed progressive lenses for me this year. I don't like having old-people glasses, but I'm glad that my corrected eyesight is better. I wish I'd gotten these years ago.

Life with my wife and stepson keeps getting better. Bailey has matured and calmed down a lot over the past year—we actually see him smile once in a while! Pebble hasn't had to spend any time in the hospital this year, which makes us both feel a lot better. Our five dogs are all healthy and happy. Our little cabin in the foothills is still the nicest place I've ever been.

I don't like getting older, but as long as the years keep getting better, I won't complain about it.

Creating .NET Remoting IPC Channels

Yet another C# code snippet. I'm developing a service and an accompanying UI that always run on the same physical box, and it was suggested that I implement the communication between them using .NET Remoting and the IPC channel type, which is a supposedly-easy way to get processes on the same machine to talk to one another.

Of course, it wasn't easy, because if you simply create and register an IpcChannel with default parameters, you get security-related exceptions when you try to do anything with it. You have to delve through documentation and online forums to figure out what underdocumented magic is required to get the stuff to actually work.

There were two obstacles I had to overcome:

  • By default, user-defined types will not be deserialized, to prevent deserialization-based attacks by malicious clients. To disable this "feature", one must set the TypeFilterLevel to Full.
  • My service runs as the LocalSystem user, whereas the client application runs in the logged-in user's security context. By default, the user's account would not be able open the IPC port that the service creates. The fix to this is to set the channel's authorizedGroup to the name of a user group that is allowed to open the port.

So, as usual, the resulting code looks simple, but it took a couple of hours to figure out what had to be written.

Configuring WebDAV and Digest Authentication for Ubuntu

I'm looking at using WPKG as a mechanism for distributing software updates to client workstations. WPKG appears to be a pretty nice system, but it has one big downside: one has to set up a WebDAV-enabled server if the updates are to be pulled from the Internet instead of from a local shared directory. So I've spent a few hours learning the intricacies of setting up WebDAV on my Ubuntu-based Internet server and accessing it from Windows machines. Here's what I learned.

Deserializing Objects from XML in C#

Here's another C# code snippet that takes me way too much time to recreate by just reading the documentation.

This is a simple example of a class that can be serialized to/from XML. In this case the "ServerConfig" XML string can contain a list of servers, looking like this:

<ServerConfig loggingEnabled="1">
  <Servers>
    <Server host="test1.example.com" port="9999" />
    <Server host="test2.example.com" port="8888" />
  </Servers>
</ServerConfig>

The client code can just do "var serverConfig = ServerConfig.FromXmlString(s);" to deserialize it into a ServerConfig object.

using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;

public sealed class ServerConfig
{
    public sealed class Server
    {
        [XmlAttribute("host")]
        public string Host { get; set; }

        [XmlAttribute("port")]
        public int Port { get; set; }

        public Server()
        {
            host = "";
            port = 0;
        }
    }

    [XmlArray]
    public Server[] Servers { get; set; }

    [XmlAttribute("loggingEnabled")]
    public int LoggingEnabled { get; set; }

    public ServerConfig()
    {
        Servers = null;
        LoggingEnabled = 0;
    }

    /// <summary>
    /// Create an instance of ServerConfig from an XML string
    /// </summary>
    /// <param name="xmlString">XML string containing &lt;ServerConfig&gt; element</param>
    /// <returns>ServerConfig instance</returns>
    /// <remarks>
    /// Throws an exception if the XML string is not valid.
    /// </remarks>
    public static ServerConfig FromXmlString(string xmlString)
    {
        var reader = new StringReader(xmlString);
        var serializer = new XmlSerializer(typeof(ServerConfig));
        var instance = (ServerConfig) serializer.Deserialize(reader);

        return instance;
    }
}

(The method that would serialize a ServerConfig to an XML string is left as an exercise for the reader. I rarely need to do that.)

Pretty-formatting XML in C#

I had a need to convert an XML string to a nice, indented format. It was a little more complicated than I expected, so I'm posting this snippet here where I can find it again when I need it.

using System;
using System.Text;
using System.Xml;
using System.Xml.Linq;

static string PrettyXml(string xml)
{
    var stringBuilder = new StringBuilder();

    var element = XElement.Parse(xml);

    var settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    settings.Indent = true;
    settings.NewLineOnAttributes = true;

    using (var xmlWriter = XmlWriter.Create(stringBuilder, settings))
    {
        element.Save(xmlWriter);
    }

    return stringBuilder.ToString();
}

Note that this method can throw exceptions for a variety of reasons.

Code Reuse Is Not Lazy

Stack Overflow is an amazing resource for computer programmers. I've asked a lot of questions there, and answered a lot of questions there, and I've found the answers to lots and lots of questions that someone else has already asked. Participating in Stack Overflow has been great.

However, there have been a few cases where I've asked a question in this form:

I need some code that will [...]. Can someone point me to some existing code that does this?

And then I have received responses and comments like these:

We aren't here to do your homework for you.

You can't expect help without doing a little bit of work on your own.

You mean "Plez sir send me the codez?"

I don't understand why my questions provoke these responses. It is possible that I am asking the question in a way that the readers interpret as demanding or rude. But I also wonder if some people think that looking for existing code to solve a problem is a dishonorable thing to do, and Real Programmers write everything they need from scratch.

What if I had asked this:

I am new to C. I need to format some printed output in my C program. What's the easiest way to do this?

I hope someone would respond with

There is a standard function called "printf()" that will do what you want.

and not

Why can't you just figure out how to write your own formatting function It's the best way to learn C. Or are you just too lazy to spend time learning things?

Appropriate reuse of already written and debugged code is the mark of a professional, and time spent in research of existing implementations of algorithms you need is time well invested. If you want to write the millionth from-scratch implementation of Quicksort in your favorite programming language, go right ahead, but those of us who have real work to do are going to look for a library or a code snippet.

Steve Jobs

It's OK to have heroes, right?

I didn't think I had any heroes, but when Steve Jobs passed away last week, it hit me harder than expected. I didn't cry, I didn't go into a funk, but I was sad and felt like I'd lost something.

We idealize our heroes. We ignore their flaws and the fact that they are just regular people, and instead create simple character sketches based on a few noble aspects of their personalities and deeds. For example, Albert Einstein was a very smart, yet very warm and kind person, Abraham Lincoln freed the slaves, and Thomas Jefferson wrote the Declaration of Independence. We reduce a hero to a simple sentence, knowing that it is an incomplete picture, but focusing on what it is that makes the hero important to us.

Steve Jobs inspired people to make awesome things.

To me he represents the drive to make things better. But "better" wasn't good enough; he insisted that they be great. Sure, he exaggerated the greatness of Apple's products, and didn't give credit to the sources of many of the ideas that went into those products, but he did everything he could to make them the best they could be, and to give them a little bit of magic.

He didn't make things easy for software developers, or for hardware engineers, or for component manufacturers, or for IT managers. He simply did not care about their problems. His goal was to bring the amazing power of computers to normal people. He wanted normal people to have machines that they could use to create things and to enjoy themselves, without expecting them to become programmers and hardware techs.

A lot of business-type people wish that they were Steve Jobs. Not me. I would not have wanted to be Steve Jobs, but I would have loved to work for Steve Jobs. Even if I was the recipient of his famously colorful criticism, I'd know that I was getting advice from someone who expected me to do great things.

I missed out on the Apple II era (having an Atari 800 instead), so my first Apple product was a Macintosh SE. I loved that cute, beautiful little computer. I learned Pascal, C, and Motorola 68000 assembly programming on that computer. I drew pictures, I played games, I stuck it in the back seat of my car when going from place to place.

But you know what it is about that Mac that really sticks out in my memory? If you opened the case, instead of finding just metal and wires, you found engraved signatures of Steve Jobs and other members of the Macintosh team. They had created something special, and they were very proud of their work. That inspired me to be proud of the things I make, and to make them as beautiful and magical as I am able.

Sometimes I forget to do those things. I need Steve Jobs around to occasionally remind me.

It's OK to have heroes, right?

My Visit to Android-land

I've been a happy iPhone and iPad user for a while, but I'm currently involved in developing Android applications, so I decided to buy an Android phone to use for a few weeks. It's important to understand the user-interface conventions and user expectations for whatever platform you are developing for, and I figured that the only way to learn those things would be to take the plunge and immerse myself in Android for a while.

The following is a self-indulgent review of what I've found. If you are an Android fan, you will probably summarize it as "Surprise! Apple fanboy doesn't like Android," and you can just stop reading here.

KJMenuTableViewController - iOS Menus Made Easy

I have a new open-source library on Github for use by iOS developers: KJMenuTableViewController.

KJMenuTableViewController is an Xcode project that contains set of classes that simplifies the
creation of "menus" in iOS applications using UITableViewController.

The UITableViewController class is a generic mechanism for presenting a scrollable list of
rows of items. It is powerful and extensible, but it can be a chore to present a simple
list of button-like objects that react when tapped. One must provide implementations of several
methods of the UITableViewDataSource and UITableViewDelegate classes, each of which will
probably have a case statement to handle each of the individual items. It's not difficult, but it is
tedious and error-prone.

The KJMenuTableViewController classes simplify this usage case. One simply defines a subclass of
KJMenuTableViewController and overrides the viewDidLoad method to create sections and row items.
KJMenuTableViewController implements the table view delegate and data source methods to
appropriately display the sections and rows, and will take action when a row is tapped.

The code to be executed when an item is tapped are written as a block.
When the block is invoked, a KJMenuItemInvocation structure is passed to it. This structure
contains pointers to the menu item, cell, and controller, so there is no reason for the block
to retain any of these objects itself. (Beware of retain cycles if the block does reference
the menu item, cell, or controller.)

Beware the Lure of the iOS UIWebView

Apple's iOS SDK provides a class, UIWebView, that provides a simple way to display HTML content in an iOS application. Many apps use UIWebView to display web pages, online help, and other formatted content.

For the basic purpose of displaying HTML content, it works pretty well. However, as it appears to just be a wrapper around WebKit, one might be tempted to use it to try to implement a full-fledged web browser embedded in an application. Don't do this! UIWebView has many limitations that make it unsuitable for this purpose:

  • Many commonly used JavaScript functions, such as alert() and window.open(), don't work at all or only work in limited ways in a UIWebView. So many of the web sites one would try to visit do not work in a UIWebView.
  • There are limited hooks for customizing the behavior. There are a few delegate methods that notify your app when the web view starts loading or finishes loading, but you can't detect many of the events you'd really want to detect.
  • UIWebView does not send the same browser identification info that Mobile Safari does, so some servers will treat it as an unknown browser and return limited content.

Of course, some intrepid developers have found ingenious ways to work around some of these limitations. If you really want to try it, or if you are curious about what kinds of hackery are needed to use UIWebView as a web browser, check out these links:

The lesson I learned (after several hours of banging my head against the wall) is to pass web URLs over to Safari, rather than trying to display them in a UIWebView within my app. It's just not the right tool for this job.


Update (2011/10/1): My original post included this bullet point:

  • You can't control authentication. UIWebView can open an HTTPS connection, but if the server-side certificate is self-signed, there is no way to get it to ignore the certificate, and so it just fails with an error message.

I've been informed that this is not entirely true. It is possible to somehow "preconnect" to the server with an NSConnection, deal with authentication, and then pass the credentials to the UIWebView. Maybe someday I'll try to find the details of how to do that.

Syndicate content