Tuesday, January 01, 2013

The Geek Armando

Return of the Natives

Last week I saw Return of the Natives, a really cool improv at the Blue Door Theatre. They did a show based the Armando, a form where a monologist tells a story and then the improvisers improvise on the story, the monologist tells another story, more improv, each feeding into the other until they run out of time. In this show, the monologist was a standup comedian and she started out with a bit from her show (she now lives in LA), the improvisers where originally from Spokane but have moved away to places where they could get paid to do improv.

.NET Rocks #300 and others

In DNR # 300, Richard Campbell tells geeky tales of his early hacking as a kid in the 1970s and 80s. He told stories about how he built an Electronic Rocket Countdown Timer at 10, fixed computers for grownups, solved a difficult hardware problem by replacing the hardware, built a server farm in his house, etc. He even tells “The Goliath Story” (I can’t give it justice, just listen to it). I’ve heard Richard geek out on other podcasts on other podcasts like Hanselminutiae. I’ve heard other geeks tell tales of great geekdom on blogs, podcasts, the speaker’s room at code camps, at work, etc.

Improv in the workplace

Years ago I learned that Infusion Development offers improv classes to their associates. They even have a video on youtube. This knowledge is one of the factors that lead me to start taking improv classes at the Blue Door. Ted Neward gave an improv session at the 2012 Seattle Code Camp. There are countless articles on the business benefits of teaching improv to your employees from sites like businessweek.com, foo.com & careerbuilder.com. I’ve written about my experience with improv.

Fantasy – Putting it all together

I would like to see an Armando style show based on the monologs of a visionary/character of our industry with improvisers who are geeks. This performance could take place at an industry conference, code camp or such.

Richard Campbell would be an excellent choice to be the monologist, but there are others out there who could tell great stories. I’ve heard other geeks tell tales of great geekdom on blogs, podcasts, the speaker’s room at code camps, at work, etc. The monologist must be someone who can get up there and talk and tell good stories. There could be a dialog in the form of an interview in place of the monolog; a good interviewer can help bring out the character if the principal is otherwise shy.

Infusion Improv would be an excellent choice for the players. I hope there are other companies that offer improv training, one of those companies could send their improv all-stars or the geek improvisers from the host city. If a company provided the improvisers, they could get some recruiting PR points.

Thursday, December 27, 2012

Windows 7 Activation Heck

A long time ago, I noticed that my hard drive was behaving suicidal. so I bought a new one, copied the old one with Ghost and installed the new one. Everything ran fine for awhile (I wasn’t getting updated from Microsoft, but I wasn’t paying attention), so everything was bliss as I continued to use my computer.

Then, behold, I was informed by Windows Activation Technologies that my Windows wasn’t “Genuine”. I figured that my windows license was destroyed with my HD, so I clicked “Resolve online now” and ended up buying a “Get Genuine Online Kit” online. Microsoft gave me a new Product Key on the spot. I entered it and I still got the message. A week later, the software came in the mail; I tried and failed to upgrade couple of times and it failed each time telling me that my computer isn’t compatible with Windows 7.

A couple of days ago I downloaded MGADiag.exe and when I run it, it tells me that my Windows is “Genuine”:

IsItGenuineOrNot

Update

Someone on answers.microsoft.com suggested that I reinstall my Intel Rapid Storage Tech driver and so far so good. Windows Update even works.

Wednesday, November 28, 2012

Testing and Medicine

Lately I have been thinking about testing in areas outside programming. This time I will tackle the area of Medicine.

Medicine

One problem is that you can’t do a unit test without killing the subject. The issue is that you can’t isolate your heart from the rest of the system. It is an area where you are doing maintenance, Doctors don’t build bodies; they have to keep the bodies designed by God or Nature in good working order. Sure they have a limited opportunity to do some refactoring using surgery and medication; there is no Green Field Medicine. It is all maintenance work.

Medical tests appear to be closer to code metrics that the kind of testing we do in software. For example, we know that too much cholesterol in the blood is a bad thing that people with too much cholesterol are more likely to have heart attacks. Does cholesterol cause heart attacks? I don’t know, but based on what we know right now, we need to keep it down below a certain level. Same for blood sugar, blood pressure, etc. There is a correlation between what we are measuring and what we care about. Just like too many GO TO statements and long procedures tend to appear in rotten code.

Modivation

I got a bad cough in September and it has continued through November. I have seen more doctors in the last 2 ½ months than I have in the last 10 years.

Wednesday, October 31, 2012

Testing and The Law

I work in software where test is paramount (some would say that we've gone overboard and spend more time testing than getting real work done...a discussion for later). Well, anyway, I've been thinking about testing in other fields.

Legal

Here testing appears to be expensive. There are many legal documents out there but few are ever tested. By testing I mean brought before a judge or jury for a decision, and the test isn't complete until the appeal process is completed.

The result of the test is based on human interpretation of the document and the law. There are various theories of law and you may get a different result based on who hears the case.

Much of it is settled without testing. The two sides asset their position and the law and come to an agreement. It is often based on the strength or weakness of each side of the case.

Since the law is based on president, or what was decided before, some people will deliberately test a law (bring it to trial) in hopes of changing the law based on the decision - a test case.

Motivation

I am trading my condo for another one of greater than or equal value. Well, anyway, the other party dropped off the documents to complete the deal. Reading them got me thinking.

Sunday, September 30, 2012

Healthcare: My Struggles with a Complex System

Earlier this month my decided to be less cooperate and developed a condition that I still don’t understand. So far I’ve been to “the doctor” 3 times and visited the pharmacists’ after each visit. I’ve missed more days this month that I’ve missed in the previous 3 years. I was even tested for Whooping Cough (I don’t have it).

I am dealing with a complex system that I don’t understand. Right now this system is important to me, so I am forced to wade through it the best I can. Perhaps this is the way non-nerds teal with technology and other things that I deal with every day.

First I didn’t know how to enter the system. I had the cough for over a week and things weren’t getting better; I hadn’t bothered to doctor up before the crisis (I should schedule these things better). Now supposed that I was a 75 year old woman who wanted to get a new tablet (my improv skills come in handy here). Do I get an iPad, Kindle Fire, Nook Color or some other thing I’ve never heard of? Would I even know of anything other than the iPad? What is it supposed to do anything? How much do I want to bother my son with question about the new thing? Etc.

So, I finally get myself to the doctor’s office. What do I say? What is relevant? What is too much information? Did I leave something out? Am I falling into the “ask your doctor about [sponsored drug name here]” trap? Now suppose that I need custom software to solve some problem. How much does the program need to match my current process? Do I care if it is written in Java, .NET or X86 Assembler? How do I know if the software vender is any good?

As a programmer, Search is my friend; I can Bing with Google and get quick answers to my programming query. I can even tell the good from the bad. When I searched for medical stuff over the last couple of weeks, I would find things to feed my paranoia. (Things like “Lung Cancer”, “Throat Cancer”, anything else with “Cancer” in the name; my perceptions of my symptoms would morph to match WebMD.) When a customer (or friend or family member) finds some article about I’m doing that turns out to be less than relevant or downright dangerous, I should think about my experience with WebMD and deal with them gently.

So, what, I don’t understand this whole medical stuff. What I am trying to do here is suggest that I can use this pain to emphasize with my customers. I mean I can’t forget all the things that I know about programming and technology and even if I did, I would still think different. So when they appear to struggle in my area, I need to remember what it was like to struggle in someone else’s area.

Tuesday, August 21, 2012

Weekend Challenge #1: CSV to a Web Page

If you know programming and want to see samples of my work, you can read this blog. If you are not a programmer and want to evaluate my skills, there is nothing out there that I can show you. I haven’t worked on a public web site for over 3 years. My current projects are internal Windows Forms applications. You could load Improv Suggester onto your Windows Phone, if you have one.

So last weekend I challenged myself to write a public sample. I wanted to challenge myself to work in technologies that I haven’t worked in for awhile if ever.

Problem

Suppose you have a system that uses Excel spreadsheets to store data. Now, suppose that you want to transition to a web based system but you want to be able to fill out an existing spreadsheet and “Import” the data into the new system.

The Tools

Web Matrix 2

Editor – Half way between Visual Studio and notepad. The editor felt bulky without the features I would expect in exchange for the bulk. There were a couple of times when the editor was a dozen or so keystrokes behind me. Publishing to the web is easy.

Link to Web Matrix 2

Razor Rendering Engine

Language & Rendering Engine – It is interesting how HTML, JavaScript and C# are mixed together. It looks cleaner than ASP.NET, PHP or T4 markup, though I wish the JavaScript looked more different than C#, but that may be an editor issue.

Link to Razor

Hanson Table

Grid Control – This was the first JQuery control that I found that behaved the way I needed it to. There were other grids that allowed you to edit the cells but forced you to click on the cell you wanted to edit.

Link to Hanson Table

Lumenworks (CsvReader)

Parse CSV – This is somewhat of a cheat. I have used this library on a couple of other projects. It has this cool feature that allows you to reference columns by name, assuming that these names are on the first line. Since I wanted to allow the user to put global data at the top of the sheet, I looked for the headers and that was the first line that I gave to CsvReader.

Link to Lumenworks on Code Project

The Code

According to the rules that I have imposed on myself, I give you the code as it existed as of the end of August 19. You can see the sample in action on my main site.

@using Microsoft.Web.Helpers;
@using System.Web;
@using System.IO;
@using LumenWorks.Framework.IO.Csv;
@using System.Text;
@{
    Layout = "~/_SiteLayout.cshtml";
Page.Title = "Upload Grid Demo";

var make = "Make";
var date = string.Empty;
var submittedData = "";
var fileName = "";
var content = "";
var dataArray = "";
if (IsPost) 
{
var _txtMake = Request.Form["_txtMake"];

if(_txtMake != null)
{
submittedData = "Make: " + Request.Form["_txtMake"] + Environment.NewLine +
"Date: " + Request.Form["_txtDate"] + Environment.NewLine +
"Grid Data: " + Environment.NewLine +
Request.Form["_hidGridJson"];
}
else
{        
var fileSavePath = "";
var uploadedFile = Request.Files[0];
fileName = Path.GetFileName(uploadedFile.FileName);

StreamReader sr1 = new StreamReader(uploadedFile.InputStream);
string st = sr1.ReadToEnd();

Dictionary<string,string> topParams;
string lineItems;

getParamsAndGridDetail(st, out topParams, out lineItems);

Stream st2 = GenerateStreamFromString(lineItems);
TextReader tr = new StreamReader(st2);

dataArray = getGridDataForTextReader(tr);

if (!topParams.TryGetValue("Make:", out make))
{
make = string.Empty;
}
if (!topParams.TryGetValue("Date:", out date))
{
date = string.Empty;
}
}
}
}
@functions{
    public void getParamsAndGridDetail(string allLines, out Dictionary<string,string>
topParams, out string lineItems)
{
topParams = new Dictionary<string,string>();
StringBuilder sb = new StringBuilder();
string[] linesArray=allLines.Replace("\r", string.Empty).Split(new char[]{'\n'});
int stepNumber = 1;
foreach(string line in linesArray)
{
if (stepNumber == 1)
{
if (isHeaderLine(line))
{
sb.AppendLine(line);
stepNumber = 2;
}
else
{
lookForKeys(line, ref topParams);
}
}
else if (stepNumber == 2)
{
if(line.Replace(",", string.Empty).Trim().Length == 0)
{
stepNumber = 3;
}
else
{
sb.AppendLine(line);
}
}
}
lineItems = sb.ToString();
}
public void lookForKeys(string line, ref Dictionary<string,string> topParams)
{
string[] sumItems = line.Split(new char[] {','});
//foreach(string cell in sumItems)
for (int i = 0; i < sumItems.Length - 1; ++i)
{
if(sumItems[i].EndsWith(":"))
{
topParams.Add(sumItems[i], sumItems[i + 1]);
}
}
}
public bool isHeaderLine(string line)
{
bool foundModel = false;
bool foundYear = false;
bool foundColor = false;
string[] sumItems = line.Split(new char[] {','});
foreach(string cell in sumItems)
{
string normalizedCell = cell.Trim().ToLower();
if(normalizedCell == "model")
{
foundModel = true;
}
if(normalizedCell == "year")
{
foundYear = true;
}
if(normalizedCell == "color")
{
foundColor = true;
}
}
return foundModel && foundYear && foundColor;
}
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
public string getGridDataForTextReader(TextReader tr)
{
var sb = new StringBuilder();
sb.AppendLine("[");
using (var csv = new CsvReader(tr, true))
{
bool isFirstLine = true;
int fieldCount = csv.FieldCount;
while (csv.ReadNextRecord())
{
if(!isFirstLine)
{
sb.AppendLine(",");
}
isFirstLine = false;
sb.Append("        [");
sb.AppendFormat("\"{0}\",{1},\"{2}\"", csv["Model"], csv["Year"], csv["Color"]);
sb.Append("]");
}
}
sb.AppendLine("");
sb.Append("    ];");
return sb.ToString();
}
}
@section Scripts
{
<script src="@Href("~/lib/jquery.js")"></script>
<script src="@Href("~/jquery.handsontable.js")"></script>
<script src="@Href("~/lib/bootstrap-typeahead.js")"></script>
<script src="@Href("~/lib/jquery.autoresize.js")"></script>
<script src="@Href("~/lib/jQuery-contextMenu/jquery.contextMenu.js")"></script>
<script src="@Href("~/lib/jQuery-contextMenu/jquery.ui.position.js")"></script>
<link rel="stylesheet" media="screen" 
href="/lib/jQuery-contextMenu/jquery.contextMenu.css">
<link rel="stylesheet" media="screen" href="/jquery.handsontable.css">
}
    @FileUpload.GetHtml(
initialNumberOfFiles:1,
allowMoreFilesToBeAdded:false,
includeFormTag:true,
uploadText:"Parse CSV File")
@if (IsPost) {
<br/>
<span>File uploaded!</span>
<h3>@fileName</h3>
}
@if (string.IsNullOrEmpty(submittedData)){
<form action="" method="post" name="_formWriteBack" onclick="doOnSubmit();"  >
<input type="hidden" name="_hidGridJson" id="_hidGridJson" />
Make: <input name="_txtMake" id="_txtMake" value="@make" /><br />
Date: <input name="_txtDate" id="_txtDate" value="@date" /><br />
<div id="example1grid" class="dataTable"></div>
<script>
var $container = $("#example1grid");
var $parent = $container.parent();
$container.handsontable({
rows: 2,
cols: 3,
minSpareCols: 0, //always keep at least 0 spare row at the right
minSpareRows: 1, //always keep at least 1 spare row at the bottom
contextMenu: true,
colHeaders: ["Model", "Year", "Color"],
autoComplete: [
{
match: function (row, col, data) {
if (col == 2) {
return true;
}
return false;
},
highlighter: function (item) {
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
var label = item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>';
});
return '<span style="margin-right: 10px; background-color: ' +
item + '">&nbsp;&nbsp;&nbsp;</span>' + label;
},
source: function () {
return ["Yellow", "Red", "Orange", "Green", "Blue", "Gray", "Black", "White"]
},
strict: false //allows other values that defined in array above
}
]

});

var data = @Html.Raw(dataArray)
$container.handsontable("loadData", data);

function doOnSubmit() {
var newdata;
newdata = $container.handsontable("getData", "");
_hidGridJson.value = newdata;
}
</script>
<input type="submit" value="Submit Form" />
</form>
}
@if (!string.IsNullOrEmpty(submittedData)){
<p>This is the data you just submitted to the web server. </p>
<pre>
@submittedData
</pre>
}

Friday, July 27, 2012

Dealing with DataSet’s Outdated Nullability Model

The DataSet is one of the most ancient relics of the .NET framework. DataSets were designed before the invention of Nullable<T> and came up with a different way to deal with database null values. So we are stuck with properties that throw StrongTypingException when the property is null and special IsXXXNull() methods to test whether a property is null. So you end up with ugly code like this:

if (!row.IsReportsToNull())
{
Console.WriteLine(row.ReportsTo);
}
else
{
Console.WriteLine("NULL");
}

or

try
{
Console.WriteLine(row.ReportsTo);
}
catch (StrongTypingException)
{
Console.WriteLine("NULL");
}

This code dance is necessary because you can’t even touch a null property without triggering an exception. So you can’t pass the property to a method that would check for nullability. But you can pass a Func<T> to a lamda:

private string GetStringForTFromDataRowField<T>(Func<bool> isNull, Func<T> getValue, 
string formatString = "{0}")
{
if (!isNull())
{
return string.Format(formatString, getValue());
}
else
{
return "NULL";
}
}

With this function I can reference the field in one (ugly) statement:

Console.WriteLine(GetStringForTFromDataRowField(row.IsReportsToNull, 
() => { return row.ReportsTo; }));

Here I am not referencing the actual property until I confirm that the property isn’t null. Since the property is referenced in an anonymous method it isn’t evaluated until after the IsNull() method confirms that the value isn’t null.

What do I get? Slightly cleaner code, I guess. You still need to match the property with the correct IsXXXNull() method. I find the code in the first couple of examples so ugly that this hack is worth the effort for me.