Nerdy tidbits from my life as a software engineer

Friday, May 29, 2009

Why I’ll Never Be A ‘Web Guy’

If popular culture is right, then I’m in for a disappointing career.  That’s because most people think that “everything is moving to the web,” and if that’s the case, then I can’t imagine being happy as a software engineer for the rest of my life.  So for my sake, I really hope everybody’s wrong.

I’m continually bombarded with questions from friends and other folks why I don’t want to work for an Internet company.  Most of them don’t understand.  When they look around at innovation in the software industry, they see cell phones and flashy web pages.  Nobody sees the awesome stuff going into the .NET framework, or, sadly, the amazing things you can develop on top of it (where are all those awesome WPF applications I’ve been waiting for?).  There’s a reason I work where I do.  As far as I’m concerned, the people I work with are doing the most innovative and amazing things on the planet.  What a thrill it is to be a part of it.

But why not the Internet?  The reason is that it’s the most aggravating place in the world to write commercial software for.  You have, off the top of my head, 4 major web browsers to deal with across at least two operating systems.  Each of these scenarios requires its own set of tests, and each browser will behave slightly differently depending on what OS it’s running on and what browser version it is running.  And then there’s mobile.  Want your website to look good on a cell phone?  Have fun: now you get to render a different page for every cell phone model in existence.  And just in case this wasn’t unpleasant enough, the debugging and diagnostic tools for most of these environments are non-existent.  That means you get to guess why a page renders funny or a random JavaScript error occurs, because you really have no way of figuring it out in a procedural, and scientific way (get ready for liberal use of Window.Alert).

Most of us have gotten used to the civilized world where we have compilers, IDEs, object orientated languages and debuggers.  We have strong-typing, class inheritance, and plenty of system resources at our disposal.  It’s a challenging place to be.  We can write things to disk, spawn multiple threads and render in 3D.  There’s no limit to what we can do.  And yet, most people seem to want to program in a limiting box called a web browser in a ‘language’ called HTML.

But then, that’s just it, isn’t it?  The reason most people want to program for the web is that they’re not smart enough to do anything else.  They don’t understand compilers, concurrency, 3D or class inheritance.  They haven’t got a clue why I’d use an interface or an abstract class.  They don’t understand: virtual methods, pointers, references, garbage collection, finalizers, pass-by-reference vs. pass-by-value, virtual C++ destructors, or the differences between C# structs and classes.  They also know nothing about process.  Waterfall?  Spiral?  Agile?  Forget it.  They’ve never seen a requirements document, they’ve never written a design document, they’ve never drawn a UML diagram, and they haven’t even heard of a sequence diagram.

But they do know a few things: they know how to throw an ASP.NET webpage together, send some (poorly done) SQL down into a database, fill a dataset, and render a grid control.  This much they’ve figured out.  And the chances are good it didn’t take them long to figure it out.

OK, so that’s not an entirely fair accusation to make.  Of course there are smart people who like to work on the web, and who find challenging things about it.  But I would argue that most people aren’t in this category.  For proof, try interviewing people who have lots of web experience, and contrast them with people who have lots of application experience.  In every case I’ve seen, candidates with application experience are often far better engineers than candidates with lots of web expertise.

So forgive me for being smarmy and offensive, but I have no interest in being a ‘web guy’. And there are two reasons for this.  First, it’s not a challenging medium for me.  And second, because the vast majority of Internet companies are filled with bad engineers – precisely because you don’t need to know complicated things to be a web developer.  As far as I’m concerned, the Internet is responsible for a collective dumbing down of our intelligence.  You just don’t have to be that smart to throw up a webpage.

So I really hope everybody’s wrong and everything doesn’t ”move to the web.”  Because if it does, one day I will either have to reluctantly join this boring movement, or I’ll have to find another profession.

Update 8/17/2009 – In response to a plethora of criticisms, especially one by the esteemed Jeff Atwood, I have posted a reply on the blog.  I don’t expect it to please everybody, but it will hopefully clarify what I was intending to say the first time around.

Wednesday, May 20, 2009

Annoying Gotcha #230

Ack, is this annoying.  The following code will almost certainly cause problems for you if you’re not careful:

using (XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open)))
{
  ...
}

Why does this cause problems?  Because the default XmlReaderSettings passed into the Create overload does not have the CloseInput property set to true.  This means that the file handle is not disposed of at the end of the using block – and it means that some other program, later on, can very easily run into IOExceptions when it tries to open the same file and gets blocked because another program never closed a file handle.

Of course the way around this is easy:

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;

using (XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open), settings))
{
   ...
}

But the amount of time I’ve wasted in the last few days figuring out what’s going on before I was reminded that this is not the default behavior is rather depressing.  Why this isn’t the default setting, I can only guess.  I expect that when a stream is disposed, every stream that it decorates is also disposed.  Hence, passing in an XmlSettings object shouldn’t be necessary.  reader.Dispose() implies that the stream passed into the reader is also disposed.

But maybe what aggravates me the most is inconsistent behavior.  Most streams close their inner streams when they are disposed.  So why should XmlReader be any different?

Wednesday, May 13, 2009

Styling a Window Background With a Logo

I finally have a chance to get working with the WPF again.  It’s been a long time, and it’s funny how quickly you both forget and remember things.  A lot of time all I need is a quick look at a reference book and my memory kicks in.  And then there are those things that you wonder how you ever understood in the first place.

I had a friend of mine whip up a simple logo / icon for my current project.  It’s super slick looking, and I want to get it into whatever windows and dialogs and webpages that I can.  Nice UI’s make your work look professional, and if there’s one thing I’ve learned about software, it’s that first impressions make a lasting impact.  All it takes are a few wiz-bang, flashy effects and your customers are instantly impressed.  Of course, you still need to deliver…but that’s another issue.

So I had a great idea to use the logo as the background for all of my windows by using some styles and a VisualBrush.  It’s funny how a seemingly simple project could wrack your brain for a few hours.  The main problem was that, for some reason, there is no trivial way to set the filler background color for a VisualBrush, and so it defaults to black.  So say, for example, that your logo .xaml resource is ~150 x ~76.  What you want is for the visual to be drawn in the center of the window, uniform scaled (so that there’s no distortion), with the rest of the background color set to whatever other color you want.  Since it’s very unlikely that your windows will be sized to exactly fit the 150 x 76 dimensions of the logo, there will inevitably be some dead space in your window.  And what you can’t have is for the background color of the logo to be different from the background color of that dead space.

The other alternative is to scale your logo to either Fill or UniformToFill.  But neither of those options are ideal.  One distorts the logo, and the other will end up clipping much of it off screen.  So you end up having to do some canvas-within-a-canvas scaling magic to get it working properly:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- The logo was exported into .xaml from Adobe Illustrator -->
    <!-- It is defined in a ResourceDictionary as a Canvas with x:Key="Logo" -->
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="..\ResourceDictionaries\Logo.xaml" />
    </ResourceDictionary.MergedDictionaries>

    <Style x:Key="WindowStyle"
           TargetType="{x:Type Window}">
        <Setter Property="Background">
            <Setter.Value>
                <VisualBrush Stretch="UniformToFill">
                    <VisualBrush.Visual>
                        <Canvas Width="100"
                                Height="100" 
                                Background="White">
                            <Canvas Canvas.Left="2"
                                    Canvas.Top="2"
                                    Width="96"
                                    Height="96">
                                <Canvas.Background>
                                    <VisualBrush Visual="{StaticResource Logo}"
                                                 Stretch="Uniform"
                                                 Opacity=".25" />
                                </Canvas.Background>
                            </Canvas>
                        </Canvas>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Icon"
                Value="..\Logo.ico" />
    </Style>

</ResourceDictionary>

This looks trivial, but the trick was to realize that the logo’s canvas needed to be placed inside another canvas that was UniformToFill.  Any other value and the logo ends up distorted.  For instance, if the outer VisualBrush is set to Fill, then the inner logo ends up being stretched even though it’s set to Uniform.  Setting it to None or Uniform doesn’t work either, because the result is black-colored dead-space.  But setting the outer to UniformToFill causes it to expand to cover the entire background of the window, while the inner canvas’ content is resized to fit the space it’s given.

There may be a better way to do this, I don’t know.  But for now the logo is looking pretty slick.  So I’m going to keep it this way.