DCSIMG
Google+ June 2007 - Posts - Doron's .NET Space

June 2007 - Posts

Recently I had an argument with a friend about what I felt were the most technically-difficult problems in developing software. These are issues that have troubled developers since the early days of programming, and are inherently difficult. I feel that it is unlikely that they'll be completely "solved" by any new technology.  

5. Spatial data. I might be biased about this, because I work with GIS systems, but there's something about data that has a geographic location that makes it 10-times more complicated to work with. It starts with the coordinates themselves (how do you represent them? where do you store them?) and continues with all these tasks you thrust upon this data. You have to see how different layers relate to each other, to see which data is near to other data, find paths, display it on maps, and it really never ends. In fact it is practically impossible to work with geographic data without a special software to help you out a bit. Even then, though, it doesn't get easy.

4. Packaging and versioning. I've talked about DLL Hell before. Every software is nothing but a group of inter-connected packages, or assemblies, if you wish to speak in the .NET lingo. And our need to separate our code into different parts, each with its own version, is a source of whole world of troubles. You always have to make sure that one part can find the other, and that what is found is really what it expects to find. And that other part has dependencies of its own, and so it continues. COM demonstrated this more than anything else, but every technology I've worked with has tortured me in this regard. Whether it was C, Java or .NET.

3. Relational databases. A relational database is in the base of almost every information system. The thing is, they're not well suited to working with object oriented languages. Yes, OR/M tools can make your life easier, but they do not solve this issue completely. You still have to understand what goes on behind the scenes. To know how your data is persisted and when or why it is loaded when it is. And you still have to write queries and tune them. There is just no way for you to be oblivious to the underlying relational model. And this tabular model  has got nothing to do with the way we see the world, the way we see the objects form and connect. That's what makes it so hard - not working with the database itself - but to be able to fit it with our view of the world.

2. Multi-threading. Well, this is a no-brainer. If you've been developing for a while, you probably ran into threading issues a few times. Multi-threading is so useful (and in web-development, a requirement) and yet it is always such a huge headache. The .NET framework makes it a bit easier for you, but you still have to know your way around your locks and signaling to avoid performance or deadlock issues. In fact, I feel that multi-threading today is not easier than it was when I worked with it in C.  The bad news are this is not likely to change any time soon, on the contrary - with the growing popularity of multi-core CPUs multi-threading is probably going to become more and more important.

1. Dates. This might seem weird to you at first. What's so difficult about dates? DateTime is a lovely .NET struct that solves all your problems in this department, right? Wrong. This attitude is exactly what makes dates the most problematic technical issue in software, in my opinion. You should never underestimate the damage of not working correctly with dates can cause. Take Y2K for example. The entire world was panicking because everyone neglected to use a 4-digit year. The world has never panicked because of a threading deadlock, has it? And we've all seen date-related bugs over and over again. There are too many formats, too many cultures and too many options regarding the usage of dates, and every language and system handles this differently, causing developers great head aches. I've seen caching systems failure, database corruption and scripting hell (I mean really, 0-based index for months? The one who's responsible for this Javascript bit was probably drunk at the time), all because of the importance of Time.

So, which issues do you find the most troubling? Share your thoughts.

Posted by dorony | with no comments
תגים:

One of the really great things about the ASP.NET Ajax Extensions library is its client-side capabilities. It allows you to write OOP-Style code with namespaces, classes, inheritance and the works. Still, learning to use it can be a bit annoying. You don't get the intellisense or documentation support as you would with C#, and all in all the Visual Studio javascript editor is nothing to tell the kids about.

Therefore, what I would have liked is to be able to write some code in C#, and see how it gets translated to javascript. Nikhil Kothari's Script# does exactly that. This is in fact a C# compiler that generates javascript instead of IL. Recently, he added support for an ASP.NET Ajax only mode, meaning the javascript that is emitted relies only on Microsoft's standard library (instead of Nikhil's library).

This is a great way to write and learn ASP.NET Ajax client script. You want to know how to use classes and namespaces in ASP.NET Ajax? Just write it in C# like this:

public class Person
{
private string firstName;
private string lastName;
private DateTime birthDate;

public Person()
{
this.BirthDate = new DateTime(1983,10,18);
}

public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public string Name
{
get { return FirstName + " " + LastName; }
}

public DateTime BirthDate
{
get { return birthDate; }
set { birthDate = value; }
}
protected virtual string GetIntroduction()
{
return string.Format("Hi, my name is: {0} ", Name);
}
public void SayHi()
{
Script.Alert( GetIntroduction());
}
}

And see how it gets translated to this:

TestScriptSharp.Person = function TestScriptSharp_Person() {
this.set_birthDate(new Date(1983, 10, 18));
}
TestScriptSharp.Person.prototype
= {
_firstName:
null,
_lastName:
null,
_birthDate:
null,

get_firstName:
function TestScriptSharp_Person$get_firstName() {
return this._firstName;
},
set_firstName:
function TestScriptSharp_Person$set_firstName(value) {
this._firstName = value;
return value;
},

get_lastName:
function TestScriptSharp_Person$get_lastName() {
return this._lastName;
},
set_lastName:
function TestScriptSharp_Person$set_lastName(value) {
this._lastName = value;
return value;
},

get_name:
function TestScriptSharp_Person$get_name() {
return this.get_firstName() + ' ' + this.get_lastName();
},

get_birthDate:
function TestScriptSharp_Person$get_birthDate() {
return this._birthDate;
},
set_birthDate:
function TestScriptSharp_Person$set_birthDate(value) {
this._birthDate = value;
return value;
},
getIntroduction:
function TestScriptSharp_Person$getIntroduction() {
return String.format('Hi, my name is: {0} ', this.get_name());
},
sayHi:
function TestScriptSharp_Person$sayHi() {
alert(
this.getIntroduction());
}
}

Nice and simple, and even uses the javascript naming conventions for us :-). Now we can easily use this script from any aspx file by referencing it with a ScriptManager control.

<asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Path="~/App_Scripts/TestScriptSharp.js" /> </Scripts> </asp:ScriptManager> <script language="javascript"> var person = new TestScriptSharp.Person(); person.set_firstName("Doron"); person.set_lastName("Yaacoby"); person.sayHi(); </script>

In fact, you don't have to limit your usage of Script# for educational purposes only. The next time I'll have to write lot's of client-side code which uses the MicrosoftAjax library, I will probably use Script# for this. It contains most if not all the functionality javascript provides, and it gives me C#-comfort.

To get started with Script# I recommend watching the 10-minute screen-cast in Nikhil's post. Basically you have to download the MSI and create a visual-studio project using the built-in Script# templates.

A few warnings:

  1. You probably want to turn ReSharper off when you're using Script#, they don't play very well together.
  2. If you're using the "Atlas Class Library" project, make sure you remove any reference to an assembly that starts with ss (such as sscorlib.dll). Those are the assemblies for Nikhil's own script library (which is actually more powerful than the ASP.NET Ajax one, but it is not the standard). The assemblies you need start with aa (mainly aacorlib.dll).
  3. It took me a while to find the full documentation for Script#. It can be found here.

Happy scripting!

Posted by dorony | with no comments
תגים:, ,

I've mentioned before that we're using Team Foundation Server as our source control repository and integration server. We have encountered many bugs in the tool, and have quite a few complaints (like how it's so very slowingly slow), but it was still a definite improvement over what we had before (VSS 6 for source control and nothing for integration).

A few days ago an issue had risen that required us to reinstall TFS. Currently we're our own TFS admins in the company, so it is our responsibility to do this procedure. And there was hell to pay.

Anyone who has tried to install TFS, knows it's not easy. You start with a whole bunch of unclear error messages, which you have to google up for solutions. And once you get through one of those, you get another one. And so it continues, until it ends after a few days of trials and errors. In essence, there are very specific steps you have to go through, and if you leave something out, you have to start all over again. Joy.

Now, reinstalling is exactly like that, only worse, since now you have to worry about all that data you already have in the server. It took us two days to reinstall everything (SQL Server, WSS, TFS and relevant service packs and hotfixes) - apparently there's a new line of errors we haven't seen yet if you're reinstalling and not installing on a fresh machine. Once that was over, we tried to restore our database backups (again, there are specific steps you must take). That of course, didn't work. We were unable to connect to TFS. So we figured we did something wrong in the installation process, and so we reinstalled again. And again. Still nothing - all we have to work with is 5 different errors in the event viewer which show up after we attempt a connection to TFS. Needless to say, looking these errors online turned up nothing.

Currently my team is pretty much grounded on the account of no source control to work with. Our only choice seems to be to recreate our team project on a fresh and uncorrupted database, and check-in local copies of our solutions (losing all history in the process). This will allow the rest of the team to go back to coding, while we continue to try and restore our backups to a different server, so we'll at least have access to the history if we need it.

You could argue that we lack the required knowledge about TFS, and that we need some system team to do the installs/restores for us. You'd be right - this is a new product, and we're still in the process of learning it. And yet, I feel that it shouldn't be this hard. I mean, can't it just work? I've never had such issues with any Microsoft software, or even with ESRI's software which is never easy to install and configure.

Now we're in the risk of losing our source code history, and I can't help but feel uneasy to work with a product that I know to be so unstable. The basic thing I can expect from a source control server is to be able to restore its data from backup, should it happen to explode. I can't sleep easily at night if I'm not absolutely certain that I can achieve that. With TFS, my nights are not easy at all, and I can't help but wonder if we did the right choice when we decided to work with V1.0 of the product. Waiting for the stable V3.0 might have been a better idea.

Posted by dorony | 1 comment(s)
תגים:,

I've been learning WPF for a while now (using WPF Unleashed - a great book by Adam Nathan), and it's really awesome. I'm guessing that soon enough there will be little reason to develop new smart-client applications using WinForms. WPF's API is really well-thought of and easy to work with, and it also makes for such pretty results.

One thing I had an annoying issue with was WPF's commands. Commands are actions in your window (or any other element) that accomplish something and are not specifically related to any button or menu click event.

For example, suppose you have an InkCanvas, which is basically a drawing pad which you can draw stuff on with your mouse, and you want to be able to clear it once in a while.

You could add a "clear" button to the window and clear the canvas on this button's click event, but what if you wanted to have a right-click menu that can do the same? And what if you want it get cleared on "Shift-C"? Using the Click event creates an undesired coupling between the button and the canvas in this case.

So I tried to do this using the Command feature, which allows you to have loose coupling in cases like this. At first, my code looked like this:

<Window x:Class="WindowsApplication1.CanvasExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WindowsApplication1" Height="300" Width="300" > <Window.CommandBindings> <CommandBinding Command="ClearCanvas" Executed="ExecuteClearCanvas"/> </Window.CommandBindings> <InkCanvas x:Name="MainCanvas"> <InkCanvas.ContextMenu> <ContextMenu> <MenuItem Header="Clear" Command="ClearCanvasCommand" /> </ContextMenu> </InkCanvas.ContextMenu> </InkCanvas> </Window>

With the code-behind being:

public partial class CanvasExample : System.Windows.Window
{

public CanvasExample()
{
InitializeComponent();
}

void ExecuteClearCanvas(object sender, ExecutedRoutedEventArgs e)
{
MainCanvas.Strokes.Clear();
}

}

The XAML part contains an InkCanvas, and inside it a context menu (a right click menu) with a "Clear" item. This "Clear" Item is bound to a "ClearCanvas" command, which calls the ExecuteClearCanvas method on its Executed event. Seems OK, no?

This would compile, but will not run. A very unpleasant (and unclear) XamlParseException was thrown at me and I had to duck (har har).

I understand that this is a new technology, but man, I hate it when I have to figure out my own stupidity on my own. I scratched my head for a while, and then I went and read some more about WPF commands.

Apparently, what I didn't realize was the wrongness of this line:

<CommandBinding Command="ClearCanvas" Executed="ExecuteClearCanvas"/>

The "Command" attribute here actually expects something that stands for a real object that implements ICommand. This does not mean that I have to implement ICommand on my own, but I do have to add the following lines to my code-behind class:

namespace WindowsApplication1
{
public partial class CanvasExample : System.Windows.Window
{
public readonly static RoutedUICommand ClearCanvasCommand;

static CanvasExample()
{
ClearCanvasCommand
= new RoutedUICommand("ClearCanvas", "ClearCanvas", typeof(CanvasExample));
}
....
}
}

Here I'm adding the command object to my class, which is an instance of the RoutedUICommand object (this is why I don't have to implement ICommand myself, RoutedUICommand does this already). Now I just have to fix my XAML to refer to this object.

1 <Window x:Class="WindowsApplication1.CanvasExample" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:WindowsApplication1"
5 Title="WindowsApplication1" Height="300" Width="300" 6 > 7 8 <Window.CommandBindings> 9 <CommandBinding Command="local:CanvasExample.ClearCanvasCommand" Executed="ExecuteClearCanvas"/> 10 </Window.CommandBindings> 11
12 <InkCanvas x:Name="MainCanvas"> 13 <InkCanvas.ContextMenu> 14 <ContextMenu> 15 <MenuItem Header="Clear" Command="local:CanvasExample.ClearCanvasCommand" /> 16 </ContextMenu> 17 </InkCanvas.ContextMenu> 18 </InkCanvas> 19
20 </Window> 21

Instead of the "ClearCanvas" string you see this - local:CanvasExample.ClearCanvasCommand. This is our way to refer to the actual command object we created on our code-behind class. The "local" refers to an XML Namespace, which we declared on line 4 - This allows us to import the WindowsApplication1 namespace to our XAML, so whenever we're using "local" we're actually referring to this CLR namespace. At this point everything worked and I was very pleased.

Now, if I wanted the canvas to get cleared on Shift-C, I would only need to add this to my XAML:

<Window.InputBindings> <KeyBinding Command="local:CanvasExample.ClearCanvasCommand" Modifiers="Shift" Key="C"/> </Window.InputBindings>

It's important to note that we don't have to create our own command objects for all the command we are using. WPF has many built-in commands, that reside in static classes such as ApplicationCommands and EditingCommands. They contain useful commands such as "Close", "Help" or "Copy" and "Paste".

To conclude, I feel that WPF commands can help you create nicely decoupled applications when you know how to use them. If you don't, don't expect nice error reporting from the current version...

This concludes my first post about WPF. Since I'm really hooked up on this technology, I guess you could expect more in the future. Oh, and This article has more about WPF commands. Enjoy!

Posted by dorony | 4 comment(s)
תגים:
I've just encountered this amusing note on Gamer's Hell, a known gaming site:

Note to Internet Explorer 6 users: your browser is unable to download files over 2 gigabytes.
If you wish to download large files you must switch to a better browser. We suggest Firefox or Opera.

I loved the use of the word better, and the fact that they didn't even mention IE7. And to think that not so long ago IE6 was the standard 95% of the Internet users used.
Posted by dorony | with no comments
תגים: