A collection of learnings and opinions.

Tuesday, September 30, 2008

Podcasts

I listen to a lot of podcasts. What can I say, I bore easily. When I have to do something that's not social and takes more than a few minutes I often pop the earbuds in and start listening. My player, the Zen V 2Gb, is far too small to contain any music, and podcasts are a great way of getting some intelectual topping in the daily drudgery.

I thought I'd post the list of podcasts I enjoy regularly:
  • CBC Radio Quirks and Quarks
    A great show about the stories breaking in science. Definitely a Canadian slant, and they've been running theme shows about Canada's carbon-footprint and such lately (which doesn't interest me that much), but still one of the greatest.

  • FLOSS Weekly
    This show died for a while, but they're back with a vengeance. In-depth interviews with important people in the open-source world. Could it be better?

  • In Our Time With Melvyn Bragg
    Melvyn is a delightfully pretentious British chap interviewing academics on interesting themes. Always interesting, and a really eclectic selection of themes.

  • IT Conversations
    One of the really early podcasts, this is excellent quality. I listen to the entire feed, which I think syndicates a lot of other feeds. Great content from biomedical/genetics to philosophy and CTO-grade stuff. There's always something here you haven't heard about.

  • Math Mutation
    This is a new one for me. Erik Seligman talks very briefly (3-5 minutes) about some interesting topics from the world of Math and Numbers. Good content!

  • StarStuff with Stuart Gary
    I'm a sucker for the starry nights, and this recent discovery seems right up my alley. I've only listened to two yet, but I think it's a keeper!

  • The Java Posse
    My favourite! The posse have weekly commentaries on the tech-world with a heavy java-slant. All the members are world-class developers with strong opinions and the arguments to back them up. It makes my day every time I see a new one pop into my playlist.

  • The Skeptic's Guide to the Universe
    Tackling the idiocy and numb-thinking out there head on, the Skeptical Rogues are not afraid to delve deeply into any theme they find. It's so refreshing to see that there are intelligent people out there, not just nuts.

  • This Week in Science - The Kickass Science Podcast
    Another recent discovery on my part. I'm not sure if this is a keeper yet. The themes seem interesting, but they're just not catching me yet. I'll keep them around for a few weeks, and see if they're worth it.

  • This Week in Tech
    I've a feeling this is the big one. Leo Laporte is a great host, and he gets a lot of interesting punters. Whenever they talk about something I know they always manage to get it dead-wrong though, so I take their opinions with a grain of salt. Still, the show is a gem.
Definitely a Tech/Science slant, eh? Any others I should know about, or comments are much appreciated :)

Thursday, September 25, 2008

CountDistinct - How About SumDistinct - Or Just AggregateDistinct?

Making a report in Microsoft SQL Server 2005 Reporting Services today I needed to sum up several levels in a table. However, the numbers where available only at an intermediate aggregated level, so I needed to sum up only the distinct sublevel-items. Got that? Maybe it's easier if I show an example:


Let's concoct an example here. I'm extracting data in the following groups: Firm, ProductType, Product, Account, Item. Say I'm summing up one measure, BalanceAmount, on products, but my dataset returns other measures on the lowest level, Item.


Here's an example DataSet






















































































Firm ProductType Product Account Item BalanceAmount ItemMeasure
Acme Explosive Nitroglyserin C-001 Bottle $200 $2.14
Acme Explosive Nitroglyserin C-001 Mug $200 $4.87
Acme Explosive TNT C-001 Stick $200 $0.79
Acme Explosive Plastique C-001 Wad $200 $7.64
Acme Prop Fake rock C-001 Crate $200 $4.55
Acme Explosive TNT C-124 Stick $89 $0.79
Acme Explosive TNT C-124 Half-stick $89 $0.40
Acme Explosive Nitroglyserin C-089 Stick $40 $0.79


In the report I need to show this as a drill-down table, with the measures down on the lowest level (Item) summed up on every level, and the aggregated measure (BalanceAmount) summed up on every level where it makes sense.


The problem is that if you use the common SUM function the report would sum up all BalanceAmounts on the Account level resulting in a BalanceAmount of $1000 for Account C-001, not $200 which is the correct value (that would be $200, Einstein).


What you really need is something like CountDistinct, but just for Sum. In fact, this is a specific case of a more general problem where you need to conduct some aggregation on some scope. How do I do something like that?


It's not really hard. What I need is some way to make just the first instance of a value in whatever scope needed be the counting one. To get this I enter the
following into the Code tab of you Report properties:



    Dim scopes As System.Collections.Hashtable
Function getDistinct(ByVal checkMe As Object, ByVal scope As String) As Boolean
Dim firstTimeSeen As Boolean

If (scopes Is Nothing) Then
scopes = New System.Collections.Hashtable
End If

If (Not scopes.Contains(scope)) Then
scopes.Add(scope, New System.Collections.ArrayList)
End If

If (Not CType(scopes(scope), System.Collections.ArrayList).Contains(checkMe)) Then
firstTimeSeen = True
CType(scopes(scope), System.Collections.ArrayList).Add(checkMe)
Else
firstTimeSeen = False
End If

Return firstTimeSeen
End Function

The usage pattern to get SumDistinct in this case is:


=SUM(IIF(Code.getDistinct(Fields!account.Value, "scopeId"), Fields!BalanceAmount.Value, 0))

The "scopeId" string identifies the current scope, so it will change from group to group. E.g. in the Firm group you'd enter "firm", in the ProductType group you'd enter "prodType", etc.


So what am I doing here? We're remembering the values of the checkMe parameter in the context of the scope, and returning True in only the first instance. Thus we can just sum the first of every checkMe value. You could use this to do your own CountDistinct by entering the following expression (but this would be a bit roundabout for that use-case):


=COUNT(IIF(Code.getDistinct(Fields!account.Value, "scopeId"), Fields!BalanceAmount.Value, 0))

I hope you get some use out of this. This kind of code is easy to crank out, but even easier to just copy-paste.

Sunday, August 10, 2008

The 21 Laws of Computer Programming

These had me in stitches. Particularly number 19: "If you automate a mess, you get an automated mess". So true, and taken with another favourite saying of mine, "If it's worth doing once it's worth automating" we've got a true mess on our hands :)

Read 21 laws of computer programming

The Great Office War

Thursday, August 2, 2007

DropDownList with a blank item on top

The DropDownList (DDL) is a nice little databindable control in ASP.Net. The easiest way to use it is to databind it to some value from your database and let the user select.

The problem with straight on databinding is that the first item in the DDL will be the first item in the databound collection (naturally), thus making choosing that item "a little too easy" and "a little too hard". When the user wants to select the top item you might be in for problems, as that selection won't fire off a SelectedIndexChanged -event, which is what you'd normally listen for.

There are ways around this - I've seen several suggestions. None of these are even starters in my opinion:
  • Don't handle changes in the DDL, read from it on some other event (typically a button)
    • This makes it very hard to create responsive UIs, as your user will always have to keep clicking buttons
  • Set whatever you want to happen on changes in the DDL as if the first choice was already chosen (pre-choose for the user)
    • Badness - especially in a stateless media like the web - your user may never correct your initial (possibly wrong) assumption
  • Add an empty record in the databound object (typically your database)
    • Perhaps the worst idea I've seen. The database should not contain filler like this. It's a bit better if you're working with some transient object - but still it's a hack. We don't like hacks.
The way to fix this problem is really not very hard. What you want is an empty item on the top of the list that the user will not expect to work, with a known value you can check for in your SelectedIndexChanged handler.

To do this add a ListItem to the DDL in the page/control's definition with your sentinel value and an empty string as the Text property. Normally this item would disappear on databinding, but wait: set the AppendDataBoundItems property on the DDL to True, and your empty initial value will survive!

Two things to beware: Make sure you check for your sentinel value in the handler, and remember to clear all but the initial item of the DDL's ItemListCollection if you're databinding that control again later (unless you want to keep appending).

Here's your illustrative code:
A standard DDL:

<asp:DropDownList id="ddBasic" runat="server" autopostback="True">
<!-- Selecting the top item will not fire an event (it will be pre-selected) -->
</asp:DropDownList>


A DDL with the empty top-item:

<asp:DropDownList id="ddWithEmptyTop" runat="server" autopostback="True" appenddatabounditems="True">
<asp:ListItem value="-1" text=""> </asp:ListItem>
</asp:DropDownList>


Technorati Tags: , , ,

Thursday, July 26, 2007

Glotton - word glutton


I've launched a new small open-source application, Glotton. Get it at http://code.google.com/p/glotton/

It's my summer holiday, and I've been playing some word-games (in particular Scrabble and BookWorm). I'm not particularly good at these, but I find them fun.

What I can do, however, is to get a computer to help me. So I did - I created Glotton.

It is free, open-source and available for whatever use anyone may put it to. The easiest way to use it is to download the pre-packaged zip, extract this and run the jar-file.

Send me a note if you like it or find any bugs.


Powered by ScribeFire.

Wednesday, June 27, 2007

Error ... error ... whence cometh thou?

I'm working on a page that will allow our users to view a table in a database in ASP.Net. To do this I am writing a UserControl where I am connecting to the database through a SqlDataSource, and I bind a GridView on the UserControl to this datasource. If you are unfamiliar with databinding this simply means that I hook the presenting controller (the GridView) up to an object that can provide it with data. This automagically populates the presenter with the data from the source. But, as with all automagical things can, and do, go horribly wrong.

Small digression: I'm from the Java plains, but I've recently set up shop in the .Net woods where I mostly hang around in the soppy marshes of ASP, the glossy banks of MSSQL-RS and more recently the crags of ADO. Being quite new in these parts I get to do a lot of really stupid things, and I'm building an appreciation of each land's pros and cons. One of my gripes with the marshes of ASP is the incessant focus on doing things declaratively as the first-choice. Sure, it's great if what you want is static, but I don't want static content!

Why this rant? Declarativity just bit me in the rump, like a particularly nasty ass.

So, I was binding my GridView to the SQLDataSource declaratively, like a good ASP-ape. Everything was working as expected until I started testing the page with non-standard inputs. The datasource is setup with the data it needs to connect to the database, and an initial select statement to get at the data you want. If any of this is incorrect the entire page explodes in a messy way. Red goo all over the walls.

My test-case was simply setting up the datasource with an incorrect login. This caused an SQL-exception when the SQLDataSource tried to perform the initial Select (as one would expect). Now, .Net does not have checked exceptions (expect a post on this later), so being from the Java-land I am always a bit surprised and worried to see exceptions being thrown willy-nilly run-time.

Well, this exception I should be able to deal with. It is a real problem, but the application should be able to handle such problems gracefully. I just had to find some place to catch this exception, and handle it.

There are several places you can handle an error in ASP.Net:
  • global.asax (where you can handle application-level errors), overriding one of the following methods
    • Gobal_Error
    • Application_Error
  • Page_Error (where you can handle errors on a page-level)
In addition to this you can define a page to send the user to in case of an error, so the plebs don't have to see the ugly innards of your app. All of these solutions are good, but not for my use-case where I actually wanted to handle the exception, should it occur. These solutions let you do things like log and redirect on errors, but offer little in the way of actually handling the problem.

Yes, on a page I could have used the Page_Error, the problem is that I am building a UserControl, which is part of a page, but not the page itself. And, a UserControl has no onError event to catch, and on Error method to override. In effect the UserControl blew up, killing all bystanding controls and page-elements.

Digging in to where the error originated I saw that it was spawned when the controls on the page where coming to life, in the preRender -stage of the lifecycle. This tells me that I must place some code to handle this before that stage of the lifecycle to avoid this error. In the purely declarative mannar I would declare a handler for some SqlDataSource error event, but that component does not have one. So I am relegated to provoking the error myself, and handling it correctly.

This is not really all that hard, once you've gotten to this level (the realisation that I had to do it this way took much longer than the coding of the fix). What you're forced to do is to not bind the GridView to the SQLDataSource declaratively. Read that again. To handle the error you're forced to step out of the declarative world and do the binding yourself. Now, this isn't hard, but it suddenly seems as if the declarative way of doing things is second-rate and sunshine-days-only. I can live with that, but what I really don't like is how every example focuses on declarative implementation, when it's the less powerful and (to me) less natural way of doing things. Sigh.

Oh, well, on to the fix. Just remove the DataSourceID="someDataSource" element from your GridView decalaration, and add something like this to you Page.Load handler:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
theGridView.DataSource = someDataSource
Try
GridView1.DataBind()
btnSave.Visible = True
lblError.Visible = False
Catch exc As SqlException
lblError.Visible = True
btnSave.Visible = False
lblError.Text = "Could not load table: " & exc.Message
End Try
End Sub

This will let the UserControl come up, even if the datasource experienced an error. Much better, but I'm left feeling it's dumb that I have to do it this way.



Technorati Tags: , , , , , ,