Scott Hanselman

10 Awesome Things I Remember About Computers

March 5, '09 Comments [124] Posted in Musings
Sponsored By

imageGreat fun on Twitter today as I asked when folks went online for the first time in their lives. The answers were marked with the #goonline hashtag. Mostly just random reminiscing but it got me remembering the fun we had "suffering" in the olden days.

The best part, of course, is that my "olden days" aren't yours. Maybe you learned with punch cards or maybe your first machine was a *gulp* Pentium. Either way, it was different and now it's a part of you.

Here's a totally random, completely useless collection of things I remember doing/accomplishing/working on while I was "coming up" in computers.

What's your list? Is it a list of suffering? Of joy? Of great fun? Of accomplishment?

What's 10 Awesome Things You Remember About Computers?

QEMM Using QEMM to rearrange all the TSRs in upper and extended memory. Then getting better than QEMM and using intuition to get better results.


sc0003b3d4 Stacker'ing a 40 meg MFM hard drive. Upgrading to DR-DOS and getting compression for free.


808019844_b1946eab8e Running a multi-node WildCAT! BBS under DesqView. Later running it under OS/2, then OS/2 Warp.


s_PC1553-2 Upgrading my PC/XT by meticulously adding dozens of DIPs to an QUADBOARD expansion.


200px-Squareholepunch Using a standard paper hole punch to punch another write-protect notch in a 5 1/4" floppy to make it double-sided.


mus_128 Telling everyone to be quiet so the acoustic coupler on a 300 baud modem could do its thing.


tape Using a regular cassette tape to play games on a Commodore Vic 20. LOAD "*", 1, 1


asciiart Printing out 40+ page or more giant-posters of Mr. Spock created entirely in ASCII on a TSR-80 and a 9-pin dot matrix printer. It took hours.


compute Typing in games from the back of COMPUTE! magazine. I ended up hiring kids from down street to read the long list of HEX values and CRC codes to me.


pclip_compute_feb86 Buying a printer to work with PaperClip and having to type the printer's control codes directly into the application.


What's yours, Dear Reader?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Quake Live Review and Rant - Why is this interesting?

March 2, '09 Comments [34] Posted in Gaming
Sponsored By

So I installed and have been playing QuakeLive. Here's the Review part. It's fun. It's Quake. Fast, pretty, twitchy, fun. Quake. Good fun.

Here's the Rant part. I'm having trouble understanding is why this is interesting in any way?

Folks on the 'tubes are saying, "OMG, this is a Browser-based game?"

To say, browser-based game, to me, implies effortless installation. More importantly, it also implies a reason to be in the browser. See the screenshot below? That's the MSI installer I ran as Admin.

InstallingQuakeLive

See this screenshot? That's IE requesting permission to run this plugin. There's a separate MSI if you want to run it in Firefox. I download and installed both installers separately.

image

Here's a sample error message:

** GLW_CreateWindow: could not register window class
Please report the the problem you encountered on the Quake Live forums.
You must reload the web page to make this display go away.

A web (or web-enabled) app that doesn't phone home with errors? Hm. Doesn't seem like a web app to me.

See this screenshot? That's my %appdata% folder with 266 MEGS downloaded. It gets downloaded in the background while you "train." Why do you think they train you for 10 minutes in a single level? It's because they are downloading the other 1/4 gig of content.

QuakeFolder

I'm sorry, but this is a re-imagining of Quake III Arena, compiled as a DLL and running inside my browser. It's the same PAK file concept and format that you (possibly) remember from ten years ago. Yes, 1999.

Yes, there's social aspects, background content delivery, easy multi-player matching, but why is this a DLL living inside the browser's memory space and not an EXE that jumps out of the browser? Do I want something that I think of as a browser plugin downloading 256megs+ of content for me? Why is no one pointing out that the emperor frag-fest has no clothes?

Apparently this is interesting to the young people today because the ones playing Quake Live because they weren't alive when Quake was released originally.

I would rather that a game company like ID spend more time really innovating in the gaming engine space (and I know they are), rather than repackaging the same game in different ways for a decade.*

Quake Live is NOT an interesting game. There are more interesting ways to distribute games that have been working nicely for me since 2003. GuildWars is another GREAT example. It was a <1meg EXE to bootstrap and streamed the levels you needed. There's no reason for QuakeLive to be shoe-horned into a browser plugin.

Now I'm off to delete 256 megs of Quake III from %AppData%\LocalLow\id Software\quakelive\home\baseq3.

End of rant. Move along.

*Quake and its four sequels, Quake II, Quake III Arena, Quake 4, and Enemy Territory: Quake Wars

Technorati Tags:

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Experiencing ALT.NET Seattle 2009 Open Spaces

March 2, '09 Comments [5] Posted in Back to Basics | Learning .NET | Musings | Open Source | Screencasts
Sponsored By

ALT.NETLogo I'm up in Seattle at the ALT.NET Open Space (group DL) and the MVPSummit. "Open Space" is a technique to hold self-organizing conferences. ALT.NET conferences have always been Open Spaces, and if you haven't gone an Open Space conf (of any kind) I recommend you check it out. This is my third (?) ALT.NET conference, and sixth Open Space conference and I always enjoy it more than larger shows.

 Martin Fowler says this about Open Space:

The unusual (and powerful) thing about Open Space is that you don't pre-plan a list of activities and speakers. Instead you provide a basic skeleton of time and space, and the attendees figure out what actually happens. The result is a more participative and energetic event.

What is ALT.NET?

In April of 2007, David Laribee coined the phrase ALT.NET after reading a post by Scott Bellware about the NHibernate Mafia. The core message David was keying off of was the maintainability of a software solution and not the tools involved in creating it.
ALT.NET means many things to many people and the debate will continue about what it means to you.
David proposed ALT.NET signifies:

  1. You’re the type of developer who uses what works while keeping an eye out for a better way.
  2. You reach outside the mainstream to adopt the best of any community: Open Source, Agile, Java, Ruby, etc.
  3. You’re not content with the status quo. Things can always be better expressed, more elegant and simple, more mutable, higher quality, etc.
  4. You know tools are great, but they only take you so far. It’s the principles and knowledge that really matter. The best tools are those that embed the knowledge and encourage the principles (e.g. Resharper.)

Robert Scoble introduced me to Kyte.TV last week after he moved a Twitter conversation we were having out of the constrained space of Twitter and into a live video stream with a chat window. As an experiment I recorded a "Hanselminutes Live" using Kyte and it was pretty fun. Fast forward to ALT.NET a week later and I'd forgotten about this. Then I noticed a number of folks on Twitter saying "wish we were there!" I had my webcam with me so I started streaming the sessions I was attending live using Kyte.

Nate Kohari and Ben Scheirman also started recording. Here's the extremely raw video we ended up with. We're still learning, so there's audio and video problems, so set your expectations LOW.

PhotosFromALT.NETScott - ALT.NET Recorded .NET Sessions

Ben - Recorded ALT.NET Sessions

Nate - Recorded ALT.NET Sessions

You can also click the "Shows tab in the embedded interface below:

  Blog posts about ALT.NET Seattle 2009:

Enjoy!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 151 - Fit and Fitness with Ward Cunningham and James Shore

February 28, '09 Comments [7] Posted in Podcast | Tools
Sponsored By

WardCunninghamMy one-hundred-and-fifty-first podcast is up. Ward Cunningham is the creator of the Wiki, and the creator of the "Fit" testing framework. James Shore is the coordinator of the Fit project, an agile coach and the author of The Art of Agile Development.

JamesShoreYou may have heard the terms "Fit" and "Fitnesse" bandied about by the software engineering literati. What are they? Are they useful? Are they used at all? Does your testing strategy need some fitnesse? The creator of Fit and the coordinator of the Fit project chat with Scott and answer the hard questions. Is Fit Dead?

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Genome is a sponsor for this show!

Welcome to powerful, mature object-relational mapping in the .NET world. Genome lets you use the full benefits of LINQ with all major database platforms (Microsoft SQL Server, Oracle and IBM DB2). Genome: supporting real-world enterprise application development since 2002.

Telerik is a sponsor for this show!

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET and Windows Forms. Enjoy the versatility of our new-generation Reporting Tool. Dive into our online community. Visit www.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

Technorati Tags: ,,

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Splitting DateTime - Unit Testing ASP.NET MVC Custom Model Binders

February 26, '09 Comments [27] Posted in ASP.NET | ASP.NET MVC
Sponsored By

I've got this form for users to create an event. One of the fields is a DateTime, like this:

image

And that's kind of lame as it's hard to type in a Date and a Time at the same time. It's also no fun. Most sites would have those separated, and ideally use some kind of Calendar Picker with jQuery or something.

image

But when you post a form like this back to a Controller Action, it doesn't exactly line up neatly with a System.DateTime object. There's no clean way to get partials like this and combine them into a single DateTime. The "ViewModel" in doesn't match the Model itself. I could certainly make my method take two DateTimes, along with the other fields, then put them together later. It could get mess though, if I split things up even more, like some travel sites do with Month, Date, Year each in separate boxes, then Hours, Minutes, and Seconds off in their own.

image

I figured this might be a decent place for a custom "DateAndTimeModelBinder" after my last attempt at a Model Binder was near-universally panned. ;)

Here's my thoughts, and I'm interested in your thoughts as well, Dear Reader.

DateAndTimeModelBinder

First, usage. You can either put this Custom Model Binder in charge of all your DateTimes by registering it in the Global.asax:

ModelBinders.Binders[typeof(DateTime)] = 
new DateAndTimeModelBinder() { Date = "Date", Time = "Time" };

The strings there are the suffixes of the fields in your View that will be holding the Date and the Time. There are other options in there like Hour, Minute, you get the idea.

Instead of my View having a date in one field:

<label for="EventDate">Event Date:</label>
<%= Html.TextBox("EventDate", Model.Dinner.EventDate) %>

I split it up, and add my chosen suffixes:

<label for="EventDate">Event Date:</label>
<%= Html.TextBox("EventDate.Date", Model.Dinner.EventDate.ToShortDateString()) %>
<%= Html.TextBox("EventDate.Time", Model.Dinner.EventDate.ToShortTimeString()) %>

Now, when the Form is POST'ed back, no one is the wiser, and the model is unchanged:

[AcceptVerbs(HttpVerbs.Post), Authorize]
public ActionResult Create(Dinner dinnerToCreate) {
//The two fields are now inside dinnerCreate.EventDate
// and model validation runs as before...
}

That's the general idea. You can also just put the attribute on a specific parameter, like this:

public ActionResult Edit(int id, 
[DateAndTime("year", "mo", "day", "hh","mm","secondsorhwatever")]
DateTime foo) {
...yada yada yada...
}

It's so nice, that I give it the Works On My Machine Seal:

Here's the code, so far. It's longish. I'm interested in your opinions on how to make it clearer, cleaner and DRYer (without breaking the tests!)

NOTE: If you're reading this via RSS, the code will be syntax highlighted and easier to read if you visit this post on my site directly.

public class DateAndTimeModelBinder : IModelBinder
{
public DateAndTimeModelBinder() { }

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}

//Maybe we're lucky and they just want a DateTime the regular way.
DateTime? dateTimeAttempt = GetA<DateTime>(bindingContext, "DateTime");
if (dateTimeAttempt != null)
{
return dateTimeAttempt.Value;
}

//If they haven't set Month,Day,Year OR Date, set "date" and get ready for an attempt
if (this.MonthDayYearSet == false && this.DateSet == false)
{
this.Date = "Date";
}

//If they haven't set Hour, Minute, Second OR Time, set "time" and get ready for an attempt
if (this.HourMinuteSecondSet == false && this.TimeSet == false)
{
this.Time = "Time";
}

//Did they want the Date *and* Time?
DateTime? dateAttempt = GetA<DateTime>(bindingContext, this.Date);
DateTime? timeAttempt = GetA<DateTime>(bindingContext, this.Time);

//Maybe they wanted the Time via parts
if (this.HourMinuteSecondSet)
{
timeAttempt = new DateTime(
DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day,
GetA<int>(bindingContext, this.Hour).Value,
GetA<int>(bindingContext, this.Minute).Value,
GetA<int>(bindingContext, this.Second).Value);
}

//Maybe they wanted the Date via parts
if (this.MonthDayYearSet)
{
dateAttempt = new DateTime(
GetA<int>(bindingContext, this.Year).Value,
GetA<int>(bindingContext, this.Month).Value,
GetA<int>(bindingContext, this.Day).Value,
DateTime.MinValue.Hour, DateTime.MinValue.Minute, DateTime.MinValue.Second);
}

//If we got both parts, assemble them!
if (dateAttempt != null && timeAttempt != null)
{
return new DateTime(dateAttempt.Value.Year,
dateAttempt.Value.Month,
dateAttempt.Value.Day,
timeAttempt.Value.Hour,
timeAttempt.Value.Minute,
timeAttempt.Value.Second);
}
//Only got one half? Return as much as we have!
return dateAttempt ?? timeAttempt;
}

private Nullable<T> GetA<T>(ModelBindingContext bindingContext, string key) where T : struct
{
if (String.IsNullOrEmpty(key)) return null;
ValueProviderResult valueResult;
//Try it with the prefix...
bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName + "." + key, out valueResult);
//Didn't work? Try without the prefix if needed...
if (valueResult == null && bindingContext.FallbackToEmptyPrefix == true)
{
bindingContext.ValueProvider.TryGetValue(key, out valueResult);
}
if (valueResult == null)
{
return null;
}
return (Nullable<T>)valueResult.ConvertTo(typeof(T));
}
public string Date { get; set; }
public string Time { get; set; }

public string Month { get; set; }
public string Day { get; set; }
public string Year { get; set; }

public string Hour { get; set; }
public string Minute { get; set; }
public string Second { get; set; }

public bool DateSet { get { return !String.IsNullOrEmpty(Date); } }
public bool MonthDayYearSet { get { return !(String.IsNullOrEmpty(Month) && String.IsNullOrEmpty(Day) && String.IsNullOrEmpty(Year)); } }

public bool TimeSet { get { return !String.IsNullOrEmpty(Time); } }
public bool HourMinuteSecondSet { get { return !(String.IsNullOrEmpty(Hour) && String.IsNullOrEmpty(Minute) && String.IsNullOrEmpty(Second)); } }

}

public class DateAndTimeAttribute : CustomModelBinderAttribute
{
private IModelBinder _binder;

// The user cares about a full date structure and full
// time structure, or one or the other.
public DateAndTimeAttribute(string date, string time)
{
_binder = new DateAndTimeModelBinder
{
Date = date,
Time = time
};
}

// The user wants to capture the date and time (or only one)
// as individual portions.
public DateAndTimeAttribute(string year, string month, string day,
string hour, string minute, string second)
{
_binder = new DateAndTimeModelBinder
{
Day = day,
Month = month,
Year = year,
Hour = hour,
Minute = minute,
Second = second
};
}

// The user wants to capture the date and time (or only one)
// as individual portions.
public DateAndTimeAttribute(string date, string time,
string year, string month, string day,
string hour, string minute, string second)
{
_binder = new DateAndTimeModelBinder
{
Day = day,
Month = month,
Year = year,
Hour = hour,
Minute = minute,
Second = second,
Date = date,
Time = time
};
}

public override IModelBinder GetBinder() { return _binder; }
}

Testing the Custom Model Binder

It works for Dates or Times, also. If you just want a Time, you'll get a MinDate, and if you just want a Date, you'll get a Date at midnight.

Here's just two of the tests. Note I was able to test this custom Model Binder without any mocking (thanks Phil!)

Some custom model binders do require mocking if they go digging around in the HttpContext or other concrete places. In this case, I just needed to poke around in the Form, so it was cleaner to use the existing ValueProvider.

[TestMethod]
public void Date_Can_Be_Pulled_Via_Provided_Month_Day_Year()
{
var dict = new ValueProviderDictionary(null) {
{ "foo.month", new ValueProviderResult("2","2",null) },
{ "foo.day", new ValueProviderResult("12", "12", null) },
{ "foo.year", new ValueProviderResult("1964", "1964", null) }
};

var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = dict};

DateAndTimeModelBinder b = new DateAndTimeModelBinder() { Month = "month", Day = "day", Year = "year" };

DateTime result = (DateTime)b.BindModel(null, bindingContext);
Assert.AreEqual(DateTime.Parse("1964-02-12 12:00:00 am"), result);
}

[TestMethod]
public void DateTime_Can_Be_Pulled_Via_Provided_Month_Day_Year_Hour_Minute_Second_Alternate_Names()
{
var dict = new ValueProviderDictionary(null) {
{ "foo.month1", new ValueProviderResult("2","2",null) },
{ "foo.day1", new ValueProviderResult("12", "12", null) },
{ "foo.year1", new ValueProviderResult("1964", "1964", null) },
{ "foo.hour1", new ValueProviderResult("13","13",null) },
{ "foo.minute1", new ValueProviderResult("44", "44", null) },
{ "foo.second1", new ValueProviderResult("01", "01", null) }
};

var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = dict };

DateAndTimeModelBinder b = new DateAndTimeModelBinder() { Month = "month1", Day = "day1", Year = "year1", Hour = "hour1", Minute = "minute1", Second = "second1" };

DateTime result = (DateTime)b.BindModel(null, bindingContext);
Assert.AreEqual(DateTime.Parse("1964-02-12 13:44:01"), result);
}

Thanks to LeviB for his help. Your thoughts?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.