<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Michael Stuart's Weblog</title><subtitle type="html">GUTS--Grand Unification Theory of Software</subtitle><id>http://blogs.msdn.com/methylamine/atom.xml</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/methylamine/atom.xml" /><generator uri="http://communityserver.org" version="2.1.61025.2">Community Server</generator><updated>2004-11-19T16:53:00Z</updated><entry><title>Incommunicado for TWO YEARS...Yes, I have contributed to the gene pool</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2007/10/15/incommunicado-for-two-years-yes-i-have-contributed-to-the-gene-pool.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2007/10/15/incommunicado-for-two-years-yes-i-have-contributed-to-the-gene-pool.aspx</id><published>2007-10-16T00:24:00Z</published><updated>2007-10-16T00:24:00Z</updated><content type="html">&lt;p&gt;My charming and uber-tolerant wife has given me a beautiful baby girl, Selkie.&amp;nbsp; This happened 21 months ago, but it's only now I find a spare 30 seconds to blog about it.&lt;/p&gt;&lt;p&gt;LOL, though, because I was that guy who variously poked fun at my friends with children or scorned them for being behind on the newest movies/games.&amp;nbsp; Well, I haven't bought a new XBox.&amp;nbsp; I don't own Halo 3 yet.&amp;nbsp; I haven't even finished Halo 2, let alone Half-Life 2.&lt;/p&gt;&lt;p&gt;About the only thing I have completed is my second bass horn...and that took two years.&amp;nbsp; More on exponential horns and bass later.&lt;/p&gt;&lt;p&gt;The great consolation and hope I can offer prospective fathers is HOLY CRUD it's fun.&amp;nbsp; I'm enjoying her more every day; she's at that n^4 cognitive stage where they pick up half a dozen new words a day.&amp;nbsp; You can practically HEAR the synapses firing as new dendrites sprout.&amp;nbsp; I'm surprised I don't have to mount one of those lovely copper-flower Zalman cooling fans on her head because that CPU must be dissipating 100W easily :)&lt;/p&gt;&lt;p&gt;Spent a year doing Java, enjoyed it, lovely language, but back to C# 2 and 3.&amp;nbsp; C# is definitely the better language now; Java will be with us for lo many years, but I believe there's more room in the CLR's architecture for neater and neater tricks in the future.&lt;/p&gt;&lt;p&gt;Recent fun projects:&lt;/p&gt;&lt;p&gt;Asynchronous Command Execution Service (ACES)--reads ServiceAgents from any "queue" source, which depending on the provider can be MSMQ, MQSeries, a DB table, whatever.&amp;nbsp; The ServiceAgent adheres to IServiceAgent and gets de-serialized from the queue provider, then called in on Execute().&amp;nbsp; The ACES manages a common thread pool, assigns agents to them, monitors their health, kills them if they go off to never-never land, etc.&amp;nbsp; The beauty of it is, it can read from as many sources as you configure, and can be distributed across as many machines as you like.&amp;nbsp; We're using it to do everything from asynchronous exception logging, code audit logging, to running 24-hour queries for report generation.&lt;/p&gt;&lt;p&gt;RulesEngine--not exactly a green-field application, but tailored well to our needs.&amp;nbsp; Takes any expression with arithmetic, set, boolean, and statistical operators and evaluates them.&amp;nbsp; Dynamically parses DataSet tables and columns, fetches the data, and operates on it.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5464478" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Leaving the nest at Microsoft...Bigger Things Afoot</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/06/18/430483.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/06/18/430483.aspx</id><published>2005-06-19T00:47:00Z</published><updated>2005-06-19T00:47:00Z</updated><content type="html">&lt;font face="Verdana"&gt;After five fine years, I'm leaving Microsoft.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
I couldn't have hoped for a better experience.&amp;nbsp; I've learned more
in five years than I did in four of medical school; deep technical
sk1llz, consulting skills, how businesses operate, how to develop
_products_ not just projects...an amazing amount, a firehose.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
Microsoft is one of those rare places that inspire real passion in
people.&amp;nbsp; I have a Windows XP logo tatto'ed on my right
shoulder...yes, it's real and it's permanent (to paraphrase Terri
Hatcher in Seinfeld).&amp;nbsp; I've yelled myself hoarse at Steve
Ballmer's annual ra-fests; &lt;b&gt;I was right there at "developers&lt;/b&gt;&lt;/font&gt;&lt;font face="Verdana"&gt;&lt;b&gt; developers&lt;/b&gt;&lt;/font&gt;&lt;font face="Verdana"&gt;&lt;b&gt; developers&lt;/b&gt;&lt;/font&gt;&lt;font face="Verdana"&gt;&lt;b&gt; developers..."&lt;/b&gt;&amp;nbsp; Most of the time, I got up in the morning excited about going to work.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
It wasn't all rosy and wonderful; like any company there are
imperfections.&amp;nbsp; I'd like to post a constructive commentary on that
in a later blog.&lt;br&gt;
&lt;br&gt;
I'm going to a super-cool small software company here in Houston called
"PROS Pricing Solutions".&amp;nbsp; They are the forerunners in a field
variously named but herein "revenue optimization".&amp;nbsp; Basically, I
have something that is valuable NOW, but in a while it will expire;
what should I sell it for to maximize my profit?&amp;nbsp; Applies to
airline seats, hotel rooms, transmission capacity, you name it.&amp;nbsp;
Takes serious, heavy-duty math and code to grind an answer.&amp;nbsp; My
PhD buddy John Salch (was in Rice grad school while I was in med
school) will be filling me in on the gory details.&lt;br&gt;
&lt;br&gt;
I'll be tech-lead doing hard-core development--my favorite thing to do
in the whole wide world.&amp;nbsp; I haven't met everyone on my team yet;
but judging from my interviewers (three PhD's and a very smart
developer) they will be stellar.&lt;br&gt;
&lt;br&gt;
It's going to be a pleasure to focus on ONE THING, and do it exceedingly well, producing a product.&amp;nbsp; &lt;br&gt;
&lt;br&gt;
The company is about fifteen minutes' drive from my house...hey maybe
I'll get one of those uber-dork Segway thingies, you know, "Ginger" :)&lt;br&gt;
&lt;br&gt;
I'll also get to play with...er, um...&lt;i&gt;alternate&lt;/i&gt; tech such as
...er, um....the "J" word and the "U" word.&amp;nbsp; I'm really keen
though; it will be nice to become multi-lingual and multi-platform.&lt;br&gt;
&lt;br&gt;
Stay tuned.&amp;nbsp; I will have MUCH to blog on, I'm sure, as I get immersed in new tech and new problems.&lt;br&gt;
&lt;br&gt;
ex-msft Michael&lt;br&gt;
&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=430483" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>**WARNING POLITICS** Stupidity of War On Some Drugs</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/06/02/424341.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/06/02/424341.aspx</id><published>2005-06-02T17:53:00Z</published><updated>2005-06-02T17:53:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;**&amp;nbsp; WARNING:&amp;nbsp; PERSONAL LIBERTARIAN POLITICS AHEAD&amp;nbsp; **&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Here goes--my first rabidly political post.&amp;nbsp; Oh, goody!&amp;nbsp; I'm&amp;nbsp;drooling with glee.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The recent hub-bub about lowering the drinking age in Wisconsin for military folks got me all hopped-up frothing and raving again.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Once again I'm struck by the complete absurdity of the War On Some Drugs (WOSD).&amp;nbsp; Our Puritan heritage allows us the nifty double-think trick of legalizing the two most awfully harmful, blatantly addictive drugs known to man...because they're both quite damaging and, we feel, those who experience pleasure MUST be punished later.&amp;nbsp; That is--ethanol causes hangovers, a just retribution for enjoying oneself; tobacco, well, we know how THOSE sinners are punished!&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;EM&gt;Before I go any further:&amp;nbsp; I argue these points from a completely abstract viewpoint, since I'm a total non-user and non-drinker.&amp;nbsp; I really do have the betterment of mankind at heart :)&lt;/EM&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;So back to the War On Some Drugs.&amp;nbsp; We're in the completely laughable position of fighting a battle we've fought before--Prohibition--that we've been fighting for 30 years; recognizing it, and yet persisting in the insanity.&amp;nbsp; We've created a hugely profitable business with wonderful profit margins; what fool would want to destroy such a lucrative market?&amp;nbsp; The drug suppliers sell natural or off-patent substances, manufactured or harvested generically, which by themselves are worth pennies a dose--at 1000*cost.&amp;nbsp; Sure, they lose the occasional 10% to the Keystone Cops, who trumpet each bust on the evening news like they've shut down drug Y for all of North America this month.&amp;nbsp; In fact it just means Mitsubishi-brand Ecstacy won't be available that evening, we'll have to settle for those crummy Smurf X tabs.&amp;nbsp; Or go sniff glue and gulp Robitussin DM.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Law enforcement, meantime, benefits almost as richly as the suppliers.&amp;nbsp; Sure, most of the officers are honest people just doing their work; they probably even believe in it though how I don't know.&amp;nbsp; Some, I'm sure, gain handsomely themselves; no enterprise this profitable fought by underpaid civil servants escapes corruption.&amp;nbsp; Even the&amp;nbsp;honest ones--well, they're employed by the WOSD, aren't they?&amp;nbsp; And those agencies--DEA, BATF--what will they do if we go sane?&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;Due process?&lt;/STRONG&gt;&amp;nbsp; Out the window; if it's drugs, your stuff (money, home, vehicles, freedom) are confiscated first; you essentially sue to get your own stuff back.&amp;nbsp; I seem to remember the "logic" for this trampling of the Constitution was that those awful, rich cocaine suppliers can afford &lt;EM&gt;such great attorneys, why, we've gotta make sure all they can use is our crappy public defender here in Podunkville&lt;/EM&gt;...Gestapo, anyone?&amp;nbsp; Yep, civil rights are just too inconvenient when you're fighting the noble War On Some Drugs.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The two legal intoxicants kill somewhere around 450,000 people per year; roughly 370,000 from smoking, and another 80,000 or so from drinking.&amp;nbsp; Meanwhile, while true statistics for drug deaths are hard to find, even the most imaginative interpretations of drug-related deaths..."Well ma'am, I'm sorry your son died.&amp;nbsp; He died of drugs; at the time he was hit by a bus, there may have been marijuana in the city somewhere."&amp;nbsp; But guaranteed, deaths due to all illegal drugs together are an order of magnitude less.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;When we instituted Prohibition (why don't we remember how badly THAT sucked), ethanol deaths increased dramatically; due to impurity, on-the-sly consumption in dangerous situations, crimes over turf battles, the list goes on.&amp;nbsp; It was a &lt;EM&gt;disaster&lt;/EM&gt; and we quickly came to our senses.&amp;nbsp; Now granted--ethanol wouldn't pass muster with the FDA today by a long shot,&amp;nbsp;but at least what you buy isn't adulterated.&amp;nbsp; The same logic applies to drugs.&amp;nbsp; Today's market is filled with adulterated product made in shoddy labs or diluted with impurities.&amp;nbsp; It's consumed on the sly creating dangerous situations.&amp;nbsp; It's so profitable that it drives a huge criminal industry, and costs us a huge enforcement engine that's ineffectual except to maintain inflated price levels.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Ah--but if we legalize (aka "decriminalize"), the World Will End and people will simply Spiral Out Of Control.&amp;nbsp; Nope.&amp;nbsp; People are remarkably smart if they're given free choice and the information to exercise it.&amp;nbsp; Publish the truth about every substance; an MSDS (Material Safety Data Sheet) and a proper drug insert--just like those pharmaceutical commercials where beautiful people smile and wink knowingly, then the announcer comes on rapid fire and says things like "Do not take Foovamine if you are a person.&amp;nbsp; Or a dog.&amp;nbsp; Or a mammal at all.&amp;nbsp; May cause blindness, itching, auricular necrosis, and supraventricular tachycardia.&amp;nbsp; Talk to your doctor immediately if your fingers turn black and fall off."&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I bet that with decriminalization we'd initially see a huge upswing in use--maybe one to five years--followed by a huge decline, probably to current levels or less.&amp;nbsp; Deaths would decrease dramatically; high quality, well-documented substances would curtail the usual junkie overdoses and adulterant toxicity cases.&amp;nbsp; People would exercise their free choice--and learn to protect themselves.&amp;nbsp; Certainly we'd avoid the thousands of unnecessary violence-related deaths; fighting over turf, fighting over money, drug busts gone bad, the whole damn mess.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Hey--&lt;STRONG&gt;we didn't used to have prohibition!&lt;/STRONG&gt;&amp;nbsp; It's a fairly recent thing.&amp;nbsp; Let's get rid of it and spend the money on a manned mission to Mars or something.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;And oh yeah--the decent people who voluntarily visit forsaken overseas hell-holes and risk their lives for esoteric things like our principles--can we PLEASE let them have a beer?&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=424341" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>SQL Injection--Everyone Knows It, No-one FIXES IT!</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/06/01/424072.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/06/01/424072.aspx</id><published>2005-06-02T04:42:00Z</published><updated>2005-06-02T04:42:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Does the following input into a web application text box strike appropriate fear into your heart?&amp;nbsp; Nay, I should say, dost though poop thine pants gazing there-upon?&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;' or 1=1;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;'; use master; xp_cmdshell 'net user SomeUser SomeUsersPassword /add'; --&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I love the last one.&amp;nbsp; I just added a user to your SQL box.&amp;nbsp; Now I will paaaarr--tay.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I remember vividly the vomit-comet, bowel-dropping sensation I had when Jesper Johanssen used this as the opening salvo in a complete network penetration at last year's TechEd.&amp;nbsp; I think the talk was titled "10 Easy Steps to Penetrating Your Network"--Jesper sorry if I butchered the title.&amp;nbsp; It was an excellent talk.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;That second line works on quite secure-appearing networks; ones with proper external firewalls, a nice tidy DMZ with your uber-secure web serveren, and an inner firewall where your pristine, champagne-sipping SQL boxen sit.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The moral of this frightening tale?&amp;nbsp; &lt;STRONG&gt;Protect yourself against SQL Injection!&lt;/STRONG&gt;&amp;nbsp; If you don't know what it is, Google it.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I've seen so many complacent customers with SA passwords in cleartext in web.config.&amp;nbsp; Start there--use &lt;STRONG&gt;CryptoUtility&lt;/STRONG&gt; to at least protect your connection string. (&lt;A href="http://workspaces.gotdotnet.com/cryptoutility"&gt;http://workspaces.gotdotnet.com/cryptoutility&lt;/A&gt;)&amp;nbsp; But before you go encrypting it--&lt;STRONG&gt;use least privilege!&amp;nbsp; &lt;/STRONG&gt;SA is really hitting the fly with a hammer.&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Use stored procedures.&amp;nbsp; I was asked recently, "...well if I pass a varchar that came from user input, and then use string concatenation in the stored procedure, then use &lt;EM&gt;sp_executesql&lt;/EM&gt; to run it...that's safe, right?"&amp;nbsp; &lt;STRONG&gt;NO.&lt;/STRONG&gt;&amp;nbsp; The beauty of stored proc params is they're not executed; if you do string concat-execute you circumvent that.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Yep, there are times we can't use sp's for everything and have to generate SQL on the fly.&amp;nbsp; But remember that &lt;STRONG&gt;all user input is evil and untrustable!&amp;nbsp; &lt;/STRONG&gt;There are some nice reg-ex based utilities out there that do a good job of scrubbing user input for nasties...but they're not perfect.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Now I'm going to go back to looking at my HoneyPot box in my DMZ.&amp;nbsp; I like to watch script-kiddies come in with cute little hacks like:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;2005-05-30 14:40:48 67.167.243.58 -&amp;nbsp;&amp;lt;my ip&amp;gt;&amp;nbsp;80 GET /scripts/root.exe /c+dir 404 -&lt;BR&gt;2005-05-30 14:40:48 67.167.243.58 - &amp;lt;my ip&amp;gt; 80 GET /MSADC/root.exe /c+dir 404 -&lt;BR&gt;2005-05-30 14:40:48 67.167.243.58 - &amp;lt;my ip&amp;gt; 80 GET /c/winnt/system32/cmd.exe /c+dir 404 -&lt;BR&gt;2005-05-30 14:40:48 67.167.243.58 - &amp;lt;my ip&amp;gt; 80 GET /d/winnt/system32/cmd.exe /c+dir 404 -&lt;BR&gt;2005-05-30 14:40:48 67.167.243.58 - &amp;lt;my ip&amp;gt; 80 GET /scripts/..%5c../winnt/system32/cmd.exe /c+dir 404 -&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Aren't they just precious?&amp;nbsp; Ah, the&amp;nbsp;eternal optimism of the young...hey kids,&amp;nbsp;doesn't it seem odd that the machine's name is "HoneyPot"?&amp;nbsp; I blame the schools these days.&amp;nbsp; They just don't teach these young'uns to READ, especially great classics&amp;nbsp;like "The Cuckoo's Egg".&amp;nbsp; What especially cracks me up are the ones who, day after day, from the same damn IP addresses, run full port scans against my ISA 2005 external firewall.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=424072" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>New Version of CryptoUtility</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/05/31/423504.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/05/31/423504.aspx</id><published>2005-05-31T19:31:00Z</published><updated>2005-05-31T19:31:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Please have a look at:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;A href="http://workspaces.gotdotnet.com/busybeebuilder"&gt;&lt;FONT size=2&gt;http://workspaces.gotdotnet.com/busybeebuilder&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;A href="http://workspaces.gotdotnet.com/cryptoutility"&gt;http://workspaces.gotdotnet.com/cryptoutility&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;CryptoUtility&lt;/STRONG&gt;:&amp;nbsp; My friend J Sawyer and I&amp;nbsp;published CryptoUtility as part of an article on high-security crypto in a real world application last year, in the November 2004 MSDN magazine....see:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/04/11/CryptoUtility/default.aspx"&gt;&lt;FONT face=Verdana size=2&gt;http://msdn.microsoft.com/msdnmag/issues/04/11/CryptoUtility/default.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Verdana size=2&gt;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Anyway, J didn't really, er, um...LIKE...my UI.&amp;nbsp; Yes, I admit it... My name is Michael Stuart, and I do not design pretty UI's.&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;J did up a very nice property-control admin UI, and I've revamped the solution file to include it and got rid of a bunch of superfluous other stuff.&amp;nbsp; &lt;STRONG&gt;The new Admin Wizard&amp;nbsp;is very nice!&lt;/STRONG&gt;&amp;nbsp; Thanks J.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The rest of the CryptoUtility--that is, the core Crypto stuff--is unchanged and still rock-solid.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The MSI installs buildable source, binaries, and the documentation.&amp;nbsp; I've updated the documentation to work with the new admin wizard UI.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The &lt;STRONG&gt;key new feature&lt;/STRONG&gt; is that the Admin Wizard creates a setup file for CryptoUtility, complete with everything necessary to install it on a blank machine.&amp;nbsp; It then &lt;STRONG&gt;password-encrypts the setup config file&lt;/STRONG&gt;; you take that file, and copies of the CryptoUtility binaries, and put them on a USB key.&amp;nbsp; Then, you run around the various servers in your farm, plug the USB key in, copy the binaries to whereever, and &lt;STRONG&gt;run the wizard in command-line mode&lt;/STRONG&gt;.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;Why is this better?&lt;/STRONG&gt;&amp;nbsp; Because only one person, the admin, ever has access to the symmetric crypto key for your server farm.&amp;nbsp; He or she knows the password to the config file containing the ONLY cleartext copy of that key.&amp;nbsp; It's a secure install process--much better than the old admin utility.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=423504" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>New Versions--CryptoUtility and BusyBeeBuilder</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/05/31/423499.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/05/31/423499.aspx</id><published>2005-05-31T19:18:00Z</published><updated>2005-05-31T19:18:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Please have a gander at:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;A href="http://workspaces.gotdotnet.com/busybeebuilder"&gt;http://workspaces.gotdotnet.com/busybeebuilder&lt;/A&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;A href="http://workspaces.gotdotnet.com/cryptoutility"&gt;http://workspaces.gotdotnet.com/cryptoutility&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I've updated my two&amp;nbsp;(currently) favorite pet projects.&amp;nbsp; More on CryptoUtility in the next post...here's BusyBee:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;BusyBeeBuilder:&lt;/STRONG&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&lt;FONT face=Verdana size=2&gt;My automated build solution.&amp;nbsp; About 18 months ago I became frustrated with the complexity of some automated build solutions, and with the&amp;nbsp;over-simple alternatives.&amp;nbsp; There had to be&amp;nbsp;a middle ground--and BusyBeeBuilder is it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I wrote it as&amp;nbsp;essentially a sequential workflow management framework.&amp;nbsp; It uses the Plug-In pattern extensively, allowing you to write very simple "IBuildActionWorker" implementations to do&amp;nbsp;build&amp;nbsp;tasks.&amp;nbsp;&amp;nbsp;BusyBee comes with most of the useful ones already--.NET Solution file build,&amp;nbsp;SourceSafe&amp;nbsp;label and get, run NUnit's, run FxCop, move files, move/copy directories, archive, and send email to the team.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;It runs as a service and it can build multiple applications simultaneously;&amp;nbsp;it's running at several quite large places very successfully.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;It implements a very good monitoring model, so BusyBee allocates a certain number of minutes to each task; if the task exceeds its allocation, BusyBee kills it cleanly...no more hung instances of DevEnv.exe holding up your builds.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;There's a Remote Control, so developers can pull up the Remote, connect to a server, and kick of builds on demand.&amp;nbsp; It echoes back progress on each step--BTW, uses eventing over a Remoting channel and implements the two-way proxy thing to mutually hide the server and client types from each other...kind of fun.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The&amp;nbsp;config file is very literal and simple to set up; it specifies a Build Target and some global settings like where to put the log file, and then has a sequence of BuildActions.&amp;nbsp; Those actions' Workers are specified by&amp;nbsp;name, type, assembly, and they're passed a name-value collection of parameters.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Please&amp;nbsp;join the workspace.&amp;nbsp; The MSI you'll find there, version 2.2, installs source, binaries, documentation (still kind of sparse, but OK).&amp;nbsp; It also installs two ZIP files that you can use to run most of the NUnits, which are included.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I'm glad to offer help on the GotDotNet workspace's forum/discussion.&amp;nbsp; Please let me know if you use BusyBee!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://workspaces.gotdotnet.com/cryptoutility"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=423499" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Funny story...funny ha-ha on me :)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/05/13/417205.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/05/13/417205.aspx</id><published>2005-05-13T17:19:00Z</published><updated>2005-05-13T17:19:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana color=#000000&gt;A good friend of mine--whose company I'm consulting for right now--emailed me this joke.&amp;nbsp; Too funny...and kind of hit home :)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Thanks for keeping me humble, Ryan!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A cowboy was herding his herd in a remote pasture when suddenly &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a brand-new BMW advanced out of a dust cloud towards him. &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The driver, a young man in a Brioni suit, Gucci shoes, Ray Ban &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sunglasses and YELL tie, leans out the window and asks the &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cowboy, "If I tell you exactly how many cows and calves you have &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; in your herd, will you give me a calf?" &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The cowboy looks at the man, obviously a yuppie, then looks at &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; his peacefully grazing herd and calmly answers, "Sure.&amp;nbsp; Why &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; not?" &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The yuppie parks his car, whips out his Dell notebook computer, &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connects it to his AT&amp;amp;T cell phone and surfs to a NASA page on the &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Internet, where he calls up a GPS satellite navigation system to &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get an exact fix on his location which he then feeds to another &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NASA satellite that scans the area in an&amp;nbsp; ultra-high-resolution &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; photo. &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The young man then opens the digital photo in Adobe Photoshop &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; and exports it to an image processing facility in Hamburg, &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Germany.&amp;nbsp; Within seconds, he receives an email on his Palm Pilot &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; that the image has been processed and the data stored. &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; He then accesses a MS-SQL database through an ODBC connected &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Excel spreadsheet with hundreds of complex formulas.&amp;nbsp; He uploads &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; all of this data via an email on his Blackberry, and after a few &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; minutes, receives a response. &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Finally, he prints out a full-color, 150-page report on his hi- &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tech, miniaturized HP LaserJet printer and finally turns to the &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cowboy and says, "You have exactly 1586 cows and calves." &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "That's right.&amp;nbsp; Well, I guess you can take one of my calves," &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; says the cowboy.&amp;nbsp; He watches the young man select one of the &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; animals and looks on amused as the young man stuffs it into the &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; trunk of his car. &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Then the cowboy says to the young man, "Hey, if I can tell you &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; exactly what your business is, will you give me back my calf?" &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The young man thinks about it for a second and then says, &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Okay, why not?" &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "You're a consultant." says the cowboy.&amp;nbsp; "Wow! That's correct," &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; says the yuppie, "but how did you guess that?" &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "No guessing required," answered the cowboy.&amp;nbsp; "You showed up &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; here even though nobody called you; you want to get paid for an &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; answer I already knew; to a question I never asked; and you &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; don't know anything about my business." &lt;BR&gt;&amp;gt; &lt;BR&gt;&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Now give me back my DOG."&lt;/FONT&gt; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=417205" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Swallowing The Red Pill</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/05/03/414340.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/05/03/414340.aspx</id><published>2005-05-03T19:19:00Z</published><updated>2005-05-03T19:19:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana&gt;As I alluded in my last post, I've officially swallowed the Red Pill...at least this month.&amp;nbsp; For the 3 developers who haven't seen the Matrix--the red pill pops you out of the Matrix into reality, the blue pill returns you to blissful ignorance and a life of computer-generated fantasy...the latter much like owning an XBox.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I want to emphasize some core philosophical points I re-learned on my last project:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Verdana&gt;use supported technologies/products&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana&gt;focus on the final goal, not the path to it&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana&gt;spend engineering effort where it helps the business&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana&gt;when you pay for expert advice, listen to it&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Use supported technologies/products:&lt;/STRONG&gt;&amp;nbsp; Open source tools like NUnit, CruiseControl, NDoc, etc. are just super.&amp;nbsp; They're indispensable to me.&amp;nbsp; But you'll notice, they're not really embedded in the actual output; they're tools we use during development.&amp;nbsp; The flip side is code that'll show up in release builds; there's a different animal.&amp;nbsp; How much do you truly trust what you've included?&amp;nbsp; How bulletproof is it?&amp;nbsp; Chances are, you really don't know.&amp;nbsp; I know how hard it is to truly test code; I mean TEST it!&amp;nbsp; Beat it up.&amp;nbsp; Run it for 72 hours at absolute maximum load.&amp;nbsp; Gather perf-counter and exception data for that whole time.&amp;nbsp; Verify accuracy of results during that run.&amp;nbsp; Black-box testing--positive input, negative input, boundary input, garbage input, etc.&amp;nbsp; Does it leak handles or memory?&amp;nbsp; Does it degrade over time?&amp;nbsp; Is it fragmenting the heap(s)?&amp;nbsp; Is it chewing up threadpool threads?&amp;nbsp; Is it hiding exceptions but spewing out garbage?&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;It's really hard to honestly test this stuff and trust completely in the outcome...I mean, trust to the extent that I'll gladly say "Why YES, Ms. CIO, you can confidently put your $25million/day website on this application.&amp;nbsp; No really." &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I've done this extent of testing, front-to-back, honestly about five times in the past five years.&amp;nbsp; It's expensive, time-consuming, and many customers just won't buy off on it or won't dedicate the hardware and people to make it happen.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;When you go plugging random Mom &amp;amp; Pop LLC code into your code, you should know if they've done this testing, or do it yourself.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;On the other hand--look at quasi-products like PAG's EnterpriseLibrary.&amp;nbsp; It is BULLETPROOF, and whenever it's discovered it's not, it's fixed.&amp;nbsp; You have a "neck to wring"--Microsoft's.&amp;nbsp; It has huge community support--extensions, bug fixes, discussions, and its developers' blogs.&amp;nbsp; It's had the horrendous brutalizing testing done already--in fact you can SEE the unit tests right there, and read the tester's&amp;nbsp;articles on MSDN.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Focus on the Final Goal&lt;/STRONG&gt;:&amp;nbsp; Too often on a big project we (developers+architects) get lost on the design, the abstractions, the "frameworks"...in other words, navel-gazing academic purism of the worst degree.&amp;nbsp; The fact is, every design will evolve during development.&amp;nbsp; Period.&amp;nbsp; There is NO AMOUNT of pretty UML and exhaustive user interviews that will change this--which is why I'm so in love with XP's pragmatic weekly iterative approach.&amp;nbsp; &lt;STRONG&gt;Every day, ask yourself:&amp;nbsp; "Did we do something today that contributes &lt;EM&gt;directly&lt;/EM&gt; to the end goal?"&lt;/STRONG&gt;&amp;nbsp; Or "Did we implement a feature?&amp;nbsp; Did we fix a bug?"&amp;nbsp; At the end of the week, when you do an interim gold release, will the users see measurable progress and no regressions?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I FREAK OUT when I see folks designing "frameworks", without an application inside it that serves as a weekly user-visible benchmark of actual progress.&amp;nbsp; You're asking for trouble with that old-school waterfall mentality; you can't possibly anticipate every need for the framework unless you are simultaneously loading it with an application.&amp;nbsp; Much worse, if you're developing a "framework" with multiple apps in mind.&amp;nbsp; The specifications become so vague, the abstractions so broad, and the timelines so long that they basically never get done.&amp;nbsp; What have you saved?&amp;nbsp; You may have reuse, but the effort to get there was more than the time you would have spent adapting smaller, more modular "application blocks" which were more focused on a particular problem.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I guess that last part means:&amp;nbsp; think first about pattern, template, and process reuse; then about modular "application block" reuse--like CryptoUtility, or all the awesome PAG blocks; THEN maybe think about reusing an entire framework...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Spend Engineering Effort Where It Helps The Business:&lt;/STRONG&gt;&amp;nbsp; Stop!&amp;nbsp; Why are you writing a thread pool?&amp;nbsp; Sure it's fun.&amp;nbsp; I've written one or two of those; and other meaningless things like workflow engines.&amp;nbsp; But unless you're a software house, it's unlikely you're doing anyone a favor with such a duplication.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;By the same token, don't do too many "smart" things--I kick myself routinely looking back on a piece of over-engineered code that gets called maybe once a day.&amp;nbsp; "do the absolute simplest thing that could possibly work".&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;But DO put your engineering best into TESTING, then more TESTING.&amp;nbsp; The bulk of your work comes AFTER you are code- and feature-complete.&amp;nbsp; Have you load tested?&amp;nbsp; Stress tested?&amp;nbsp; Soak tested?&amp;nbsp; I'm assuming of course you already had thorough TDD-style unit tests which were run every time you automatically built, at least once a day.&amp;nbsp; This stuff really takes time because &lt;STRONG&gt;it depends on other groups' cooperation.&amp;nbsp; &lt;/STRONG&gt;You have to interface with the infrastructure folks, with management; you're asking for an isolated test-network, with lots of machines and software and setup.&amp;nbsp; You'll have devs and testers hanging out looking glazed poring over perf-mon logs and trace files and dumps.&amp;nbsp; You'll have bleary-eyed coders who aren't used to using LoadRunner writing scripts--and wondering if they're representative of real-life data.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;And before all that--you've added testing hooks, right?&amp;nbsp; You can turn on and off detailed tracing?&amp;nbsp; You have performance counters, dozens of them?&amp;nbsp; You have MSI installers that go BANG and put it in right?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;That's&lt;/STRONG&gt; where the real engineering effort goes.&amp;nbsp; It's not algorithms; those things you find in books for the most part.&amp;nbsp; It's the hard tedious stuff, that stuff above, that counts.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;When You Pay for Expert Advice, HEED IT:&lt;/STRONG&gt;&amp;nbsp; I'm astonished at how&amp;nbsp;many companies will gladly shell out $10,000 a week for consultants, and then blandly ignore their advice; that's one of those "ya outta be fired" sins.&amp;nbsp; Let's pretend there's an adequate screening process for said consultant, and they know what they're talking about--as proven by a track record of customers willing to give testimony, and a list of successful projects.&amp;nbsp; They work for a reputable and preferably the vendor company. Probably would be nice if they're published, too.&amp;nbsp; And be sure they're in their area of expertise--and if they're not, they're willing to admit it and bring in other expertise.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Those things said, you now have an expert.&amp;nbsp; And you're paying for it.&amp;nbsp; Will you listen?&amp;nbsp; People on the team may question the advice, and that's good; the consultant should hear it and ably defend his/her thesis.&amp;nbsp; But when push comes, chances are they're right.&amp;nbsp; If they're not why are you paying ten grand a week??&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;The best part about a vendor consultant--the company's reputation is on the line, not just his/hers.&amp;nbsp; And that company will move mountains to see a good outcome; use that to your advantage!&amp;nbsp; Chances are they actually know how to get the best out of their own products....&lt;STRONG&gt;funny how that works :)&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Man.&amp;nbsp; Couple more posts like this and I'll just be moving right into management.&amp;nbsp; Think I'll plug that jack-thingy back into my head now and jump a couple of skyscrapers....&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=414340" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Ferrari vs. Chevy:  pragmatic engineering</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/05/02/414022.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/05/02/414022.aspx</id><published>2005-05-02T19:20:00Z</published><updated>2005-05-02T19:20:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana&gt;I love cars.&amp;nbsp; It's the thing I'm most likely to spend stupid amounts of money on, and only the guiding hand of my frugal wife keeps me from mortgaging future college funds on a shiny 400HP...whatever.&amp;nbsp; Too many 400HP cars around to count these days--topic for a future blog.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Let's talk software engineering by analogy with engine...er, engineering.&amp;nbsp; This is a rough analogy but it works during two-hour talks where the audience doesn't have time to examine my hand-waving and see where the analogy breaks down :)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Ferrari engines are exquisitely engineered; ground-up development for the most part.&amp;nbsp; They borrow from their F1 experience with exotic piston coatings, high-strength Exotic Alloy Du Jour for connecting rods, sodium-filled or titanium valves, aluminum blocks, you name it.&amp;nbsp; They run insane compression ratios at stupendous RPM's--over 8500 in the latest ones.&amp;nbsp; They reach and surpass what used to be a magical barrier--a specific output of more than 100HP per Liter (nice mixed US/SI measurements).&amp;nbsp; That&amp;nbsp;number's not so impressive against the 200+ that modern motorcycles churn out--but they have a huge advantage, since it's much easier to get high specific output from an engine of smaller sizes.&amp;nbsp; Output decreases as the square of engine dimensions, while mass decreases as the cube.&amp;nbsp; A 4-liter engine making 430 HP is quite an achievement, considering it has to be streetable and last at least 50,000 miles with no major hiccups.&amp;nbsp; F1 is a different game; they're around 300HP/Liter now, but they might as well be turbine engines they're spinning so fast.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;This is&amp;nbsp;the equivalent of finely-crafted C++ with some assembly thrown in for the critical parts.&amp;nbsp; I think of Mike Abrash's book on optimizing code; down at the level of thinking about registers, L1 cache, locality of reference type stuff.&amp;nbsp; Getting that last 0.1%.&amp;nbsp; Worrying about reordering.&amp;nbsp; Thinking about memory barriers.&amp;nbsp; Cursing kernel-user transitions.&amp;nbsp; Pain, pain, and more pain.&amp;nbsp; Building a beach, one grain at a time, with a toothpick.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;By comparison, the venerable Chevy small-block; truly an engineering tour-de-force, but not of the same kind.&amp;nbsp; This thing's been around what, 40, 50 years?&amp;nbsp; It's evolved, but the basic layout is the same.&amp;nbsp; For crying out loud, its camshaft is still nestled between the banks and operates its valves &lt;STRONG&gt;with freakin pushrods!&lt;/STRONG&gt;&amp;nbsp; It's archaic by comparison.&amp;nbsp; &lt;STRONG&gt;And yet&lt;/STRONG&gt;, it is triumphant in every way.&amp;nbsp; Volume, cost, reliability, total output.&amp;nbsp; Granted, it doesn't reach the Ferrari's high specific output in streetable trim.&amp;nbsp; They're in the neighborhood of 70 HP/Liter; almost lazy by modern standards.&amp;nbsp; But it gets better gas mileage--even though they're 5.7 liters against the Ferrari's 3.6 or 4-ish.&amp;nbsp; They rev less; less frictional waste.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Why is the Chevy the hands-down winner, &lt;/STRONG&gt;when technically the highly-tuned engine is superior?&amp;nbsp; &lt;STRONG&gt;PRAGMATISM&lt;/STRONG&gt; and &lt;STRONG&gt;STANDARDIZATION&lt;/STRONG&gt;.&amp;nbsp; The Chevy has had decades of effort poured into it, millions of man-hours from both the actual developers and the vast hordes of third-party developers.&amp;nbsp; It's a standard.&amp;nbsp; Its engineering weaknesses have been conquered through sheer brute force over years, so you hardly care anymore.&amp;nbsp; If you can ignore the thought of pushrods banging up and down at 7000 RPM, your Corvette Z06 sure does a number on the Ferrari next to you.&amp;nbsp; Doesn't sound as good.&amp;nbsp; But it's about 1/4 the cost, and if said pushrods fail you won't shed tears too long.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Verdana&gt;So you say: "What does this have to do with CODE, and why are you not taking Lithium?" &lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Well it upsets my tummy, on the second question.&amp;nbsp; On the first, this has everything to do with Web Services,&amp;nbsp;YAGNI, KISS, and HST.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Web Services are bandwidth hogs compared to binary protocols.&amp;nbsp; Their serialization models leave a bit to be desired.&amp;nbsp; They are a little or quite a bit slower than binary at present.&amp;nbsp; &lt;STRONG&gt;But who cares!&lt;/STRONG&gt;&amp;nbsp; Web Services are the Chevy Smallblock of the RPC world.&amp;nbsp; Their advantages are so compelling that we will though sheer brute engineering force MAKE them work.&amp;nbsp; Their "specific output", perhaps expressed as "objects/kilobyte", will probably never match a binary protocol.&amp;nbsp; &lt;STRONG&gt;But who cares!&lt;/STRONG&gt;&amp;nbsp; Over time, every vendor, every software house, will become so invested in the magic of Web Services that we'll get around the limitations.&amp;nbsp; Or live with them.&amp;nbsp; I don't hear Corvette owners boo-hoo'ing over pushrods; I do see them able to send their kids to college on the $120K they saved!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;YAGNI--"Ya Ain't Gonna Need It"--and KISS, HST ("Hooking S*** Together") are what most of us do for corporate and even ISV development.&amp;nbsp; We're not interested in the last 0.1%&amp;nbsp; We love elegance, but if it costs 4X as much it's out the door.&amp;nbsp; What we need is &lt;EM&gt;pragmatic, robust, standardized engineering.&lt;/EM&gt;&amp;nbsp; I hate to say it, because it's Not The Developers Way, but cheapest usually IS best.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Man did I ever swallow the Red Pill today.&amp;nbsp; I hope I'll soon return to my blue-pill nirvana of fine software engineering unconstrained by practicality, cost, schedule, or maintenance.&amp;nbsp; 9000 RPM code; titanium con-rods and molybdenum piston skirts.&amp;nbsp; Nope, the pushrods and iron win over time--management was right after all.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a52a2a size=4&gt;:)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a52a2a size=1&gt;P.S. these analogies are TOTALLY my opinion, do not reflect at all on the excellent (in their own ways) engines/makers, and have nothing whatsoever to do with my employer. My views are my own, and they are insane.&amp;nbsp; I do not speak for my employer.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=414022" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>More RTCClient API 1.3</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/04/28/413165.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/04/28/413165.aspx</id><published>2005-04-28T22:04:00Z</published><updated>2005-04-28T22:04:00Z</updated><content type="html">&lt;DIV class=commentssubhead&gt;&lt;FONT face=Verdana&gt;Hassan writes:&lt;/FONT&gt;&lt;/DIV&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;DIV class=commentssubhead&gt;Wednesday, April 27, 2005 7:57 PM by &lt;A id=_ctl0__ctl0__ctl0__ctl0__ctl0__ctl0_Comments__ctl0_Comments__ctl1_NameLink title=Anonymous target=_blank&gt;Hassan Khawaja&lt;/A&gt; &lt;/DIV&gt;
&lt;H4 class=altcomment&gt;&lt;A id=_ctl0__ctl0__ctl0__ctl0__ctl0__ctl0_Comments__ctl0_Comments__ctl1_PermaLink title=permalink HREF="/methylamine/archive/2005/04/13/407866.aspx#412789"&gt;&lt;FONT color=#770000&gt;#&lt;/FONT&gt;&lt;/A&gt; &lt;SPAN&gt;re: Real-Time, Server Push, Pub/Sub Network Apps in .NET--Buellar? Buellar?&lt;A name=412789&gt;&lt;/A&gt;&lt;/SPAN&gt; &lt;/H4&gt;
&lt;DIV class=commentsbody&gt;I am dealing with a somewhat related issue, basically creating an AD employee search directory app in asp.net. I want to be able to show the users' presence next to their names. &lt;BR&gt;We are using LCS2005, and I am trying to develop using RTC 1.3 in C#. &lt;BR&gt;&lt;BR&gt;So far I am pretty much stuck with getting COMException errors with some weird HRESULT codes. Interestingly a winforms app using the same code works just fine. It's the RTPresence app in the SDK samples. &lt;BR&gt;&lt;BR&gt;Have you been able to write something for the web using RTC 1.3? I'd appreciate if you could guide me in the right direction. &lt;BR&gt;&lt;BR&gt;Thanks so much, &lt;BR&gt;Hassan. &lt;BR&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;DIV class=commentssubhead&gt;&lt;SPAN class=commentspan&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;and I replied:&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV class=commentssubhead&gt;&lt;SPAN class=commentspan&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;DIV class=commentssubhead&gt;&lt;SPAN class=commentspan&gt;&lt;/SPAN&gt;Thursday, April 28, 2005 3:04 PM by &lt;A id=_ctl0__ctl0__ctl0__ctl0__ctl0__ctl0_Comments__ctl0_Comments__ctl2_NameLink title=methylamine HREF="/Profile.aspx?UserID=3903" target=_blank&gt;&lt;FONT color=#770000&gt;methylamine&lt;/FONT&gt;&lt;/A&gt; &lt;/DIV&gt;
&lt;H4 class=comment&gt;&lt;A id=_ctl0__ctl0__ctl0__ctl0__ctl0__ctl0_Comments__ctl0_Comments__ctl2_PermaLink title=permalink HREF="/methylamine/archive/2005/04/13/407866.aspx#413149"&gt;&lt;FONT color=#770000&gt;#&lt;/FONT&gt;&lt;/A&gt; &lt;SPAN&gt;re: Real-Time, Server Push, Pub/Sub Network Apps in .NET--Buellar? Buellar?&lt;A name=413149&gt;&lt;/A&gt;&lt;/SPAN&gt; &lt;/H4&gt;
&lt;DIV class=commentsbody&gt;Hey Hassan-- &lt;BR&gt;&lt;BR&gt;Yeah that's kinda what I'm talking about--the non-zero HRESULTS come flyin' back and it's just poopy. &lt;BR&gt;&lt;BR&gt;You've gotta pay attention to which thread you created the original instance of IRTCClient2 on; never create or pass outside that thread. &lt;BR&gt;Technically the team says they've fixed the marshalling but I can't make it work in C#, and I don't want to drop into C++ just for a wrapper. &lt;BR&gt;&lt;BR&gt;I created the Interop assembly with the RTCCOreLib.dll; just use the RTCCORE.IDL file in the SDK IDL directory. DON'T use the one in System32; remember this is a redirected DLL so the actual 1.3 dll is in some weird SxS directory. &lt;BR&gt;&lt;BR&gt;Also, be sure the .MANIFEST file is correct and available in your BIN dir. &lt;BR&gt;&lt;BR&gt;Hope this helps!&lt;/DIV&gt;
&lt;DIV class=commentsbody&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;I do hope it helps; I spent quite a few hours getting it all set up.&amp;nbsp; The basic steps to using RTCClient API v1.3 from C# are:&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;1)&amp;nbsp; generate an interop file from the RTCCORE.IDL file in "C:\Program Files\RTC Client API v1.3 SDK\SDK\IDL", call it a good name like "Interop.RtcCore.dll"&lt;/FONT&gt;&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;how to do step one:&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;use "midl rtccore.idl" to get a tlb&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=commentsbody&gt;&lt;FONT face=Verdana&gt;use "tlbimp rtccore.tlb /out:Interop.RtcCore.dll" to get the interop assembly; optionally, sign it at this time too&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;2)&amp;nbsp; reference said interop assembly from a C# project&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;3)&amp;nbsp; Now the delicious part; you must create this from an STA thread, ALWAYS, and you must never pass references to the objects you create outside that thread's context.&amp;nbsp; This means no delegates on background threads, no putting references in a collection that can be hit by other threads,&amp;nbsp; etc etc.&amp;nbsp; It's quite painful.&amp;nbsp; I created and managed said thread as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_staThread = new Thread( new ThreadStart( this.InitializeInternal ) );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_staThread.ApartmentState = ApartmentState.STA;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_staThread.IsBackground = true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_staThread.Name = String.Format( "RTCClient_STAThread_{0}", g_instanceCount );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_staThread.Start();&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;4)&amp;nbsp; on that thread you need to initialize an instance of IRTCClient2 as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Run the required message loop to pump messages from the RTC RtcWrapper&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;&amp;nbsp;COM object to this thread.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_context = new ApplicationContext();&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; trap messages with our filter, looking for WM_PUMPRTCMESSAGE--which &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; we'll redirect to invoke a delegate&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Application.AddMessageFilter( this );&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; create the RTCClient instance and initialize it&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RTCClientClassInitializeEx( INITIALIZEEX_PARAMS_BITMASK );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SetEventFilter( EVENT_FILTER_BITMASK );&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//MSTUART:&amp;nbsp; moved here from before new context above 04132005 to mitigate race when &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; outside, initializing thread gets signalled we're ready too soon.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; OK all done, signal to whomever's waiting in Initialize()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_completedWaitHandle.Set();&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; start message loop on this STA thread&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Application.Run( m_context );&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;All that goo above is done _on the STA thread_!&amp;nbsp; And the initializeEx is called as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_client = new RTCClientClass();&lt;/P&gt;
&lt;P class=commentsbody&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_client.InitializeEx( rtcifConstantsBitMask );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; snag events&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_client.IRTCEventNotification_Event_Event += new IRTCEventNotification_EventEventHandler( ClientEventHandler );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; set up to listen&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_client.ListenForIncomingSessions = RTC_LISTEN_MODE.RTCLM_BOTH;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp; media types&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//m_client.SetPreferredMediaTypes( RTCConstants.RTCMT_ALL, true );&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;5)&amp;nbsp; Now&amp;nbsp;if you want to call this from&amp;nbsp;many threads, you'll have to create&amp;nbsp;the plumbing for marshalling&amp;nbsp;calls onto your brand-new nifty&amp;nbsp;Windows message&amp;nbsp;loop you created above.&amp;nbsp; Since you're an IFilter, you get first chance at those messages; look for ones that pertain to you, and do only them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;It's a little painful, really.&amp;nbsp; I'm looking&amp;nbsp;forward to nice friendly&amp;nbsp;wrappers or rewrites for this.&amp;nbsp; Not having them, I had to write my own.&amp;nbsp; When it came time to do the server,&amp;nbsp;I had to think a bit about limiting the number of sessions per RTCClient instance--sending is O(n).&amp;nbsp; So I have many&amp;nbsp;instances of my wrapper (which encapsulates the STA and serializes access from outside threads),&amp;nbsp;each of which is limited to 20&amp;nbsp;sessions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;It all works but it feels unnatural.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;At the end of the day, our web service polling implementation offers so many advantages--scalability, ease of development, ease of maintenance, traverses Firewalls and NAT, etc. etc. etc. that it's probably the way we'll go.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;We had already implemented a Heartbeat-Sequence type 'reliability layer' to give some guarantee of message delivery, and we'd designed for a plug-in model; substituting any technology is easy with this design.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;Frankly I think most solutions that need to be WAN-friendly--that is, NAT, firewall, no incoming connections, etc--will be better off with HTTP(s) polling type implementations.&amp;nbsp; Inside the LAN it's a totally different picture; but I hate "asymmetric" solutions, I'd much rather double up my engineering effort on one solid solution than have one for inside and one for outside to gain some fractional speed advantage inside.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;Given how monstrously scalable web servers have become, and given the great gobs of bandwidth available--remember all that dark fiber we laid in the 90's?--it Just Works.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;It's not quite "YAGNI"--Ya Aint' Gonna Need It--but it's close.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=commentsbody&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=commentsbody&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=413165" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Real-Time, Server Push, Pub/Sub Network Apps in .NET--Buellar?  Buellar?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/04/13/407866.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/04/13/407866.aspx</id><published>2005-04-13T17:50:00Z</published><updated>2005-04-13T17:50:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;My best friend's boyfriend's cousin said she heard it passed out in the 31 flavors last night.&amp;nbsp; Guess it's pretty bad.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Yep this is awful.&amp;nbsp; It has to be the most under-served, and one of the most desirable, features in enterprise applications...YET, there are relatively few good options.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;All we need here is a server which answers subscription requests to "topics", enrolling said client in that "topic" in a pub-sub way.&amp;nbsp; Then the server sends out messages on those topics either to everyone (who filter locally) or specifically to its subscribers.&amp;nbsp; It's also sending out heartbeats with sequence numbers so clients know when they've missed something, and can request the missed set.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;It's just NOT THAT HARD, at least in the trivial case.&amp;nbsp; But let's start adding constraints:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;low client footprint, ideally NO extra install except .NET and perhaps an interop assembly that uses base-OS features&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;must work across WAN&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;WAN may be highly latent, deliver things out of order, etc.&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;messages will not be more frequent than one per second, time resolution (one second) is fixed&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;*MAY* have to communicate through NAT on the client end&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;*MAY* have to negotiate firewalls, though this is a very distant scenario&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face=Verdana size=2&gt;server must be absolutely reliable when serving up to 1000 simultaneous clients on a dozen or so "topics"&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Now we've got some issues.&amp;nbsp; In fact they're kinda nasty; so nasty that we're seriously contemplating a web service polling solution.&amp;nbsp; It just WORKS.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;SO:&lt;/STRONG&gt; What have we been trying?&amp;nbsp; The best candidate is SIP, using the RTCClient API, v1.3.&amp;nbsp; But sheesh.&amp;nbsp; It's a really really steep hill, mostly because a)&amp;nbsp; it's a COM object, so there's some Interop fudge that happens and b)&amp;nbsp; &lt;STRONG&gt;it's an STA thread model&lt;/STRONG&gt;, which is just &lt;EM&gt;super-poopy&lt;/EM&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;I've written wrapper upon wrapper; first, there's the wrapper that creates the actual IRTCClient2 instance on an STA thread; that thread, BTW, creates and enters its own application context via Application.Run().&amp;nbsp; Now we've got a messaging loop; step 2, we have to implement IMessageFilter, register our own message type, and intercept the message loop watching for it.&amp;nbsp; Oh yeah--if the message is intended for us, we then invoke the delegate that was passed to one of our own internal methods.&amp;nbsp; We just do the simple thing and force the outside calling thread to block while we work, and return the results on a private member which the caller picks up on its way out the door.&amp;nbsp; We could have gone all elegant and done a purely asynch with a callback for notification but I've spent too much time on it already.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;All standard com/win32 stuff, but really a rude shock when you've had the luxury of doing pure .NET for years.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Then there's a huge management layer on top of all this; how many remote clients per RTC instance, how many RTC instances; &lt;STRONG&gt;then&lt;/STRONG&gt; there's the reliability layer that does sequences, heartbeats, missed message retrieval and history storage.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;NOW do you see why I'm ready to throw up my hands and say "&lt;STRONG&gt;Enough already!&amp;nbsp; Let's just do a gosh-darn POLLING implementation!!~%!$%!$$##&lt;/STRONG&gt;"&amp;nbsp; (the last part is mumbled curses)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Verdana size=2&gt;Question for dear readers:&amp;nbsp; how have ya'll dealt with this need for real-time pub/sub server-push type communication in .NET?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=407866" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Fun Variant on State Design Pattern</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2005/04/10/406941.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2005/04/10/406941.aspx</id><published>2005-04-10T20:41:00Z</published><updated>2005-04-10T20:41:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana&gt;OK so I'm working on quite a fun project; it's a proof of concept for a near-real-time, pub-sub, server to client push type communicaton subsystem.&amp;nbsp; Phew.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Essentially it's a big fat wrapper around a few candidate technologies including SIP, a.k.a. our RTCClient API, v1.3.&amp;nbsp; &lt;/FONT&gt;&lt;FONT face=Verdana&gt;THAT&amp;nbsp; (RTCClient) will be the subject of another blog I'm sure.&amp;nbsp; Getting&amp;nbsp;a multithreaded .NET server app to manage and use multiple STA-threaded COM objects was quite fun...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;The heart of the wrapper is a quasi-reliable-messaging protocol.&amp;nbsp; Because the underlying communication API's don't all offer reliability, we had to engineer our own.&amp;nbsp; It doesn't have to be as bulletproof as MSMQ or other reliable systems; it just has to be Pretty Darn Good.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I went with the obvious solution; messages with sequence numbers, and a heartbeat system telling all clients on a regular schedule what the latest sequence number for a topic is.&amp;nbsp; Clients can detect missed messages and request historical updates.&amp;nbsp; There's some complexity as we have to account for out-of-order receiving, rolling over Int32.MaxValue sequence number cleanly, etc.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT face=Verdana&gt;So where's the State Pattern?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Right, enough preamble.&amp;nbsp; I had this really nasty method with a TON of if-then's, some with composite tests--lots of &amp;amp;&amp;amp;'s and ||'s scattered around.&amp;nbsp; I **FEAR** such methods from painful experience going back to age 10 and writing a PacMan in assembly.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I busted out C#Refactory (&lt;A href="http://www.xtreme-simplicity.net/"&gt;http://www.xtreme-simplicity.net/&lt;/A&gt;, best 100 bucks you'll ever spend on a coding tool).&amp;nbsp; Sure enough, the Cyclomatic Complexity of said method was 10--and 10 is a magic number.&amp;nbsp; That is the cyclomatic complexity at which it is almost _certain_ you will&amp;nbsp;create a bug when modifying the method.&amp;nbsp; And, the fates help that poor developer who comes after me and has to mentally compile that pile of doo I wrote!!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Here's where the State pattern comes in.&amp;nbsp; Separate state representation from behavior, and allow flexibility and extensibility of the system.&amp;nbsp; In fact it just recognizes the key fact:&amp;nbsp; those long-winded if-then methods we hate to debug are in fact finite state machines, and should be written that way...Take a peek at &lt;A href="http://msdn.microsoft.com/msdnmag/issues/01/07/patterns/"&gt;http://msdn.microsoft.com/msdnmag/issues/01/07/patterns/&lt;/A&gt;&amp;nbsp;for a great example of when/how to use State.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;My case wasn't really amenable to the iterative type of State machine there though.&amp;nbsp; Most State implementations assume the vending machine analogy, or the bank account status, etc.&amp;nbsp; You send messages to the FSM and it migrates between nodes in response.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Mine had to work with a known set of inputs, present from the outset.&amp;nbsp; I had to get the information--the "language" I'd feed the FSM--and ask the FSM to find the right output state for that input right away.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;So I created a State abstract base class, with properties to describe the State--in this case, HaveMissedMessages, IsBadState, and TrueSequenceNumber.&amp;nbsp; Those three describe fully what conditions we can be in.&amp;nbsp; See the abbreviated source below.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;But here's the departure from usual State implementations:&lt;/STRONG&gt;&amp;nbsp; I'm going to call it &lt;EM&gt;&lt;STRONG&gt;Statically Found State&lt;/STRONG&gt;&lt;/EM&gt; because I'm naming-impaired:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I don't pass my Context into the State.&amp;nbsp; In fact State knows _nothing_ about its users; most State patterns have to know about their context--their user, the behavior thing above them.&amp;nbsp; They also often mimic all the methods of the context; so their signature can be quite cluttered.&amp;nbsp; They don't JUST have the properties that define the current State.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Instead I have a static method defined on the State base and all derivatives, "&lt;STRONG&gt;FindOutputState&lt;/STRONG&gt;".&amp;nbsp; Each class implements its own version of FindOutputState.&amp;nbsp; Each class knows what inputs correspond to which of its immediate neighbor nodes.&amp;nbsp; It then calls FindOutputState on the appropriate next neighbor in the graph.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;That next neighbor, again, knows only about its immediate neighbors and what inputs would transition to one of them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Eventually you have a final state with no exits--you've gone to ground and the FSM ends.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;In this system the output states are InSynchState--we have not missed any messages--OutOfSynchState--we've missed some but we're recoverable--and BadState, which happens when you're so far off it's ridiculous.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;The inputs are InternalSequence, which is what we believe is our sequence, ExternalSequence--what we received--and whether the message was a Message or a Heartbeat.&amp;nbsp; The latter is important because the semantics are subtly different.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;I abbreviated the code below a little 'cause this editor blows every CRLF into a fat double-spaced linefeed.&amp;nbsp; The important parts--implementations of FindOutputState--are bold and indented.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Why I Love the State Pattern:&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;It&amp;nbsp;separates state from behavior.&amp;nbsp; It formally expresses each node of the FSM, rather than burying them in the scope of some if-then clause.&amp;nbsp; I can&amp;nbsp;add new States and inject it between&amp;nbsp;existing nodes with little effort.&amp;nbsp; The very existence of each State derivate class verbalizes that node formally, calling out an anticipated&amp;nbsp;intermediate.&amp;nbsp; &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Note that the most complex FindOutputState has a CC of only 4--much easier to NUnit test.&amp;nbsp; In fact using the State pattern is wonderful for TDD, because you can test your FSM without any of the crufty context you usually need to inject to get at those long if-then-elseif poopy methods.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;STRONG&gt;Question&lt;/STRONG&gt;:&amp;nbsp; is this a new pattern?&amp;nbsp; Or am I totally deluded?&amp;nbsp; Do the departures from the usual State implementation seem valuable?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Here's the code:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=1&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana color=#0000ff&gt;public&lt;/FONT&gt;&lt;FONT face=Verdana&gt; State(){}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;&lt;FONT color=#808080&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;const&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; ROLLOVER_THRESHOLD = &lt;FONT color=#ff0000&gt;10000&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt;; &lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; _trueSequenceNumber = &lt;FONT color=#ff0000&gt;0&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; _haveMissedMessages = &lt;FONT color=#0000ff&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; _isBadState = &lt;FONT color=#0000ff&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; State FindOutputState( &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; isMessage, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; intSeq, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; extSeq )&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;State state = &lt;/FONT&gt;&lt;FONT face=Verdana color=#0000ff&gt;null&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;if&lt;/FONT&gt;&lt;FONT face=Verdana&gt;( isMessage )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;state = MessageState.FindOutputState( isMessage, intSeq, extSeq );&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;else&lt;/FONT&gt;&lt;FONT face=Verdana&gt; &lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;state = HeartBeatState.FindOutputState( isMessage, intSeq, extSeq );&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; state;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; HaveMissedMessages &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; IsBadState&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; TrueSequenceNumber&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt; 
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;internal&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;sealed&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;class&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; MessageState : State&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana color=#0000ff&gt;public&lt;/FONT&gt;&lt;FONT face=Verdana&gt; MessageState(){}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; State FindOutputState( &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; isMessage, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; intSeq, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; extSeq )&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;// easy one first: all inputs that lead to InSynchState:&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;if&lt;/FONT&gt;&lt;FONT face=Verdana&gt;( intSeq == extSeq )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; InSynchState.FindOutputState( isMessage, intSeq, extSeq );&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;// external sequence is internal plus one, basically OK&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;( intSeq == ( extSeq - &lt;FONT color=#ff0000&gt;1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; ) )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; InSynchState.FindOutputState( isMessage, intSeq, extSeq );&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;// second easiest next; out of synch by more than one difference&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;( intSeq &amp;lt; ( extSeq - &lt;FONT color=#ff0000&gt;1&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; ) )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; OutOfSynchState.FindOutputState( isMessage, intSeq, extSeq ); &lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;// OK now for the rollovers; &lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;// if internal is more than external pass off to rollover handler&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;if&lt;/FONT&gt;&lt;FONT face=Verdana&gt;( intSeq &amp;gt; extSeq )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; MessageRolloverState.FindOutputState( isMessage, intSeq, extSeq );&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; BadState.FindOutputState( isMessage, intSeq, extSeq );&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=1&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;&lt;FONT color=#808080&gt;///&lt;/FONT&gt;&lt;FONT color=#008000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;&amp;lt;summary&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;&lt;FONT color=#808080&gt;///&lt;/FONT&gt;&lt;FONT color=#008000&gt; Leaf node. Internal was behind external by a recoverable amount.&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;FONT size=2&gt;&lt;FONT color=#808080&gt;///&lt;/FONT&gt;&lt;FONT color=#008000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;&amp;lt;/summary&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;internal&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;sealed&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;class&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; OutOfSynchState : State&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana color=#0000ff&gt;public&lt;/FONT&gt;&lt;FONT face=Verdana&gt; OutOfSynchState(){}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; State FindOutputState( &lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt; isMessage, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; intSeq, &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Verdana&gt; extSeq )&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;{&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#008000&gt;&lt;FONT face=Verdana size=2&gt;// leaf node; we are out of synch but recoverable&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;State state = &lt;/FONT&gt;&lt;FONT face=Verdana color=#0000ff&gt;new&lt;/FONT&gt;&lt;FONT face=Verdana&gt; OutOfSynchState();&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;state.HaveMissedMessages = &lt;/FONT&gt;&lt;FONT face=Verdana color=#0000ff&gt;true&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana&gt;state.IsBadState = &lt;/FONT&gt;&lt;FONT face=Verdana color=#0000ff&gt;false&lt;/FONT&gt;&lt;FONT face=Verdana&gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;state.TrueSequenceNumber = extSeq;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Verdana color=#0000ff&gt;return&lt;/FONT&gt;&lt;FONT face=Verdana&gt; state;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=406941" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>More on XBox Live</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2004/11/30/272603.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2004/11/30/272603.aspx</id><published>2004-12-01T01:52:00Z</published><updated>2004-12-01T01:52:00Z</updated><content type="html">&lt;p&gt;&lt;font face="Verdana"&gt;Wow!&amp;nbsp; Lots of comments/emails from that last post.&amp;nbsp; Seems others have been trolled on Live too.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;So there's a positive too:&amp;nbsp; there are a host of decent, very nice people playing Halo 2 on Live.&amp;nbsp; People who have the courtesy to say "good game" even after they trounce you...or get trounced.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;It must be a difficult problem for the Live admins.&amp;nbsp; (totally uninformed ranting to follow, which does not reflect Microsoft's position only my own, and does not contain any inside information)&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;The Live folks probably work under several constraints:&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;*&amp;nbsp; they have to increase the # of subscriptions&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;*&amp;nbsp; stupid people&amp;nbsp;cause regular people to leave&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;*&amp;nbsp; stupid people also pay for their subscriptions&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;*&amp;nbsp; feedback is subjective; who knows what feedback I've got?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;So they have to balance booting with subscription counts, keeping in mind that a certain number of judicious bootings will actually increase the number of Live subscriptions--by making it a more pleasant place to be.&amp;nbsp; &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;They have to keep false positives low--unfairly booting a decent person due to negative feedback probably left by trolls is a bad thing.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;Ultimately the most reliable boot-decider would be for Live admins to sit in and listen to games.&amp;nbsp; I don't know how many Live accounts there are, but it's millions--so they can't all be monitored.&amp;nbsp; Perhaps they listen to the accounts with the most negative feedback to decide; I don't know.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;The constraints above sound like a system highly amenable to statistical analysis.&amp;nbsp; I don't know if the Live team has taken a rational modeling approach to it and set it up as an optimization problem.&amp;nbsp; Seems doable though; I'll have to ask my statistician PhD buddy John how hard/easy it would be.&amp;nbsp; I'm just a dumb biochemist/doctor/developer :)&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;Or, how about a code solution?&amp;nbsp; Perhaps a voice-recognition bot that caught racial slurs and other nastiness and flagged the account?&amp;nbsp; It sounds Orwellian, but it _is_ a subscription service--not the town square.&amp;nbsp; After a very few flaggings the abusive user would get a sysadmin message next time they logged into Live warning them...&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;&lt;strong&gt;Live Team--if ya'll are listening, I'm ready to code.&lt;/strong&gt;&amp;nbsp; I want Live to be the finest online gaming, period.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=272603" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Stupid people on XBox Live</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2004/11/30/272518.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2004/11/30/272518.aspx</id><published>2004-11-30T23:33:00Z</published><updated>2004-11-30T23:33:00Z</updated><content type="html">&lt;p&gt;&lt;font face="Verdana"&gt;DUDE!&amp;nbsp; What is up with the troglodyte faction playing Halo 2 some nights?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;Recently me and three of my friends were verbally assaulted by two separate groups.&amp;nbsp; One group kept referring to us as "n******" (rude slang for African-American).&amp;nbsp; I was flattered, but I realize they meant it as an invective; this really puzzled me though.&amp;nbsp; Honestly, people, who talks like that?&amp;nbsp; Where do these rock-crawling, slime-covered cretins breed?&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;Another group loudly yelled that we were of a certain religious heritage.&amp;nbsp; Well, I'd be proud to be Jewish.&amp;nbsp; But again, I think their intent was derogatory.&amp;nbsp; I'll just take it as a complement, and keep trying to be as funny as Seinfeld.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;These incidents repeat in various forms about once a night.&amp;nbsp; I guess out of the dozen or so games we play every night that's not so bad, but I'd love to avoid the kind of person who spews nastiness.&amp;nbsp; A little vulgarity in the heat of the moment is to be expected; after all, these ARE life-and-death struggles.&amp;nbsp; But personal invective?&amp;nbsp; I thought I'd left that behind in grade school.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;My friend Chris has a good idea; he'd like Live to have "certified gamertags" much like good-seller ratings on eBay.&amp;nbsp; This way, I could choose not to play with anyone with X amount of negative feedback.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;Meantime, I encourage everyone on Live to use the feedback feature and leave negative feedback for trolls, troglodytes, orcs, and goblins whenever they appear.&amp;nbsp; I believe the Live team does eventually ban those idiots...the faster, the better.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font face="Verdana"&gt;P.S. To the level 23, 24, and 25 people who start new clans every night and play at clan level 5--you are NOT cool.&amp;nbsp; Now go do your homework or read a book tonight.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=272518" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry><entry><title>Software and the UniMog</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/methylamine/archive/2004/11/19/267037.aspx" /><id>http://blogs.msdn.com/methylamine/archive/2004/11/19/267037.aspx</id><published>2004-11-20T00:53:00Z</published><updated>2004-11-20T00:53:00Z</updated><content type="html">&lt;font face="Verdana"&gt;Coming soon...&lt;/font&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=267037" width="1" height="1"&gt;</content><author><name>methylamine</name><uri>http://blogs.msdn.com/members/methylamine.aspx</uri></author></entry></feed>