Friday, August 21, 2009

Tightening screws

Kinda funny how everyone was talking about web developers sucking / not sucking, and then someone pointed to this on Reddit: Guido basically giving up on CSS.

I read a comment by Josh Powell on this article that was resonated with me:

Whenever I hear people insult web developers, I remember the time when I was in the workforce for only one year and some java developers came up to me and said "we can't get this whitespace to go away in ie, but it isn't there in netscape" I went over and took 30 seconds to fix it, and afterwards they said "We spent hours on that! How did you know how to fix it!?!" All their knowledge of garbage collectors, destructors, compilers, etc, didn't help them remove the spaces between the last character on the line and the start of the ending td tag.

You may not think that's a big deal, but trust me, lots of real world clients could care less about what gc algorithm you use, but they will have your neck if you can't get their site looking like they want it in IE.

The whole thing reminds me of this one tale:




Once upon a time, there was company that had a big expensive machine that was critical to their business. One day, without much explanation, the machine buzzed and ground to a halt. They tried to restart it, they tried all the usual maintenance protocol. Nothing was making it start again. Management grew nervous. They were losing money for every minute the machine was down. They frantically searched high and low for anyone who could fix it.

After a long week, they finally found one technician who specialized in fixing that particular machine. They rushed him in to the corner of the factory, all the high executives trailing anxiously behind him.

The technician calmly opened a shaft, and looked at the unimaginably complex circuitry for 5 minutes. He reached into his toolbox and grabbed a tiny screwdriver, and then, without much effort, tightened a single screw. "Ok, turn it on, boys", he declared.

The executives looked at each other, a mix of hope and disbelief in their eyes. If the machine was down for a few more days, they'd literally go bankrupt. The workers powered the machine and, stunningly, it started working as if not had ever happened. Everyone rejoyced. With one flick of his wrist, the technician had saved the company. "I'll be on my way then", the technician said, humbly.

The next week, the company got the invoice for the technician's fix. It looked like a ordinary invoice printed in ordinary paper, except for one detail: the amount payable on the invoice was $10,000. A bit disconcerted, the managers called him to get some clarification.

"We believe you made a mistake on your invoice. We were all there when you fixed it and we saw that all you did was tighten one screw."

"You are correct that I only tightened one screw, but you're mistaken about one thing. I don't charge for tightening screws. Anyone can do that. I charge for knowing which screw to tighten."




Obviously not everyone is an unsung hero, but I think the world sure would be a nicer place if people stopped the whole holier-than-thou crapola.

Sunday, August 16, 2009

Thursday, August 13, 2009

Centmail

Am I the only one who, within seconds of reading this, thought "Centwitter"?

What people spend money on

Just to put things in perspective, think about the budget of hollywood movies and large TV networks. Now look at how much money moves in the real estate, insurance, health care, food and energy industries.

But we already knew that.

Interestingly, reading has its own slice (albeit small). Does that mean it's much more prevalent than other forms of entertainment? Or was there a reason to not group it under entertainment (or possibly education)?

Pascal's Wager

Wikipedia.

A point of view.

Another.

Atheist's Wager.

So much just for saying "be nice".

Wednesday, August 5, 2009

How would you map a map?

This occurred to me today. Imagine we have a list of things.

list = [1, 2, 3, 4]

Given that we have a mutation function "fn", how do we change all of the elements in the list with that function?

If we're just using idiomatic procedural code, we'd use a loop, but since we're fancy smarty pants, we're gonna use higher order functions. Like so:

map(list, fn)

Then the function could have the following arbitrary mutation algorithm:

function fn(x) {return x * x}

Nothing exciting so far.

But the data structure I want isn't a list. It's a map. You know, a list of key-value pairs. How do I map that?

My previous function no longer works because I need to be able to work on the key, as well as the value. The problem is that I can only return one thing. What do I return? The value? The key? A pair?

function fn(k, v) {return [k, v]} //two inputs, infinite output arity

Well, we'd have to follow some sort of convention to get around that infinite arity problem. Even in Java, we could potentially pass a null instead of an Entry and then you'd get a null ref exception inside the map function. Not very nice.

Would it be ok to just give up and throw an error? Hmm. Maybe. If there's no other option, I guess that'd be ok.

Oh, I know, what if we had two mapping functions?

map(myMap, keyFn, valueFn)

Then I can guarantee that I'll get reasonable arities.

function keyFn(k, v) {return k * k + v * v} //one input, one output
function valueFn(k, v) {return k / v} //one input, one output

Is it mathematically possible to have logic that cannot be split into two functions? I'm thinking if we start introducing closures and side effects, things would probably get weird, but I can't really picture how. Can anyone think of a way where this API would fail spectacularly?

Tuesday, August 4, 2009

Thoughts about C# regions

I was playing with my toy parser over the weekend, and was deciding what the syntax to handle large blobs of arbitrary text should look like (for dealing with heredocs, wysiwyg strings, comment blocks, that sort of stuff). I was just about settling for a mix of ideas from Python and some ramblings from one of my older blog posts, but then it occurred to me that there is one type of comment that is unique, implemented in a mainstream language, and that has even created heated debates in some corners of the 'tubes: C# regions.

The debate is that regions are considered by some programmers to be evil. If you're not familiar with the debate, this article presents the point of view that regions are bad, and this other one presents the view that regions are helpful.

My thoughts

Regions do two things:

  1. They create code folding points so that the editor can hide code
  2. They allow those sections to be briefly described by snippet of plain english

I can see why people would argue about the code folding, but at the end of the day, whether you fold your code or not is a personal preference. I'm actually a bit surprised that people would resort to proclaiming the feature evil before, you know, finding that there's a way to turn off code folding in Visual Studio. You'd think software developers would be good at using software. I digress.

The problem with regions that no one seems to talk about (in my opinion) is that the regions aren't usually very informative. They do give me some information, but not a whole lot. Let me elaborate.

Generally, I see regions being used to separate different types of class members: methods, properties, events. Or publics and privates. I suppose that is fine when the code does tend to be event-driven (and a lot of the .NET API is). Spend enough time with that convention and you'll subconsciously learn that you'll find the scope of stateful data within a "Member Variables" region, and that code entry points are likely to be in the "Constructor" or "Events" regions.

My gripe is that this isn't normally written out explicitly in idiomatic #region usage. You have to have this sort of mind map.

Another unfortunate thing is that I find inconsistent organization sometimes: I'd open a region to find this huge list of folded methods. Which ones are top-level functions? Which ones are helper/shared/refactored functions? Which ones are called within tight loops? From which functions? Are there more methods hidden in an almost-invisible region sitting just below the fold in my editor viewport? Why aren't the rest of the methods grouped inside a sibling region as well in that case?

Back to Earth

Now, obviously, a lot of that of that is largely a matter of style, personal preferences and knowing the conventions, but I feel there's still some aspects of regions that are worth exploring.

The debate I mentioned earlier briefly says that methods should be refactored when they are too long. But what does that actually mean in terms of code folding?

By definition, refactoring a large block of procedural code yields a bunch of small functions. Heck, the toy parser I'm working on does exactly that.

The caveat is that refactored-out functions normally have a hierarchical relationship to the function from which they were extracted from.

Imagine we have a parser with a parse function that can call parseNumber and parseString. The function parseString in turn can call parseEscapedString and parseHeredoc, and the parseNumber can call parseHexadecimal and parseImaginary.

So far we have 7 functions and the logical way to group them looks more like a binary tree than a flat array of functions. We could create a "string" region and a "number" region, but that essentially leaves the parse function floating naked by itself in a sea of meta information:

#region parsing functions
public void parse() ...
  #region string parsing
public void parseString() ...
public void parseEscapedString() ...
public void parseHeredoc() ...
  #endregion

  #region number parsing
public void parseNumber() ...
public void parseHexadecimal() ...
public void parseImaginary() ...
  #endregion
#endregion

Which would fold like this:

#region parse
public void parse() ... <- this looks ugly :(
  [+ string]
  [+ number]
#endregion

We could put that parse function in a region of its own, but that doesn't make a whole lot of sense either. Hmmm.

It'd be neat if we could write this:

#region parsing functions
  #desc entry point
public void parse() ...
  #region string parsing
public void parseString() ...
public void parseEscapedString() ...
public void parseHeredoc() ...
  #endregion

  #region number parsing
public void parseNumber() ...
public void parseHexadecimal() ...
public void parseImaginary() ...
  #endregion
#endregion

Then, this made-up #desc would fold the parse function like so:

#region parsing functions
  [+ entry point]
  [+ string parsing]
  [+ number parsing]
#endregion

And while we're at it, let's go a step further. Let's add #desc's to all the functions and allow a folding mode that looks like this:

[+ parsing functions]
  [+ entry point]
  [+ string parsing]
    [+ strings w/ escape chars]
    [+ heredocs]
  [+ number parsing]
    [+ hexadecimals]
    [+ imaginary]

That would look a lot cleaner. It basically looks like a table of contents. Maybe I'll do something like that for my toy parser.