Monday, June 28, 2004

System.Decimal Appears Horribly Broken

Run this code:

using System;

public class App
{
  public static void Main()
  {
    Decimal a = 57675350989891243676868034224m;
    ShowModulus(a, 7);
    Console.WriteLine();

    ShowModulus(a, 8);
  }

  public static void ShowModulus(Decimal a, int m)
  {
    for (int i = 0; i < m; ++i)
    {
      a++;
      Console.WriteLine("{0} % {1} = {2}", a, m, a % m);
    }
  }
}

And you'll get this output:

57675350989891243676868034225 % 7 = -2
57675350989891243676868034226 % 7 = -1
57675350989891243676868034227 % 7 = 0
57675350989891243676868034228 % 7 = 1
57675350989891243676868034229 % 7 = 2
57675350989891243676868034230 % 7 = 3
57675350989891243676868034231 % 7 = -3

57675350989891243676868034225 % 8 = 1
57675350989891243676868034226 % 8 = 2
57675350989891243676868034227 % 8 = 3
57675350989891243676868034228 % 8 = 4
57675350989891243676868034229 % 8 = 5
57675350989891243676868034230 % 8 = 6
57675350989891243676868034231 % 8 = 7
57675350989891243676868034232 % 8 = 0

I may not know much, but I know that something is wrong there: the way negative numbers are showing up is inconsistent. Frankly, I don't think they should be there at all, but if they are, you'd expect similar patterns between mod 7 and mod 8. Try it with numbers other than 57675350989891243676868034225, and for moduluses (moduli?) other than 7 and 8, too. It breaks for those as well.

This appears to be a bug in the Decimal.Modulus routine - caveat emptor. Oh, and it's still broken in the Whidbey version I'm running (40607). I tried to submit the bug over on the new MSDN Product Feedback Center, but I get an error every time I try to submit. D'oh!

Frankly, this would scare the crap out of me if I were writing financial or scientific software that relied on System.Decimal. In my case the apparent workaround is easy (add the modulus to the result if the result is less than zero), but my confidence in the algorithm is pretty low.

Sunday, June 27, 2004

I Like It Bare

Update: Be sure you read Tim Ewald's post about Doc/Literal/Bare - as I explain elsewhere, this post tells only half the story, and in fact mostly misses the point.


My, my, it has been quiet around here for the last week, hasn't it? My excuse is that I was in New Hampshire all week, working heads down on the MSDN rewrite with Tim Ewald and some other friends. My other excuse (always have a backup ready) is that I'm working on some big changes to this blog...but more about that soon enough.


Tim is always a font of entertaining but useless jokes, and enlightening and useful XML knowledge. One thing he pointed out to me this week was SoapDocumentMethodAttribute, in particular when specified with SoapParameterStyle.Bare.


Allow me to explain. Compare the XML produced by the following two functionally equivalent SOAP endpoints:


[WebMethod]
public int Add(int x, int y) { return x + y; }


and


[WebMethod]
[SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]
public int Add(int x, int y) { return x + y; }


Here are the request/response messages for the first variation:





POST /play/bare.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Add"


        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 
   
      int
      int
   

 


HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length



        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 
   
      int
   

 




and here they are for the second variation:


POST /play/bare.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/Add"


http://www.w3.org/2001/XMLSchema-instance
"
        xmlns:xsd="
http://www.w3.org/2001/XMLSchema"
        xmlns:soap="
http://schemas.xmlsoap.org/soap/envelope/">
 
    http://tempuri.org/">int>
    http://tempuri.org/">int>
 


HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length



http://www.w3.org/2001/XMLSchema-instance
"
        xmlns:xsd="
http://www.w3.org/2001/XMLSchema"
        xmlns:soap="
http://schemas.xmlsoap.org/soap/envelope/">
 
    http://tempuri.org/">int>
 




Notice the big difference? With the second variation, the wrapper element that corresponds to the method name has been removed. Which is nice, because it's superfluous - the method is already specified by the SOAPAction header. This is particularly nice in the response message where that extra level of indirection looks a little silly.


To me, this just seems like nicer XML; more like how I would do it if I were just using XmlWriter and raw sockets.

Friday, June 18, 2004

Whither Keybindings?

If I knew JoeN personally, here's what I would say to him:


Is there any science in this? Or just your idea of what makes sense? I don't ask to be accusatory - I have a real reason. :)


A few years ago, I was teaching a short .NET class at the University of Waterloo. I used emacs for something in front of the class, and one of the professors mentioned that a grad student of his had researched the impact of key bindings on productivity. He studied the emacs key bindings, a carefully designed set of bindings, and (as a sort of control) a completely random set of bindings. What was interesting was that users were able to learn even the random key bindings in fairly short order. What was more interesting however, was that the emacs bindings tied the random key bindings for usability! Both of them were significantly worse than the carefully designed set.


The point to all of this, of course, is that there isn't really an easy way to gauge how “good” a set of key bindings is. If you're really interested in helping developers, please actually do some research and see what works. Maybe you've already done this (kudos if so), but from your post it doesn't look this way. And at a company that actually does usability studies, I suspect you have the people in-house who could help you do it right.


Ultimately, it probably doesn't matter to me personally. Based on watching hundreds of students and dozens of colleagues work, I know I'm an atypical user when it comes to keyboard/mouse usage patterns. So even if you do come up with something that's optimized for your typical customer, I'll likely hate it. :)


Update: Joe responds that he did indeed work with a usability team to come up with the new keybindings. Very good! Apologies for any aspersions that were inferred - this is the sort of careful work that should be congratulated, whether or not you agree with the decision to change things.

Tuesday, June 15, 2004

PsExec - How Do They *Do* That?

I was over at SysInternals yesterday, downloading a new version of the most excellent Process Explorer, and I had a bit of a look around to see what else was cool. The answer, of course, is...everything. But I was particularly impressed by PsExec, a tool that gives you telnet-like shell connectivity to another machine without having to install anything on the remote machine!! I just run


psexec \\avalon cmd.exe


and like magic I have a command prompt that displays on my local machine that is actually executing commands over on the remote machine (avalon in my example). I repeat: without having to install anything on the remote machine. You can launch GUI applications, but they show up on the remote machine. Regardless, it's still killer for command-line guys like me.


I love it, but how the hell do they do that?

Sunday, June 13, 2004

WinForms Catch-All Exception Handling

Update: Fixed the broken image link. No content changes.


When I'm writing console applications, I tend to put a try-catch block around everything in the Main loop, primarily to let me return a non-zero exit code from the application, which makes it play well with batch scripts. But it also makes it a good place to print error messages that pertain to well-known exception types. So I wind up with something like this:


static int Main(string[] args) {
  try {
    // Do application logic here
 
}
  catch (ParseCommandLineException pce) {
    Console.WriteLine("Usage error");
    return 27;
  }
  catch (Exception e) {
    Console.WriteLine(e);
    return 42;
 
}
}


When writing WinForms applications, returning a non-zero return code generally isn't necessary, since it's atypical to want to automate a GUI application using batch scripting methods. However, having a global exception filter is still a useful thing. For example, when FlexWikiPad encounters an unhandled exception, it captures the exception and displays a dialog box that gives the user the option of emailing the error message to me. This sort of feedback lets me know what error conditions users are running into most frequently, letting me fix the big PITA bugs first.


But how do you do it? Because Windows Forms applications are event-driven, there's not really a convenient place to put a top-level try-catch block. Indeed, if you try to do something like this in a simple WinForms application:


[STAThread] static void Main() {
  try {
    Application.Run(new Form1());
  }
  catch (Exception e) {
    MessageBox.Show("Error " + e.Message);
  }
}


private void button1_Click(object sender, System.EventArgs e) {
  throw new Exception("Whoops");
}


What you'll find is that when you run it, you get the following (probably familiar) window:



Note that you'll only see this error message if you run the app outside the debugger. Why? Because WinForms is making use of its own unhandled exception mechanism, and the default behavior differs based on whether you're debugging or not. This is slightly confusing, but worse it means that in some scenarios, your carefully-crafted catch block will never run.


Fortunately, you can override the default behavior, by hooking the Application object's ThreadException event, as in the following code:


[STAThread] static void Main() {
  Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
  Application.Run(new Form1());
}


private void button1_Click(object sender, System.EventArgs e) {
  throw new Exception("Whoops");
}


private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) {
 
MessageBox.Show(e.Exception.Message);
}


Now when you run the application - inside or outside the debugger - your ThreadException handler will get called whenever an unhandled exception is thrown. You can do whatever you want here - exit the application gracefully, insult the user, or use a web service to log the bug in some sort of central database.


 

Tuesday, June 8, 2004

Advice For John

One of the best things about the Direct3D tutorial series that I've written is that occasionally people will email me asking for my help. I like this because I get to hear about what they are trying to do, and because it gives me a chance to solve interesting problems.


I recently got a letter from John Wessel that I thought posed an interesting question, so (with his permission), I'm posting it here.



> First, your tutorials on DirectX are great. I enjoy reading them because
> afterward I can actually make something work, and it validates my
> existence.


:) Glad you enjoyed them.

> Second, my question is almost related. I'm eighteen, in junior college and
> will be transferring in two or three semesters to a 4-year. I'm trying to
> find out what the job market is and what people are looking for when they
> hire. I figured I'd start by asking the people who got me interested in
> programming in the first place, the legible tutorial writers! I'm not
> quite sure exactly what you do or if you work for someone, but you seem
> knowledgeable enough so I thought you might have a good perspective.


I'm an independent computer programming contractor. My wife and I run our
own business, which is just the two of us. I used to teach for
DevelopMentor, but these days I design and write systems for my clients. I
bill myself as an expert in .NET technologies, with an emphasis on security
and web services. Our website is
http://wangdera.com if you want to see a
bit more.

> What should I major in? Is computer science absolutely necessary, or would
> something like physics, which I'm leaning towards right now, be
> acceptable? I've taught myself how to program and I dread having to take
> classes on something I'm decent at already. I'd rather learn something
> more that I can apply through programming, but I'd like to have a job,
> too.


Computer science is not necessary. It helps some, since your focus will be
on computers, but frankly, there's not a ton of difference between one BS
and another - most of your core courses are the same regardless of whether
you're a physics major or a biology major or an electrical engineer (which
is what I did).


See, here's the thing that no one tells you: learning to be a good computer
programmer takes at least ten years. Which means that just about no one
coming out of college is any good. The smart employers (and believe me,
there are a lot of dumb ones) know this, and aren't really looking for
people that already have really strong programming skills. They're looking
for people with strong *thinking* skills, since those people can be taught
to do just about anything well.


You should major in whatever you're interested in. Five years from now, when
you graduate, the job market and technologies in use will probably be pretty
different from what they are now. Also - and I know this can hard to believe
from your side of it - your brain is going to change a lot between now and
age 22. It changes even more between 22 and 30. Everyone always thinks that
you stop growing up at 18, but I can tell you that is sooooooo not true.
Anyway, the point is that it's too hard to guess with a lot of accuracy what
a) the job market is going to be like in 2008, and b) what *you're* going to
be like in 2008. Therefore, to make the most out of college, stay
interested. If that means physics, do physics.

> What skills should I have in order to get hired? My ideal programming job
> would be developing the next platform of blank, like .NET, DirectX or
> something entirely new and different. To date I've gotten a few jobs
> building some ASP.NET web applications, the major one being some
> accounting software for the City of Elk Grove, but no other work
> experience.


Well, one thing I'd point out is that for something like .NET or DirectX,
there are a very small number of people building it, but a very large number
of people using it. In other words, there's a lot more work out there
building ASP.NET web applications than there is writing DirectX 10.0. For
example, Managed DirectX 9 was written by one guy.


This is sort of good news and bad news. The bad news is obvious - what you
think is your ideal job is going to be very competitive to get. The good
news is that all of that other work building "business" applications,
actually turns out to be very interesting, and very lucrative. So don't
write it off - there are hard problems to be solved in every field, and good
programmers are needed to do the work. That said, *someone* has to write
.NET 3.0, and it might just be you. :)


My parting advice to you is that, regardless of what major you choose, be
sure to keep programming. Remember - it takes at least ten years to get
good. It sounds like you've already got a great start. (And you write well,
too, which is also a really good sign.) But make sure you take what you've
done already and keep building on it. Write code. Study design. Write more
code. Even familiarize yourself with some of the non-technology aspects of
programming like how team-based development works (e.g. pair programming,
test-driven development, etc.) You're going to need to do all of this - a
lot - before you can rightfully consider yourself an elite programmer. I
know I'm still learning.


Let me know if there's anything else I can do to help, or questions I can
answer.


-Craig


P.S. Do you mind if I reprint your message and my response on my weblog? 

Monday, June 7, 2004

&amp;quot;SQL Server does not exist or access denied&amp;quot; in Yukon

Bob Beauchemin helped me out with a little problem I was having yesterday, and I figured I'd do my part to disseminate the information.


I was playing around with some software that needs a database back-end. All I have on my machine right now is some interim build of Yukon that we're using at MSDN. I knew I was risking problems by using it, but I didn't really want to have to install SQL Server 2000 as well.


The problem I ran into was when using a connection string like this:



server=.\saratoga;database=MSDNPreview;uid=blah;pwd=foobar


I was getting the following error message



SQL Server does not exist or access denied.


After playing around with it for a while, I discovered that if I ran the program I was testing from a window where it bound to Whidbey, the error message went away. In other words, the problem only existed when using System.Data.SqlClient from the CLR 1.1. I thought I was running into a bug in Yukon that meant I was going to have to install SQL Server 2000. Sigh.


Fortunately, before I went down that road, I asked some of my DM buddies if they knew of this particular issue. Bob came back and said that he'd seen this error before, and that for him, switching the connection string to something like this:



server=localhost\saratoga;database=MSDNPreview;uid=blah;pwd=foobar


fixed the problem (note the use of 'localhost' instead of '.').


And sure enough - it fixed it for me, too. Thanks Bob!

Thursday, June 3, 2004

Cheese Doodles

Stop reading right here if you don't like suggestive jokes.



So a guy goes to the doctor. The doctor asks, “What seems to be the problem?” The guy, obviously somewhat embarassed says, “Well, it's the strangest thing, but my, um, private parts seem to have turned bright orange.”


The doctor is taken aback - he's never heard of anything like this before. He examines the man, and sure enough, the situation is exactly as the man describes it: as orange as a traffic cone.


“Have there been any significant changes in your life that might explain this?” the doctor asks.


“I don't think so. I mean, my wife left me last week, but nothing medical, if that's what you're asking.”


“Sometimes big changes like that can cause stress, and stress can have odd effects. Have you been feeling depressed, losing sleep, anything like that?”


“Not really - I've been taking it pretty easy. Mostly I just sit on the couch, eat cheese doodles, and watch porn.”


Tim Ewald told me this one when I mentioned that my wife was away at Wharton this week starting her Executive MBA. Being a smartass, he also asked me if my keyboard was orange. :)

Wednesday, June 2, 2004

mvp-xml

I called up Tim Ewald today to ask him a question I'm sure lots of people have run into before: “So, I've got an XPathNavigator, and I want to validate it against a schema. What API should I use?” He laughed, and then went on to explain how much the answer sucks. Basically, the only way to do it using the System.Xml APIs is to use the OuterXml property of the navigator to turn the XML back into a string, then suck it up into an XmlTextReader, then validate using that. This is a huge waste - it means you have to take something you already parsed, unparse it, then turn around and parse it again. Lame!


I knew I couldn't be the only one that had run into this problem before. Acting on a hunch, I ran a Google search on XPathNavigatorReader. Sure enough, I found this, which led me to this. In brief, it is the exact adapter layer I wanted, allowing me to get an XmlReader over any XPathNavigator. What's great is that the package was released just two days ago, so my timing was fortuitous.


There's a bunch of other cool stuff in there, too - definitely check it out if you're working with the System.Xml APIs at all..some of this stuff isn't even in Whidbey yet.

Tuesday, June 1, 2004

More Direct3D Afrikaans Translations



The fifth and sixth installments in the Direct3D tutorial series, are now available in Afrikaans. Thanks to Ernst Kuschke.