Running with Code Like with scissors, only more dangerous

19Feb/120

A brief detour: Dry rub for ribs

Posted by Rob Paveza

I have to admit: I'm excited. Tomorrow morning, I'll be putting my first ever dry rub on ribs. I've been looking forward to this because I've got a friend whose family is gluten-intolerant, and before he knew it, we always used to enjoy crock pot ribs with some store-bought K.C. Masterpiece honey barbecue sauce. Since they stopped eating gluten, we haven't really enjoyed ribs together. Not only that issue, but there's also the issue of actually just finding ribs when they're drowned in the sauce within the crock pot. So, for a while, I've been looking for a somewhat savory rub that I could make gluten-free that would be tasty. I think I've found it.

Apparently, John McCain has a fantastic dry rub that he uses. I'm going to adapt the recipe on that site a little bit: I have more ribs, and I think I can get a little bit more variety (and I'd like to have a little kick). So here are my ingredients:

  • 3 tablespoons kosher salt
  • 3 tablespoons garlic powder
  • 2 tablespoons black pepper
  • 1 tablespoon chili powder (I would have preferred cayenne pepper I think, but we didn't have any) - I'd like it to have just a little more punch than just black pepper would have
  • 1 orange, 2 lemons, and 1 lime, juiced

Otherwise, I'll follow the recipe as indicated: apply the rub all over the ribs, and then add the juice. Cook on low 8-10 hours.

I wanted to mix up the citrus a little. Citrus is generally interchangeable, but lime is my favorite citrus, and I wasn't willing to completely give up the sweetness of typical barbecue, so I thought the orange might be able to help add that a bit.

I will post some pictures and thoughts once they are cooked.

Tagged as: No Comments
19Feb/121

A Review of Balsamiq Mockups

Posted by Rob Paveza

Balsamiq was kind enough to provide me with a free license for Mockups a while back on the condition that I reviewed it. I'm embarrassed to say it is WAY longer than I would have expected if I had been the one providing the license. That said, I definitely still owe them the review, so I think I'd better get on it! (I had originally intended to do a videocast of using Mockups but I'm not particularly good at that sort of thing).

My daily job responsibilities have never been 100% on wireframing or feature design. Up until I was introduced to Mockups, I had tried out Axure RP Pro (I think around version 5), and during my time at Terralever, we used Omnigraffle extensively. I first was introduced to Mockups when we were partnering with MySpace on If I Can Dream. I was impressed initially by the extremely rapid prototyping that we were able to do as a collaborative team. I had spent probably about 30 hours doing the initial Facebook-based proposal, which was, in fairness, far more extensive than the MySpace integration ended up being (sorry JT). That said, we were able to put Mockups up on the projector and it was really easy to make some interesting UI components very quickly.

Since then, I've used Mockups at Terralever as well as with my own consulting business. Generally, I've found that Mockups is ideal when I'm looking for:

  • Very rapid prototyping, to help conceptualize something that I'm actively coding and just need to give myself a fixed visual.
  • Prototypes that I'm going to deliver in PDF format, because of the automatic internal linking it provides (more later).
  • Any kind of prototypes that are going to be "internal only." If I need to perform a "real" usability consultation, I prefer Omnigraffle; I think that what I can find in Omnigraffle generally looks a little more polished.

The Prototyping Experience

Absolutely exceptional. To be honest, I think it's the best aspect of Mockups in terms of its speed advantage. If the components are there in the library, it's incredibly fast to go from nothing to something good. Let's take a simple example of a common navigation element: the tabs list. Drag-and-drop from the library onto a fresh canvas, and this is what we're presented with:

You can see that there are four items in a comma-delimited list. What could be more intuitive than that? Well, I'll type some comma-separated items in and then hit enter:

Okay, that's pretty good; but I think I should be able to have the Mockups tab selected. Lo and behold, the very simple property editor window saves the day:

You can see in this image that Mockups is selected (and it is highlighted in the "Selected" field of the property editor as well). But what's also very neat about this control (and other similar ones) is the "Links" property set. See how there's a field for each one of the tabs that I created? Every one of them can link to another Mockup in the same folder. When I choose to export them to PDF, those links will be live, and I'll be able to navigate between mockups by clicking on the linking element. In my opinion, it's one of the coolest interactive features, and it's readily surfaced. (I suspect that there may be similar features in Omnigraffle but I've never used them if they do exist).

Also very cool for preserving your "sketch" feel is the ability to "Sketchify" (okay, that term isn't in the UI, but it fits) any bitmapped image you drop into the app. It's actually very good and accurate. Take a look at this (original images courtesy of Amazon and Google Shopping).:

This is tremendous for those of us who want to use images to get the point across but are terrible at using Photoshop for anything other than taking someone else's image and using the "Slice" tool.

I've found the locking and ordering mechanism to be very intuitive. Mockups is also very good about letting you select the element you want with the right-click menu, which lets you select down the visual hierarchy even if the element you're trying to get (for instance, a Web Browser surface) is occluded by something else.

The Library

The UI library is adequate. There have been times where I've longed for the ability to add a control to it, which invariably leads me to creating a "Library" mockup that contains my custom "controls." The drawback to this model is that you don't get the very nice programmed editing capabilities. For example, suppose I wanted to wireframe the feature that Facebook uses when you've auto-completed a friend (you know, the highlighted background with an X to the right of the text). I can make something that looks like it. However, I don't get the great features of the intrinsic controls: I can't make only the text editable, and I can't make the X hotlink to another wireframe. There may be a way to develop these kinds of extensions, but I haven't found it. The lack of extensibility in this sense is a detractor compared to Omnigraffle (compare Graffletopia), but at the same time, it's a good challenge to be able to do more with less. (I love Graffletopia's diversity in components, but it can also give you a library that is much, much too large).

Still, I think that, while there have been times that I've really wished for some specific controls, it's generally given me what I've needed. And when it didn't have quite what I needed, I was able to fake it.

That said, there is one thing that stands above the others: the Text Paragraph control:

You can see inline the italics, hyperlink, and bold format specifiers that can automatically be applied. I've found this enormously useful and I think the inline links are particularly handy (it's not something you see everywhere). But without a doubt, the best part is that you can get them while you're typing: no need to stop and use the mouse to select a text range just to get a special format like that.

How it stacks up

I realize that as someone who almost exclusively develops on the Microsoft stack, I should probably at least occasionally wireframe in Expression Blend's Sketchflow feature. I'm mildly ashamed to admit that I've never tried it; I think I'm afraid that if I start working in Sketchflow I'll get the urge to do some real programming, or I'll spend too much time on an animation and not get the actual prototyping done. So with that in mind, I'm going to compare it to Axure and Omnigraffle, because those are the other two tools I've used.

Axure: Mockups, even the first time I saw it, was miles ahead of Axure in appearance. Noted that it's probably 2 years ago that I tried Axure, but it sometimes felt like I was literally working with the .NET Windows Forms or Web Forms designer controls (the radio buttons stand out in my mind as looking like they were pure Windows-based controls). I have seen the end-result of some Axure work recently and was a bit impressed (I think they've added some sketchlike appearance support in a recent version). That said, I get the general impression that Axure's prototypes are meant to look a bit more like the real thing than wireframes that you might generate using Mockups or Omnigraffle.

Omnigraffle: Like I noted above, I tend to like Omnigraffle when I'm consulting for a client. Mockups produces visuals that are very sketch-like in their appearance, and while this is generally a Good Thing, sometimes that rounded edge or drop-shadow that you can include in Omnigraffle makes the product really pop. Still, Omnigraffle is only available on Mac and iPad, and while I have an iMac, I tend to be developing in Windows. The reboot required to go into OS X makes it cost-prohibitive to use when I'm going to be the consumer of the wireframes. Mockups, being an Adobe AIR application, can run on either platform. As a result, when I need to give myself some visual guidance, I tend to do my rapid prototyping in Mockups.

One note: Since installing Mockups on my new laptop, I was surprised to see that Comic Sans is no longer the default font. In some ways this saddens me. I realize that most customers were probably unhappy with that as the default because it made them hesitant to show their mockups to customers. I thought that it was a bit charming in its own way - another not-so-subtle reminder to "not take this visual too seriously". Oh well :)

Thanks, Balsamiq, for the Mockups license! Keep the goodness coming!

16Feb/120

Bridging the gap between Jurassic and the DLR, Part Two

Posted by Rob Paveza

Part Two: A More Complete Object Model

Once I started implementing the rest of the object model, things started coming together very well.

Let's take a look at the rest of the ObjectInstance implementation:

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            return TryCallMemberFunction(out result, binder.Name, args);
        }

        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            if (binder.ReturnType == typeof(string))
            {
                result = this.ToString();
                return true;
            }
            else
            {
                try
                {
                    result = Jurassic.TypeConverter.ConvertTo(this.engine, this, binder.ReturnType);
                    return true;
                }
                catch
                {
                    result = null;
                    return false;
                }
            }
        }

        public override bool TryDeleteMember(DeleteMemberBinder binder)
        {
            return Delete(binder.Name, false);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            this.FastSetProperty(binder.Name, value, PropertyAttributes.FullAccess, true);
            return true;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = GetNamedPropertyValue(binder.Name, this);
            if (object.ReferenceEquals(null, result))
                return false;

            return true;
        }

For FunctionInstance:

        public override bool TryInvoke(System.Dynamic.InvokeBinder binder, object[] args, out object result)
        {
            try
            {
                result = CallLateBound(this, args);
                return true;
            }
            catch
            {
                result = null;
                return false;
            }
        }

For ArrayInstance, things were a little more interesting. JavaScript doesn't support multidimensional arrays (as in C#, where you can access something via someArr[1,5]). However, it's important to consider the type. Fortunately, Jurassic provides that as well, fairly easily.

        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            Debug.Assert(indexes != null && indexes.Length > 0);

            result = null;

            if (indexes.Length > 1)
                return false; // multi-dimensional arrays are not supported.

            if (object.ReferenceEquals(null, indexes[0]))
                return false;

            Type indexType = indexes[0].GetType();
            if (indexType.IsEnum)
            {
                indexType = Enum.GetUnderlyingType(indexType);
            }

            if (indexType == typeof(byte) || indexType == typeof(sbyte) || indexType == typeof(short) || indexType == typeof(ushort) || indexType == typeof(int) || indexType == typeof(uint))
            {
                uint index = unchecked((uint)indexes[0]);
                try
                {
                    result = this[index];
                    return true;
                }
                catch
                {
                    result = null;
                    return false;
                }
            }
            else
            {
                string index = indexes[0].ToString();
                try
                {
                    result = this[index];
                    return true;
                }
                catch
                {
                    result = null;
                    return false;
                }
            }
        }

        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {
            Debug.Assert(indexes != null && indexes.Length > 0);

            if (indexes.Length > 1)
                return false; // multi-dimensional arrays are not supported.

            if (object.ReferenceEquals(null, indexes[0]))
                return false;

            Type indexType = indexes[0].GetType();
            if (indexType.IsEnum)
            {
                indexType = Enum.GetUnderlyingType(indexType);
            }

            if (indexType == typeof(byte) || indexType == typeof(sbyte) || indexType == typeof(short) || indexType == typeof(ushort) || indexType == typeof(int) || indexType == typeof(uint))
            {
                uint index = unchecked((uint)indexes[0]);
                try
                {
                    this[index] = value;
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            else
            {
                string index = indexes[0].ToString();
                try
                {
                    this[index] = value;
                    return true;
                }
                catch
                {
                    return false;
                }
            }
        }

        public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes)
        {
            Debug.Assert(indexes != null && indexes.Length > 0);

            if (indexes.Length > 1)
                return false; // multi-dimensional arrays are not supported.

            if (object.ReferenceEquals(null, indexes[0]))
                return false;

            Type indexType = indexes[0].GetType();
            if (indexType.IsEnum)
            {
                indexType = Enum.GetUnderlyingType(indexType);
            }

            if (indexType == typeof(byte) || indexType == typeof(sbyte) || indexType == typeof(short) || indexType == typeof(ushort) || indexType == typeof(int) || indexType == typeof(uint))
            {
                uint index = unchecked((uint)indexes[0]);
                return Delete(index, false);
            }
            else
            {
                string index = indexes[0].ToString();
                return Delete(index, false);
            }
        }

I did add one set of precompilation directives so that I could modify ScriptEngine with one little item:

        public 
#if SUPPORT_DYNAMIC
            dynamic
#else
            object 
#endif
            GetGlobalValue(string variableName)
        {
            if (variableName == null)
                throw new ArgumentNullException("variableName");
            return TypeUtilities.NormalizeValue(this.Global.GetPropertyValue(variableName));
        }

With that gem, we're in good shape. I'll update the test program; let's take a good look:

    class Program
    {
        static void Main(string[] args)
        {
            ScriptEngine engine = new ScriptEngine();

            engine.SetGlobalFunction("write", (Action<string>) ((s) => { Console.WriteLine(s); }));
            
            engine.Execute(@"
var a = {
    A: 'A',
    B: 20,
    C: function() { return 'Hello'; }
};

function double(val)
{
    return val * 2;
}

var array = [1, 5, 9, 13, 21];
");
            dynamic obj = engine.Evaluate<ObjectInstance>("a");
            Console.WriteLine(obj.A);
            Console.WriteLine(obj.B);
            Console.WriteLine(obj.C());
            obj.D = "What's that?";

            Console.WriteLine("C#: " + obj.D);

            engine.Execute(@"
write('JavaScript: ' + a.D);
");

            dynamic dbl = engine.GetGlobalValue("double");
            Console.WriteLine(dbl(20));
            Console.WriteLine(dbl.call(null, 20));

            dynamic array = engine.GetGlobalValue("array");
            Console.WriteLine(array[2]);

            Console.ReadLine();
            
        }
    }

Output is happily correct:

A
20
Hello
C#: What's that?
JavaScript: What's that?
40
40
9

Particularly neat about this implementation is that the calls automatically recurse. Note that I use the intrinsic JavaScript call method on the Function instance (of dbl). This implementation covers a whole bunch of typical scenarios and use-cases, and I'm happy to see that it has worked out fairly well thus far.

One item I've found is that there's a TypeLoadException when targeting .NET 4. This has something to do with a new CAS policy in .NET 4. For now, applying this attribute to the test program as well as the library will resolve the issue, though I don't intend for it to be long-term:

[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]

Next time, we'll do some more fit and finish, with precompilation constants and a security review.

14Feb/120

Bridging the gap between Jurassic and the DLR, Part One

Posted by Rob Paveza

Part One: ObjectInstance derives from DynamicObject

A while back I posted that I was joining the Jurassic team; Jurassic is an open-source JavaScript engine for .NET. If you've ever gone through the long search for a JavaScript implementation on .NET (other than JScript.NET, of course), there are a bunch of incomplete implementations, and if you're lucky enough to find the blog about the Microsoft project of JScript running on the DLR (once called Managed JScript), you'll find that it was an implementation that was specifically designed to give design feedback on the DLR itself, and was not planned to be carried forward into production. Personally I think that's too bad, but I'm happy to see a couple of projects (notably, Jurassic and IronJS) that have stepped up to fill the gap.

I had considered implementing IDynamicMetaObjectProvider, but inheriting from DynamicObject seems to be a better design decision all-around. Since all of the other JavaScript objects inherit from ObjectInstance, it's a simple matter of overriding its virtual methods instead of creating a new implementation of DynamicMetaObject for each class in the hierarchy.

I've created a new library project within the solution as well as a simple testing project to advise on the API as well as to step into my DynamicObject overrides. Here are some simple components:

// These are new:
using System.Dynamic;
using System.Diagnostics;

// This is updated
    public class ObjectInstance
        : DynamicObject
#if !SILVERLIGHT
        , System.Runtime.Serialization.IDeserializationCallback
#endif
    {

// The class exists as normal
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = GetNamedPropertyValue(binder.Name, this);
            if (result != null)
                return true;

            return false;
        }

        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            try
            {
                result = CallMemberFunction(binder.Name, args);
                return true;
            }
            catch
            {
                result = null;
                return false;
            }
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            this.AddProperty(binder.Name, value, PropertyAttributes.FullAccess, true);
            return true;
        }

    }

This is the source of the test application. It's very straightforward:

        static void Main(string[] args)
        {
            ScriptEngine engine = new ScriptEngine();

            engine.SetGlobalFunction("write", (Action<string>) ((s) => { Console.WriteLine(s); }));
            
            engine.Execute(@"
var a = {
    A: 'A',
    B: 20,
    C: function() { return 'Hello'; }
};
");
            dynamic obj = engine.Evaluate<ObjectInstance>("a");
            Console.WriteLine(obj.A);
            Console.WriteLine(obj.B);
            Console.WriteLine(obj.C());
            obj.D = "What's that?";

            Console.WriteLine("C#: " + obj.D);

            engine.Execute(@"
write('JavaScript: ' + a.D);
");

            Console.ReadLine();
            
        }

We create a global function 'write' which writes a string to the console. Then we create a global object a with properties A, B, and C. We then use C# to retrieve the value of this object as a dynamic. This is what provides us access to the DynamicObject's overrides intrinsic within C#'s support of the DLR. We then access each property (which each return a dynamic) and, happily because of Jurassic's automatic conversion of primitives to their respective .NET types, when these values are returned as dynamic, they can be automatically converted to their appropriate types for their Console.WriteLine parameter. You can see that we invoke TryGetMember on A and B, TryInvokeMember on C, and TrySetMember and then TryGetMember on D.

OK, it's late, so I'm not going to stick this out anymore right now. I'm not even sure if the previous paragraph was particularly coherent. :-)

There's a lot to update: it doesn't support case-insensitive languages (like Visual Basic), it's not particularly good at error checking, and I haven't dealt with any other components yet. The good news is that it seems like we should be good to go for the rest of the components.

Next time, we'll look at other classes, like ArrayInstance, FunctionInstance, and more.

6Feb/120

In a disconnected world, robust code is crucial

Posted by Rob Paveza

Probably 99.99% of HTML applications and websites are served over HTTP exclusively. (I'm referring here to HTTP as a transport protocol, not HTTP vs.HTTPS, for example, and I realize that HTTP is an application-layer protocol according to OSI; but developers generally treat it as an abstraction for "the network"). As anybody who has done web programming knows, HTTP is a stateless protocol; that is, it's based on a request-response model, and in general, one request has no knowledge of previous requests. This has posed some challenges for web developers over the years, and some brilliant abstractions of state on top of the statelessness have been devised.

The hard part now, though, isn't to deal with statelessness. It's dealing with the request-and-response model.

All network communication is inherently request-and-response. There are some applications that utilize full-duplex communications to get around that (think of chat software), but for the most part, that isn't really available behind the firewall. Web sockets are still yet to be standardized (and there are some questions about long-term compatibility with WebSocket-ignorant proxies). And typically, corporate firewalls say no to outbound connections except on ports 80 or 443. Some applications (think Meebo) have been able to get around this limitation by cleverly using long-timeout delays on AJAX requests. The client makes a request to the server, and the server either responds immediately (if an event is in queue) or holds the request for 30-90 seconds to see if an event comes in. I even did this once myself with good success, although I never took that app into production. (There was also some question about the total # of clients an ASP.NET server could sustain whilst holding threads in that way).

In many respects, Windows developers haven't had to deal with this. We could issue synchronous requests, and the UI would stand still for a second, and either it would work or it would fail. But usability concerns over this process, as well as issues with high network latency (imagine pressing the "Submit" button and having to wait 20 seconds while your app freezes - by then, I've force-closed the app) have seen platform providers decree that asynchrony is the only way to go.

HTML isn't the only application provider dealing with this limitation. Adobe Flash has long had an asynchronous-communication-only model, Microsoft Silverlight has also carried on this principle; of course, these two applications have lived predominantly in browsers, where a hanging UI probably means interfering with other apps as well as the one making the request. Interestingly, WinRT - the Windows 8 developer framework - is also going to mandate an asynchronous model, following in the Silverlight-based foodsteps blazed by Windows Phone 7.

So as we trek out into the world of asynchrony, well, we have a whole mess of questions to deal with now:

  • If there's an error, does it show up in the calling method or in the callback method? Does it even show up?
  • Does a network (transport-level) error surface differently than an application error? What if the server returned an HTTP 403 Forbidden response?
  • What are all of the different kinds of errors that can crop up? Do I need to handle SocketException or is that going to be abstracted to something more meaningful to my application?
  • What do I do if a network error comes up? Do I assume that I'm offline, panic, and quit? What if my application only makes sense "online"?
  • Do I surface an error to the customer? Silently fail? I might generally fail silently if I'm a background process, but then again, what if it's an important one? What if the customer thought he was saving his draft while all along it was offline, and then the customer closes the browser?
  • During the async operation, should I show the user a timeout spinner or something to that effect?
  • How should I design my async operations? For example, consider a Save operation. Should I capture all of my state at once and send it off, and let the user immediately keep working? Should I make the user wait until saving completes? Should I even use Save, or automatically save whenever something changes?
  • If I use auto-save, how do I handle undo? What if I want to undo between sessions? Is there a way to go back if the hosting application crashes? (Worst case scenario: the user accidentally hit Select All, Delete and then the browser crashed after the auto-save).

This merely scratches the surface of the kinds of questions we'll need to begin asking ourselves. It doesn't even deal with the difficulties of programming asynchronously, which C# 5 is going to deal with extraordinarily, but many developers will be unable to take advantage of these updates. For example, suppose I have a widget on my page that monitors the status of a long-running server-based process. I need to have JavaScript on my page that monitors that process and updates my widget accordingly. Should I:

  • Write a singleton object? This might be easier and afford strong member protection, but I can only have one widget, unless I somehow differentiate between them and multiplex, which can become hairy quickly.
  • Should the monitoring function accept a callback, or should it be event-based, so that multiple subscribers can listen? (Maybe an event-based model offers some interesting ways to deal with the complexities of a singleton?)
  • Should the widget manipulate the view directly, or should I write separate code that handles the view based on the state of the object (or objects)?

The list goes on.

We're moving faster and faster into an asychronous world. It is already happening, and we as developers need to be prepared to handle these difficulties. We also need to understand how to communicate these kinds of questions to our business analysts, our supervisors, and our customers. We need to be able to equip ourselves to ask the right questions of our customers, so that when it's time to make a decision, we have the information we need.