i18n,

Ah yes, the fine art of globalization. Let us first examine the subtle distinction between these two infamous concepts as given by our trusty friend, the Wikipedia:

Internationalization is the adaptation of products for potential use virtually everywhere, while localization is the addition of special features for use in a specific locale.

So, i18n is something a programmer does (crafting code to handle potentially all sorts of different locales) and l10n is something a local domain expert should do (creating the actual locales by, for example, translating content, UI labels and selecting culture friendly icons and colors). However, usually this task is also assigned to an unfortunate programmer.

A while ago I had to think about some i18n for a project I’m working on and at first it appeared all the locale data would be stored in a database. When I found out my (old friend) and colleague was already using a simple include file in his classic ASP portion of the project I was delighted because this meant it wouldn’t automatically wind down to a database to store our locales.

Probably because I voiced my delight a little to loudly another colleague started defending databases for storage because it wouldn’t force a re-compile when the actual localization data would change. This argument does not make sense in any environment, classical ASP, VB6.0 or .NET that we work with in our shop, heck, it makes no sense what so ever. There are loads of ways to implement resource files that do not need a re-compile whenever the actual data in it changes. And even if it would, I could probably more easily (and faster) create a new satellite assembly and upload that to the server than edit some field, somewhere in some row of a database.

Databases are often a good choice when storing enterprise data. They abstract the data storage from the applications that use it and usually excel in data retrieval tasks like selecting, sorting and grouping the data. However, this does not mean that they are good for storing everything. More often than not the actual data to store is pretty vague and some things may even be unknown. It is not uncommon to have a table with a lare quantity of columns with an almost equally large number of empty or null fields for every row in the table. This is often a sign that you’re using a database where a database is probably not the right choice.

Take a system like SAP for example. It offers an enormous amount of possibilities and locations (unlimited it seems) to store data about all kinds of entities you might find in a large enterprise. Now think about the amount of human resources it will take to gather and input all that information and consider the percentage that is actually filled out properly (correct formatting and all). It’s probably nearer to 0 than to 100. Continue reading “i18n,”

FreeBSD

A day before FreeBSD 6.0 was installed we hooked up a new 320 GB Western Digital external USB hard drive. This puppy came FAT32 preformatted but I don’t like FAT so quickly re-formatted to NTFS (not thinking about the fact that a n*x OS might not really like this…

However, I was able to mount it straightaway (hotswapping seems to work great) and now can get to my data from both Windows and FreeBSD. Apparently there’s only limited write-support in the FreeBSD NTFS driver so getting stuff from my FreeBSD partitions to the external hard drive might pose problems. Even though, I’m pretty delighted by the fact that I could get to old my old data so easily. Continue reading “FreeBSD”

Xorg

After getting Blackbox up and running and installing Firefox I came to realize my MX700 mouse wheel was not responding. I rarely actually touch the scrollbars anymore these days and having to do so while working in X is not an option for me so I immediately set out to fix this.

After a lengthy google and hack session yesterday I still wasn’t much further and I decided to give up for the day. Today I tried again and got the thing working in about ten minutes after finding and reading this. Here’s a round-up of my current settings. The mouse and wheel are now working excellent.

Note: I’m running FreeBSD 6.0 (RELEASE) with Xorg 6.8.2. Sysinstall already configured moused to run for /dev/ums0.

1. In /etc/rc.conf I had to add one line:

moused_flags="-z 4"

Apperently this is some kind of modifying factor. I didn’t bother too lookup the specifics but I also tried without this line and it doesn’t work and at this moment that’s all I need to now…

2. In xorg.conf I had to modify the “InputDevice” section for the mouse:

[code]Section “InputDevice”
Identifier “Mouse0”
Driver “mouse”
Option “Protocol” “auto”
Option “Device” “/dev/sysmouse”
Option “ZAxisMapping” “6 7”
Option “Emulate3Buttons” “no”
EndSection
[/code]

What really seemed to do the trick for me is the “ZAxisMapping” option but I’m not sure why I have the “Device” option pointing to “/dev/sysmouse”. Maybe it would also work with “/dev/ums0” but again… I couldn’t yet be bothered to dig in deeper. Continue reading “Xorg”

FreeBSD

The whole story will follow later but for now I just want to post a quick reminder to myself about a “su” problem I just finally solved.

After installing 6.0 when first trying to “su” I got the “Sorry” (Bad SU etc…) error so I messed around with the rights on the “su” binary (/usr/bin/su). After this I got “su: not running setuid”. So I added the user-to-su to the wheel group (/etc/group). No sigar. Finally, another google with “su: not running setuid” lead me to this: “Make sure /usr/sbin/su is suid root (and /usr isn’t mounted nosuid)”. So I mounted /usr with explicit “suid”. Still, no succes. At last, I went back to that link and noticed the “/usr/sbin/su is suid root” part… Another quick google lead me to this:

  1. Log in as root
  2. cd to the directory where the program file lives
  3. chown root:bin file_name
  4. chmod 4775 file_name (that will do only the suid and not both suid and guid)

And after executing this lot on the “su” binary I finally was able to “su” from my “working” user…. Geez… It’s secure but a hassle. Though, when you finally find out how it works it’s pretty rewarding. Continue reading “FreeBSD”

Asynchronous

Note to self: when executing invoking a method asynchronously and using a callback keep in mind that the callback is not executed in the same thread as the caller.

At least, it seems so because when I inspected the C1TrueDBGrid’s InvokeRequired property during a debug session on a breakpoint in a callback the property was set to True.

I’m not a big fan of the ComponentOne suite but we just need their “virtual data sets” to get our application up and running in the amount of time we have available. I don’t doubt we could create something similar eventually but not in two weeks probably. Continue reading “Asynchronous”

Thank

Well, it seems “meticulous” in combination with “geek” are ranking pretty much in regard to my site.

number 8 on google

I guess a lot of people have reacted to my rant about “static typing”. No wonder because at that time I was completely off about everything. Too bad not too many people tried to educate me however – next time, let me in on some of that stuff folks!

UPDATE: Well it seems my moment of Google fame only lasted for a few hours. If I execute the same search my site is nowhere to be found… Very strange. Continue reading “Thank”

Boo!

Yesterday and today I’ve been increasingly gripped by a wonderful language called Boo. AFAIK, it’s a relatively new “wrist friendly language for the CLR”. It’s insprired by Python and though I was very interrested in Python for a short while a long time ago I’ve pretty much been indifferent towards it most of the time. But this is not Pythong, no… This is something I can immediately put to use at work – it’s Boo man! Boo!!!

Sorry, but before I get to the wonders of Boo here’s a little background story you need to read:

Corona is an export framework I recently completed for my employer. She’s pretty much invisible but a pretty powerful part of a larger project. I spend a lot of time on her and (to me at least) it shows. However, she speaks C# and my new love is Boo so once in a while I need to talk to her a little. I recently asked her if she could describe to me in short what it does and here’s what she said to me: “I take one or more sources of data, pull some user defined operations on it to transform it into some other data and then write that to one or more popular file formats”. “Yep”, I said, “that’s correct” as I smiled politely to her and went back to jEdit to write some more Boo again.

Anyway, tonight I just couldn’t stop writing Boo and I decided to give Corona a big makeover, this time concentrating on the essential thing: data transformation. Most of Corona’s source originates from a database but because rows are essentially hashtables I decided to move my input focus from a IDataReader to a hash. Here’s my input; it’s a string containing a Boo script declaration of a variable “input” containing a list with hashes inside:
[Boo]inputStr = “””
input = ({
‘firstName’ : ‘Kinte’,
‘lastName’ : ‘Kunta’,
‘age’ : 25,
},
{
‘firstName’ : ‘Bawarsa’,
‘lastName’ : ‘Pamal’,
‘age’ : 24
},
{
‘firstName’ : ‘Quippo’,
‘lastName’ : ‘Quepsilon’,
‘age’ : 27
})”””[/Boo]
I kept my export definition in XML before but now I just written it out as a Boo hash:
[Boo]definitionStr = “””
definition = {
‘name’ : “input[‘firstName’] + ‘ ‘ + (input[‘mid’] + ‘ ‘).TrimStart() + input[‘lastName’]”,
‘age’ : “input[‘age’] * 10”,
}”””[/Boo]
Again it’s a string but this time it contains Boo script with a declaration of the “definition” variable which contains a hash of keys and transformation rules. You can see it creates two fields for every input item: “name” and “age”. It also multiplates the age by 10 for some kind of obscure reason… The name is composed by the firstName, mid and lastName input’s. There’s a TrimStart call in there to prevent spaces when there’s no mid value present.

By the way, if you want to try out the code that follows, you need this import at the top of your script, just below your namespace declaration if there is one:
[Boo]import Boo.Lang.Interpreter from Boo.Lang.Interpreter[/Boo]

Here’s the Transformer class, it has one method: Transform, which takes a single hash of inputs and a hash of rules which is combined into a new hash with the result of these two inputs:
[Boo]class Transformer:
def constructor(interpreter):
_interpreter = interpreter

def Transform(input, definition):
_interpreter.SetValue(“input”, input)
result = Hash()
for rule in definition as Hash:
_interpreter.Eval(rule.Value)
result[rule.Key] = _interpreter.LastValue
return result

_interpreter as InteractiveInterpreter[/Boo]

At this point, I’m not still quite sure how to proceed further so I have this “loose” helper function that walks a list of input hashes and combines the output from the Transform method into a list of output hashes according to the definition:
[Boo]def generate(transformer as Transformer, input, definition):
output = List()
for person as Hash in input:
result = transformer.Transform(person, definition)
output.Add(result)
return output[/Boo]

Note that you need to declare classes and functions before any client script. This is not necessary the best way to actually compose your code (think TDD and behaviour) but when you get to the point of actually running it the declarations must precede client code or else Boo might talk dirty to you.

And at this point we have all our objects assembled and can finally put them to work. First, we need to create an instance of our friendly neighbour: Interactive-“Jolly Good Good Fellow”-Interpreter:
[Boo]interpreter = InteractiveInterpreter(RememberLastValue: true)[/Boo]

I have absolutely no proof and it might very well be not be the case but it’s name and behaviour imply this is not a object to be treated lightly (it’s an InteractiveInterpreter man!) The things I have seen been done by instances created from the InteractiveInterpreter class can for most programmers be only described as “pure magic”. Feed this little puppy any valid boo script (ANY!!!) and it will just go off and do it. Freddy Fixedfingers might know what your script does but there it goes, of and running. Most of the code in this piece is based on the behaviour of the InteractiveInterpreter and I can only add that it has been a long while since I have been so excited about programming in .NET. (Damn this language man, sometimes it even begins to look a little like Smalltalk… I love Smalltalk, don’t get me wrong, but it’s like a drug to be without it… And you just can’t have Smalltalk in a Microfrot shop.)

We also need an instance of our Transformer class that was shown earlier:
[Boo]transformer = Transformer(interpreter)[/Boo]

We now have our central objects so let’s use it to make something of our input Boo script:
[Boo]interpreter.Eval(inputStr)
input = interpreter.LastValue[/Boo]
This creates a list with a bunch of hashes inside (check the script string above). You could think the List the table and the hashes the rows.

We can pull the exact same trick on our transformation or export definition:
[Boo]interpreter.Eval(definitionStr)
definition = interpreter.LastValue[/Boo]
So now we have both an input as well as a defintion instance as well as the transformer to use them. The only thing left to do is call our generate helper function (shown earlier) with all of these objects:
[Boo]output = generate(transformer, input, definition)[/Boo]
The output variable now contains a list with hashes inside. These contain the transformed results as specified by the rules in the definition variable.

Here’s another helper function to explicitly print the contents of a HashList (a List instance with Hash instances inside such as the input or output objects):
[Boo]def printHashList(hashList):
for result as Hash in hashList:
for key in result.Keys:
print key + ‘:’, result[key]
print[/Boo]
However, now that I look at this function I wonder if it is really necessary… Can’t we get Boo to print the contents of such a structure without guidance from this kind of function? (UPDATE: use “join”)

Anyway, we can now check if our transformations succeeded:
[Boo]print “Here’s your input:”
printHashList(input)

print “And here’s what I made of it:”
printHashList(output)[/Boo]

Boo is great. Continue reading “Boo!”

A

Lately, one of our shop’s foundation software products has been showing definite signs of decay (a terrible case of broken windows that is). It’s this bad that even management concluded that we could start developing from scratch a brand new version. All the while maintaining and upgrading the current package as it is. Monday, development on the new version starts and I somehow obtained responsibility to oversee the actual development. This is actually a role I’ve long desired and now I have the chance to prove that I’m up to the task. Unfortunately, I was not very prepared for this twist of fate but now that I have it I will not let go of it very easily.

I already have supplied a solid foundation by pressing upon Scrum as a proces control mechanism. This should provide (us) developers with a solid target and at the same time allow for the necessary creative freedom. Because Scrum is a lightweight method we found no difficulties in agreeing to follow its rules. Monday we’re starting our first sprint aftwer we decide which part of the backlog we’re going to do first.

The team that’s maintaining the old version of the product is not directly involved with development and to be frank this only increases the chances of our team’s succes. I like my collegues very much but some of these characters are turning out to be pretty resiliant against new ways to think about development.

Sorry but I have to sidestep for a moment here.

Today, me and my collegue found ourselves alone with the project leader of one of our current projects. My collegue asked my client if he could explain, in short, what his proces was all about. Fearing the wrong answer, I quickly added that we were mainly interrested in the actual goal rather than the way it was implemented. Failing to come up with something decent I showed him my version: exactly one sentence that fully stated, but nothing more, the mission of our clients proces. Something that I wrote up the night before. A short moment of silence followed before he asked: “could you mail me that please”. Yeah! Shock and awe baby! Or, like Phoenix Wright would say: “Objection!!! This client clearly doesn’t understand it’s own proces! Luckely I’m here to clarify things for him, your Honour”.

Ok, back to business.

So today I’ve added some backlog and monday we make our first selection. I do not doubt there will be a lot of questions so I guess that there will be a whole lot of backlog items to add monday. I “politely refused” to be the scrum master but I think I’m going to ask to be it because I feel like it anyway. Continue reading “A”

Web

Yesterday I finally found some time to try out Ruby On Rails and in one word: amazing.
Two words? Amazingly fun! I was rolling within 2 minutes…

However, even though I wish for it, there’s little hope I’m able to start developing in a friendly dynamic environment like Smalltalk, Ruby or Python. Ours is a Microsoft shop and it’s either ASP or ASP.NET so when compared with the other option .Net isn’t that bad.

Only what to do? I want Rails for .Net too!!! So before I went to sleep last night I wrote “.Net on Rails” on a little piece of paper Imagining I might be able to cook up something myself. Today I found out the project already exists (MonoRail) as part of the Castle Project which incorporates a host of other neat projects such as NHibernate, NVelocity, Boo, Brain, various other projects and also a dependency injection framework.

Although it took me a few hours to get the Castle compiled and rolling this was only due to my own stupidity. I couldn’t even blame the documentation… Continue reading “Web”

DateTime.Parse

Today I had an awful lot of trouble trying to parse a european datetime string (“16-09-2005”) into a DateTime instance. I used the following code and got a FormatException when running this on the server:

DateTime date = DateTime.Parse("16-09-2005");

Usually, the DateTime.Parse method does a pretty good job but now and then it needs a little guidance. I figured this was one of those moments so I called an overload with a specific IFormatProvider:

DateTime date = DateTime.Parse("16-09-2005", new CultureInfo("nl-NL"));

But this also failed in exactly the same way. Pretty puzzled I called in my collegue and after trying all the different overloads of Parse with al sorts of different CultureInfo instances we still couldn’t get this simple string to be parsed.

Then, my collegue suggested trying to set the culture in the web.config file. First I tried setting this in the web.config of the subfolder containing the .aspx pages but this didn’t work so I put the setting in the web.config file one level higher in the root folder of our application and miraculously this worked. Why the stupid Parse function ignored the explicitly passed CultureInfo instance in the first place remains a mystery. Continue reading “DateTime.Parse”