Last week Microsoft published the first beta of Interactive Designer (a.k.a. Sparkle) so now all those that fear angle brackets can edit XAML via nice GUI editor.
Or not. I took a project I had developed in Visual Studio 2005 and opened it up in Sparkle and as soon as I clicked on the main window the app crashed. Repeatedly. I think this is the first time I actually used the button on the crash dialog and sent crash report to Microsoft. I am genuinely interested in seeing this tool mature but for now I'll stick (unfortunately) to XAMLPad.
The markup that crashes Sparkle is not complicated and actually works fine when you start the application. Unlike Sparkle, Visual Studio is not even able to show the markup in design mode and complains about some obscure missing property or something like that.
Luckily (to me at least) Avalon is easy to code even by hand so I'll continue to do just that. But I definitely look forward to future releases of this or any other GUI editor.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
Not so much along the lines of the previous post, I think I just had an epiphany I'd like to share.
Often to the question “how to design a good UI” one of the answers comes up that deals with complexity. Presumably, a good UI designer should be able to hide the complexity of a software solution from a user (unless a user is another software developer and having most of complexity exposed is A Good Thing, but that's a small percentage of the market and doesn't hold always anyway). This often assumes that in order to do so a good UI designer should make some sort of dual UI - simple version for regular users and complex one for advanced users.
I've been a subscriber of this philosophy for quite some time too. After all, some problems are really complex and the solutions are inevitably so too. Anyone can drive a car, but can they drive a space shuttle? I don't think so - space shuttle is so much more complicated to handle (but it can fly to space and back).
That said, most of the software isn't really a space shuttle and is more like a car, so it should be as easy to handle. The real solution is not to hide the complexity under the hood and expose a simple UI (but if that works, by all means go for it) but to redefine the problem itself so that it becomes simple (or at least less complex).
This is a lot easier said than done, but ultimately that's the core of our job as software engineers. We need to think of solutions that don't hide complexity, but implement it in such a way that the exposed parts are easy to wrap in a UI. Then almost anyone will be able to make a decent UI out of it. Note that this is subtly but distinctly different from hiding complexity - we design away the complexity in the first place. Actually, looking at the solution as a whole, if it solves the same problem as the solution that hides complexity, the best we can do is to refactor the solution so that the tip of it, visible to the user in the shape of UI, is simple. The sum of all parts of the solution is still as complex as before, but it is now easy to expose.
Because this is so much more work the developers usually go for the first option - make the advanced UI that exposes a million options and then allow the user to switch to the simpler view with less options. If you can't afford to refactor the solution and have to go this route, at least make sure that you pick as many reasonable defaults (reasonable as defined by the majority of your users, not by you) and that the simple UI isn't just a pure subset of the advanced UI with less controls on the screen.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
I still edit all of my (still experimental) Avalon, ahem, Windows Presentation Framework by hand, but I was curious to see how Microsoft planned to implement GUI editor for some of the container panels so I went and installed Cider (Microsoft has a code name for everything).
Something caught my attention as soon as I added my first DockPanel... Take a look at MaxHeight and MaxWidth properties - what's that? That my friend is Serbian for infinity :) Looks like Visual Studio decided to respect my regional settings for this one instead of drawing infinity symbol or something like that.
Totally useless but cool nonetheless ;)
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
...and I don't mean just computer User Interface (UI) designers - for designers of all things that interface with people.
Just yesterday I was uninstalling the old cooking top (the one we got with the apartment we rent) in order to install our new shiny Induction based cooking top (latest technology - a lot more energy friendly/efficient, nice flat surface, really fast and safe). Guess what - it took me about 2 hours to uninstall the old unit and about 15 minutes to install the new one.
Without going into much detail let me just say the following - the person(s) that designed the way that Whirlpool 332IX installs/uninstalls should end up in mini-hell where there's nothing to do but to endlessly install and uninstall said piece of cookingware. It should be quite obvious what went wrong immediately after the first attempt.
Kudos to the designer(s) of the new model 990BA. It is a breeze to install and I know for a fact that it will be trivial to uninstall when we move out.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
The best aspect of having an XBox (yes, I still have the "old" one) is the co-op. Even though we geeks have a reputation of being introvert (in my experience, this is generally true) that doesn't mean we are not friendly and don't like to hang out with other people now and then :) Especially if it's our geek friends doing geek stuff ;)
Playing computer/XBox games is fun, but going against the game with a friend in a co-op mode is more than twice the fun - I'd go as far as say it's fun squared. Unfortunately game developers do not seem to share my point of view as there are generally about 5% of games that offer good co-op mode. On a PC, this makes sense - it is hard to support more than one keyboard/mouse combo for a typical FPS, but on a console it's really easy - all consoles have at least 2 and often 4 controllers or more.
A good example would be Halo 2 - great game, even better game in co-op. Even better example is Splinter Cell Chaos Theory - there are separate levels for co-op play designed to accomodate two players and the story is slightly different than the single player story. But enough rambling - a friend is coming over to finish the remaining few Splinter Cell co-op levels...
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
According to all the statistics it is much more likely for your first business to flop than to succeed. This should not prevent you from trying, though. Just like Neo falling the first time - everybody falls the first time (comparison is great and is not my idea - saw it on some blog the other day, unfortunately forgot where).
More along these lines can be found in No one starts with a masterpiece. I'd like to add a bit to the theme... not only that (quote from the post) No one actually knows what they’re doing but also no one throws away their first product, even when it fails.
I cannot emphasize this enough. The work you do for your first product will be reused later, even if sliced into pieces and re-assembled into something completely different. No one works in vacuum - if nothing else, business contacts, payment processor, work habbits, and most importantly your source code will give you a big head start in your second business (unless you succeed the first time but then all this is irrelevant anyway :)). The experience you get while trying is absolutely crucial - it's very unlikely you'll repeat any of the mistakes you might have made on your first try.
In other words, just do it and worry later. Here's a motivational example - did you know that the company behind FolderShare (recently [November 2005] acquired by Microsoft) is the same one that used to do music sharing service Audiogalaxy? I remember downloading some of the music (illegaly!) over the Audiogalaxy during the early P2P days (when Napster still ruled). I think it is very reasonable to assume that P2P technology developed for Audiogalaxy wasn't just thrown away and that FolderShare is a direct descendant of that code.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
Continuing the topic of my earlier post, Ben responds at the bottom of the post:
Drazen wrote a good response to me in Quick, which is better suited for XML transformation: C++ or XSLT? It is nicely presented, but I've got to say it ultimately only makes the point here stronger. It is significant that he uses "EXSLT" to get the power function he needed. Though he tried to preemptively defend this decision, it is an example of how you are at the mercy of your XSLT component to implement an extension, and it stops my MXSML 4.0 test from working. His new XSL is half the lines and if I remove the power function (and ignore the incorrect line numbers) it runs as fast as my C++ example. But it looks like the line numbering in his solution still depends on a certain number of elements as I gather from the 6 in math:power(6, count($recurse)), whereas my C++ example can have any number of col elements in any number of column elements. Sure he can fix that too, but the fact that someone skilled with XSLT can improve this particular stylesheet does not prove the value of XSLT for this problem.
Ben is right on almost all acounts - I did make an oversight and implemented the solution assuming that the number of child elements of column is equal for all elements (original post has been modified to mention this and provide the fix). I don't agree that using EXSLT is unfair - it's like complaining that if you used hash_map in your C++ app you are relying on an extension (even though all vendors provide this).
Nevertheless, let's see what the problem really is here. The stylesheet is more complicated and required power function only to work-around an inherent design issue of XSLT as a language without side-effects to variables - once set, you can't change variable's value but that's exactly what I need to implement a counter. If the problem did not require the result rows to be numbered, things would have worked out perfectly.
But let's see what I can do to fix the stylesheet as is, using something other than power and not using EXSLT. Due to the wrong assumption about number of child nodes of column element, I can't use power anyway. What I need to do is to compute the product of number of child elements following the current node. In order to do so, I'll change the line that computes the increment to this:
<xsl:variable name="increment">
<xsl:call-template name="product">
<xsl:with-param name="nodes" select="$recurse"/>
</xsl:call-template>
</xsl:variable>
But where is the mysterious product template? It's in the separate XSLT file - it's just a utility function that computes a product of a value of some nodes, where “value” is defined in terms of the template you provide. Think of templates here as functions that call each other to compute something. Here's the definition of product:
<xsl:template name="product">
<xsl:param name="nodes"/>
<xsl:param name="result" select="1"/>
<xsl:choose>
<xsl:when test="not($nodes)">
<xsl:value-of select="$result"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="value">
<xsl:call-template name="get-node-value">
<xsl:with-param name="node" select="$nodes[1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="product">
<xsl:with-param name="nodes" select="$nodes[position() != 1]"/>
<xsl:with-param name="result" select="$result * $value"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Aha, it's getting complicated, you might say. True, but again think of this as a general purpose utility function that is reusable for other purposes as well and can be included in any stylesheet. Otherwise I can dismiss Ben's C++ solution for using a custom string implementation instead of CString :) Note the get-node-value template it depends on - that's the “value“ of node I just talked about. In this case the template boils down to this (should be replaced with a different implementation for each distinct purpose):
<xsl:template name="get-node-value">
<xsl:param name="node"/>
<xsl:value-of select="count($node/*)"/>
</xsl:template>
The resulting complete template is only 6-7 lines longer than the original (not counting utility template product). But it's still complicated for the beginner, and Ben is right - simple problems like this should have simple solution. I wouldn't be telling you all this if I didn't have one, would I? :)) Let's look again at the real problem here - all I need is a simple counter. The only reason I bothered with power and product was to avoid counting. But there's another way to avoid counting too: two-pass solution. Don't worry - it is as performant as the original solution and a few lines shorter (complete source presented for completeness):
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt">
<xsl:output method="text" omit-xml-declaration="yes" encoding="iso-8859-1"/>
<xsl:template match="columns">
<xsl:variable name="lines">
<xsl:apply-templates select="column[1]"/>
</xsl:variable>
<xsl:for-each select="ms:node-set($lines)/line">
<xsl:value-of select="concat(position(), .)"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="column">
<xsl:param name="running" select="''"/>
<xsl:variable name="recurse" select="following-sibling::*"/>
<xsl:for-each select="col">
<xsl:variable name="current_running" select="concat($running, ' ', .)"/>
<xsl:if test="$recurse">
<xsl:apply-templates select="$recurse[1]">
<xsl:with-param name="running" select="$current_running"/>
</xsl:apply-templates>
</xsl:if>
<xsl:if test="not($recurse)">
<xsl:element name="line">
<xsl:value-of select="concat($current_running, ' ')"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
First I create a temporary node set, and then output it out using the position of the nodes as a counter. I know - another extension (node-set). Hey, it works with MSXSL 4.0 so at least Ben shouldn't complain ;) Seriously, the only reason I am using the extension is because it is practically a mandatory extension for every decent XSLT processor as it rectifies what I consider a flawed spec for XSLT 1.0. The proof is in the XSLT 2.0 spec - if you remove the extension the stylesheet will work as-is with any 2.0 conformant XSLT processor (tried with Saxon).
I don't think this example proves that one should avoid XSLT. What is obvious though is that the mental shift required for an average developer when going from C++ to XSLT might indeed be too high. If you can't figure XSLT out, by all means use CMarkup or a similar library. But don't do it just because XSLT is different - there's value there too. If we'd all skip technologies and languages we are not familiar with we'd code most of the Web apps in assembler instead of PHP, Ruby or Python :)
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5
I'm sure you've seen this one before somewhere - it came to me while reading some Java book, of all possible places. One of the cooler uses of macros in C++ is to define a “forever” loop, like this:
#define ever ;;
// ...
for(ever) { /* code */ }
Helps readability of code - we all should agree by now that reading code is at least as important than writing it.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5