I Build Software Like I Build Muscle
2011-11-15
Actually, I quit building muscle while I was in college, but I realized today that the majority of my (productive) software development is done with a buik/cut strategy.
If you're uninitiated into the world of body building, it is common to first "bulk", where you eat heavily to gain mass and muscle, and then follow it up with a "cut" where you focus on reducing weight to get your target shape. I don't know why this strategy works for body builders and I've never tried it myself, but there are definite correlations to my development style.
I have a secret, which I now give to the internet because it feels like it's impossible to not get a job in this market. No I don't know why but it's true. If you don't believe me, add "XAML" to your LinkedIn profile, change your address to Seattle and count the number of days before you get a job interview. Anyway, back to the secret: I don't feel like I'm smart enough for most design patterns. Whenever I start a new project at the beginning I tell myself "this time, we're going to give NEWTRENDY design pattern a try". And I don't get anything done. Ever. Weeks pass and all I have to show for it is the same singleton pattern and static constructor.
So how is bulk/cut a design pattern? By having long periods of feature development (the bulk) following by short periods of bug fixes (the cut). If you're bulking, don't stop to write unit tests. Don't build and run a manual test. Don't stop to remove debug warnings, don't even stop to fix build errors. Just add every feature you can think of that you know your users will ask for at some point. I had a conversation with a friend today, and he said "The best way to avoid bugs is to never code them." While I agree with him completely, my response is "who cares, fixing bugs is easy". And it is, for me it always takes less time to identify a bug than it does to get over the paralysis of deciding how to avoid it. So you get your features in, then you cut. Fix the bugs in a large sweeping gesture, then if your shit still doesn't work, cut the feature entirely. Or push them to 1.1.
It's News to Me, Microsoft Employees Like bing
2011-4-12
I had dinner with a couple Microsoft employees last night. There was no official business, just a couple of mix attendees relaxing after our flight. I was surprised to hear two things from them, the first was that they were excited about their company's leadership and direction, and the second was that they actually thought bing was a good search engine.
I don't disagree with either assertion, but various former MSFTs seem to paint a different picture about internal politics and backbiting. The revelation about bing was the more surprising of the two, and their explanation of the situation pretty much summed up my feelings: "It's a great search engine, but if I hadn't been asked to switch, I wouldn't have." They went on to say that bing's daily image was the biggest draw for getting their parents to switch to bing. It will be interesting to see how Microsoft pursues the search space at MIX this year.
Improved Silverlight Debugging in FireFox
2010-11-18
I'm a fan of Silverlight and the Microsoft stack, but when it comes to browsers I think FireFox is king. Paired with FireBug's javascript console and network traffic monitor, it is an extremely powerful combination for development. Since I work almost exclusively in Silverlight I find that I hit Ctrl-F5 hundreds of times a day and my browser window generally looks something like this:

As a keyboard addict, I would normally hit Ctrl-W ten times to quickly close all those extra windows, but herein lies the problem. When a Silverlight embed is focused, none of those Key Presses bubble up to the browser window. So now I have to manually click each 'x' to close those windows. Similarly, when I have rebuilt my code in Visual Studio and want to quickly reload the page by hitting F5 and... get nothing. Or when I'm trying to verify my resources are loading correctly and need to bring up the FireBug console quickly before the xap loads: F12 to no effect. These are some of the most annoying parts of my job (yes, I have it pretty good).
Solving the refresh part was easy enough, just add HtmlPage.Window.Eval("window.location.reload();");. This works in Chrome and FireFox. F5 always worked in IE8 and is not a concern. Solving the other problems requires somehow restoring focus to FireFox. I noticed that HtmlPage.Document.Body.Focus() works as long as there is at least one focusable element on the page (like a textarea or a button). The test page generated by Visual Studio doesn't and I don't create Web projects until I need them, so I kept looking. I came up with the following Javascript function:
function HtmlFocusManager() {
var list = document.getElementsByTagName('input');
if (list == null || list.length == 0) {
var elem = document.createElement('input');
elem.setAttribute('type', 'button');
elem.setAttribute('style', 'position:absolute; margin:-5000px 0 0 0;');
document.body.appendChild(elem);
elem.focus();
} else {
list[0].focus();
}
document.body.focus();
}
This detects if an input is on the page, and if none is found it inserts a new one. It then apply some CSS rules to position it offscreen. Finally, we need to detect the key presses in Silverlight and call the Javascript method. I wrote up this simple static class to do this:
using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Input;
namespace Pop.Silverlight
{
public static class HtmlFocusManager
{
static bool _isCtrlDown;
static bool _isHtmlFocusManagerEvaluated;
public static event EventHandler PageFocused;
static void OnPageFocused()
{
_isCtrlDown = false;
if (PageFocused != null)
{
PageFocused(null, null);
}
}
const string HtmlFocusManagerMethod = @"function HtmlFocusManager() {
var list = document.getElementsByTagName('input');
if (list == null || list.length == 0) {
var elem = document.createElement('input');
elem.setAttribute('type', 'button');
elem.setAttribute('style', 'position:absolute; margin:-5000px 0 0 0;');
document.body.appendChild(elem);
elem.focus();
} else {
list[0].focus();
}
document.body.focus();
}
";
public static void Initialize()
{
var ui = Application.Current.RootVisual as UIElement;
if (ui != null)
{
ui.KeyDown += InputKeyDown;
ui.KeyUp += InputKeyUp;
}
}
static void InputKeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Ctrl:
_isCtrlDown = false;
break;
}
}
static void InputKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Ctrl:
_isCtrlDown = true;
break;
default:
break;
}
var keyVal = (int)e.Key;
if (e.Key == Key.F5)
{
HtmlPage.Window.Eval("window.location.reload();");
OnPageFocused();
}
else if (
e.Key == Key.Escape ||
keyVal >= 56 && keyVal <= 67 || // function keys
(_isCtrlDown && (e.Key == Key.W || e.Key == Key.Tab || e.Key == Key.T))
)
{
if (!_isHtmlFocusManagerEvaluated)
{
HtmlPage.Window.Eval(HtmlFocusManagerMethod);
_isHtmlFocusManagerEvaluated=true;
}
HtmlPage.Window.Invoke("HtmlFocusManager", null);
OnPageFocused();
}
}
}
}
Finally, drop the following bit of code in Application_Startup:
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
HtmlFocusManager.Initialize();
}
It's not quite a perfect solution though, because you will have to hit the desired key twice for it to take effect. What are the next steps? Take this code, put it in all you Silverlight applications, and spread the word. Also, this solution doesn't work in Chrome, so if you have any ideas, please leave a comment below.
Quick Fix for Silverlight HyperlinkButton Rendering
2010-9-3
Text rendering has always been Silverlight's dirty little secret. For every major release I hope that maybe this time fonts won't look terrible. Unfortunately as of 4.0, there are still a lot of improvements that must be made before Silverlight text will match the quality and readability of Flash. Robby Ingebretsen gives some helpful tips that can improve smoothness in Silverlight 4. But one of Silverlight's most basic controls continues to look terrible:
Hover your mouse into the control area, and notice how certain characters appear more blocky (h,p,n) while others get fuzzy (H,l,i). This is totally unexpected since all that's changing is the underline, so let's look at the ControlTemplate for to see what's going on.
<ControlTemplate TargetType="HyperlinkButton">
<Grid Background="{TemplateBinding Background}" Cursor="{TemplateBinding Cursor}">
<TextBlock x:Name="UnderlineTextBlock" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Text="{TemplateBinding Content}" TextDecorations="Underline" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<TextBlock x:Name="DisabledOverlay" Foreground="#FFAAAAAA" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Text="{TemplateBinding Content}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Canvas.ZIndex="1"/>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="FocusVisualElement" IsHitTestVisible="false" Opacity="0" Stroke="#FF6DBDD1" StrokeThickness="1"/>
</Grid>
</ControlTemplate>
I didn't include the VisualStateGroups for brevity, but UnderlineTextBlock (which has the TextDecorations set to Underline) is set to Visible on the MouseOver VisualState. Similarly, DisabledOverlay is set to Visible on the Disabled visual state. The fuzziness then is a result of the TextBlock controls (UnderlineTextBlock and DisabledOverlay) getting layered on top of the ContentPresenter (who's control template will default to a TextBlock) which doubles the aliasing, making ugly text.
Why would you create three FrameworkElements in a template and bind them to Content when all you wanted to do is underline some text on MouseOver? Because TextDecorations are actually a TextDecorationCollection which can't be animated in a storyboard. Even more odd is that the TextDecoration enum only has one option: Underline. Perhaps most importantly, the HyperlinkButton is actually a ContentControl which means you might want to stick an Image or a button in there and still have it underline text when it is present.
So obviously someone at Microsoft made some compromises when designing this template, but how do we fix it? The simplest fix is to change the control template and add Visibility="Collapsed" on ContentPresenter for the three affected states: MouseOver, Pressed, and Disabled:
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="UnderlineTextBlock">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="UnderlineTextBlock">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="DisabledOverlay">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
You can verify the fix in this side-by-side comparison
This will work as long as you're only binding strings to the HyperlinkButton. Alternatively, you could change the UnderlineTextBlock to a Rectangle, make it 1 pixel high and align it to the bottom. This would have the added benefit of working for all non-text content. For someone that doesn't mind a little UI adjustment in their Code Behind you can do what I did and create a new control. I called mine a TextHyperlinkButton to make it obvious that it should only contain text.
namespace Sleight.Windows.Controls
{
public class TextHyperlinkButton : HyperlinkButton
{
private bool _templateApplied;
private TextBlock contentPresenter;
public TextHyperlinkButton()
{
DefaultStyleKey = typeof(TextHyperlinkButton);
MouseEnter += TextHyperlinkButton_MouseEnter;
MouseLeave += TextHyperlinkButton_MouseLeave;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
contentPresenter = GetTemplateChild("contentPresenter") as TextBlock;
if (contentPresenter == null)
{
throw new NullReferenceException("Could not find required TextBlock of name 'contentPresenter' in ControlTemplate");
}
_templateApplied = true;
}
void TextHyperlinkButton_MouseLeave(object sender, MouseEventArgs e)
{
if (!_templateApplied) return;
contentPresenter.TextDecorations = null;
}
void TextHyperlinkButton_MouseEnter(object sender, MouseEventArgs e)
{
if (!_templateApplied) return;
contentPresenter.TextDecorations = TextDecorations.Underline;
}
}
}
And the sample:
I did make one other change in my TextHyperlinkButton which was to tweak the FocusVisualElement. That blue rectangle has always driven me crazy, and while my gut wants to remove it entirely I decided just to change the color and make it barely visible.
You can a download the sample project here
tweesaic, My Mix10k Submission
2010-2-1
Update: Twitter changed the way they serve images to plugins (like Flash and Silverlight), so this app no longer works.
Last year I was very excited to see Microsoft's Mix 10k coding challenge but because of time constraints I wasn't able to finish an entry before the deadline. This year was threatening to do the same, but I managed to come down with a cold, work for 20 hours and squeak it in before the deadline.
So without further ado I present tweesaic, which (to my knowledge) is the first fully online photo mosaic creator. To use it, paste in an image you want generated and tweesaic will search twitter for tweets related to the 10k challenge, analyze the profile pictures associated with each tweet, and create a photo mosaic.
Here are some samples I've created with tweesaic:
My initial working version was 80k, so I was a little nervous about getting it down to size. The first four-fold reduction came easily, but getting it from 20k down to 10 was brutal. There were a couple a couple features that didn't make the cut:
- Doing image processing on a BackgroundWorker thread
- Saving a generated image, transitions and animations
- Error messaging was drastically reduced
- Buttons! (use the tab key instead)
The last is possibly the most painful omission; I had to remove the Xaml for submitting search terms and image urls. The workaround is to use the tab button to submit new search terms via the LostFocus event on each TextBox. I'm wondering if it would have been smarter to remove the logo and background gradients instead.
There are some features that I'm really glad I was able to keep in like using isolated storage for caching image data. That means mosaics will be generated faster the more you use the tool. I also like having the preview image up in the toolbar to let you compare how the mosaic looks versus the source image. The file upload feature is a convenient way to upload your own photos without hosting them (or to get around some sites which don't provide a cross domain policy).
Unfortunately, there are some bugs too. You can only upload ".jpg" images into the app, so you will have to rename any ".jpeg" extensions for them to work. Png image uploads work as expected. Also there is a bug in the image processing algorithm where an image with a high alpha component may get a higher match rating than a low alpha component. This will manifest itself on some dark regions that look unnaturally light because of the white background.
Play around with it and let me know what you think. To start, here are some images that you can copy paste into the url bar:



Special thanks to Nick Thiel for helping with the logo.
Why I Hate the Web
2010-1-8
I don't hate the web, that would be silly. But in a way, I do hate programming the web. This is kind of a odd statement since I am a Web programmer. This is more odd because if you asked me about my job I would say that I love it.
To explain what I mean I should back up a bit. I got my degree before my university had a proper web program. The internet was certainly around--it had been around for many years--but since all curriculum seems to be many years behind reality I was able to escape college having only taken one web programming course. In php. And I didn't do shit in that class. Anyway, I went through school thinking that I would be writing client applications in Windows Forms for the rest of my days and only when I had a degree and a crummy internship did I realize that maybe I had missed the point.
So now that I'm 4 years into Asp.net I find myself longing for Windows Forms again. That's not true, Forms were sloppy and I'm glad to see them go, but I do long for stateful programming. I'm tired of !IsPostBack. I'm tired of session timeouts and F5 and "To display the webpage again, Internet Explorer needs to resend the information you've previously submitted." I'm extremely tired of RequiredFieldValidators and RegularExpressionValidators and Labels and TextMode=MultiLine and AssociatedControlIDs. Every time I build a web form I weep.
It shouldn't be this way. I used to build houses and believe it or not there are people who still drive every nail into a house by a hand with a hammer and that's beautiful. Programming is not building houses. Beautiful programming is hiding the shit you hate in a class so that you never have to do it again. That's why I love it, and that's why I think Asp.net failed.
I'm not the first person to hate building webforms and I'm not the first person to try and hide that shit in a class so I never have to do it again. But me and everyone else can't seem to do it right. If I can get it to work right it's slow, if I get it fast it's either buggy or unmaintainable. If it's really clever it won't work in a shared hosting environment. Or it won't work without ViewState. Or it won't work without <form runat="server" />. If I want to buy someone else's solution it's still either slow or buggy or expensive (or all three, what we call in the biz The Trifecta).
Nobody can seem to figure it out in asp.net which is ironic because everyone can write a UserControl that works great. Hardly anyone can write a WebControl that works at all. Not if it's going to be templatable. Not with ajax. And especially not if that Ajax is going to have a graceful fallback and work with a script combiner. So 8 years after asp.net we still spend all our time writing user controls and copy pasting them as best we can. Every few months we try and turn that shit into a webcontrol and we fail.
So that's why I love Silverlight. I could kiss DependencyProperties and their corresponding OnPropertyChanged events. Not having to care when my data is loaded but knowing it will work is amazing. ControlTemplates that really do separate how it works and how it looks is phenomenal. I will never claim to be a great programmer but in Silverlight you only have to override two methods to create a custom panel. That makes me giggle. Sure I still fail miserably when I write new controls, but after each attempt I get a little bit closer to making something cool.
It may not be web programming, but it's close enough for me.
Blending and Brushes in Silverlight
2009-12-17
I'm in the process of converting a Flash site to Silverlight 3 and I just couldn't get the gradients right on my opacity mask. After talking to the flash developer he reminded me that he didn't use opacity masks but a multiply effect. I thought to myself "game over, Silverlight doesn't support blend modes."
I knew about SL3's support for custom shaders, but I was surprised to find Corey Plotts' library of blending effects for Silverlight, including Multiply. With Silverlight there are always caveats, and this has a fairly big one: you can only use VideoBrushes and ImageBrushes for effect inputs. That means in order for me to have a dynamic color applied to my blend I have to use the WriteableBitmap class to render my Grid's contents to a BitmapImage, then apply that to the MultiplyEffect as an ImageBrush. Will it work? It should, but I think I'll take a nice long winter break before I give it a shot.
Next up: Silverlight
2009-12-5
Just a quick update on the site. I'm working on a silverlight version that is nearing completion. I hope to show off some of the plane 3d effects in a new way. Expect to see it in 2010.
Until then, I may be posting a few thoughts about cool or peculiar things I've found in Silverlight 3 and 4 beta.



