Monday, September 24, 2007

I'm not much smarter than a baboon - aouch!

Yesterday I went to Microsoft's software architects users group where Yaniv Hakim, CTO of eWave, discussed the architecture of their eGen application generator.

The lecture was very interesting and very well presented, but I would like to point to his very last slide.

The question is - do you believe everything you read on the Internet?

Thursday, September 20, 2007

Some things speak for themselves

Today I had to meet someone in the village where I live. While waiting for him, my eyes wandered over a public message board. One of the messages looked like that (translated from Hebrew):

"Pretty girl will cook and clean"

Hmm, is that the only thing she is proposing?

Tuesday, September 18, 2007

Impersonating data types

I've already talked about things I'm missing in C#/CLR (here and here). I'd like to add a new concept I would call "impersonation".

Let's start with a simple example:

Say I have a method that calculates the sum of some array of doubles (double[]), like so:

public static double Sum(double[] list)
{
double sum = 0.0;
for (int i = 0; i < list.Length; i++)
{
sum += list[i];
}
return sum;
}

Now I would like to use this method with an input that is not an array of doubles, but some other list of double values (say List<double>, a RowCollection, whatever).


The straight-forward solution is to change the Sum method to receive a collection instead of an array, or make it a template method. But that's when I can change it! What if the method belongs to some class that is not under my jurisdiction?


In this case, the only solution I can think of is to create a whole new array of doubles based on the collection you want to work with. But of course, that's not what I want! First, it costs time and memory. Second, if the Sum method would also change the actual values in the array - you're lost. In my case, it's the first restriction that bugs me.


If the input variable was something else than an array (some class), in most cases you would be able to solve it by inheriting from it and feeding the child class to the method. But then again it wouldn't work for all cases. First because the lack of multiple inheritance (sigh) could restrain you from such solution. Second, in the case the input variable is of some sealed type.


My solution (proposal) - impersonation.


A possible implementation would be an attribute on the class that indicates to the compiler that an object of this type could be used to substitute some other type. For example:

[Impersonate(typeof(double[]))]
public class MyCollection
{
// Implement the parts of double[] you are going to need
}

 


Note that in theory, one could implement in MyCollection only those parts of Array that might indeed be called. Then the call to the method could be done as so:

MyCollection myCollection = new MyCollection();
double sum = Sum(myCollection);

 


And, of course, the compiler should be able to understand the attribute and not generate any errors. Unless, of course, the Sum method uses some features of Array that are not implemented in MyCollection .


Lastly, I would allow multiple impersonations on the same class.

Sunday, September 16, 2007

Asymmetric Accessor Accessibility in C#

Today I wanted to define one accessor with two different accessibility levels. That is, I wanted a property to have public 'get' access and private 'set' access. I remembered that in .NET 2.0 this became possible, but didn't remember exactly the syntax. So I tried first my intuition, which was:

public DataTable MyTable
{
get { return myTable; }
}

private DataTable MyTable
{
set { myTable = value; }
}

Unfortunately, I was wrong. A quick search revealed the secret syntax:

public DataTable MyTable
{
get { return myTable; }
private set { myTable = value; }
}

 


More details in the MSDN entry.

Wednesday, September 12, 2007

Why I urge you to NOT buy an LG laptop in Israel !!!

About a year ago I posted a very enthusiastic post about my laptop, concluding that "I'm pretty sure that next time I buy a laptop, LG will be on the top of my potential brands!".

Today, my friends, I admit I had no idea what I was talking about, because until that moment I didn't run into any problem with the machine. Now that I have, and had to get (no) help from their laptops lab I must say the exact contrary - DO NOT buy LG laptops in Israel, if you want your warranty to have any meaning!

Huh? What? What happened???

I'll try to make it short:

1. It's been some time now that I had 2 main issues with the laptop:

   a. It would suddenly freeze, leaving me no alternative but to hard-reboot it.

   b. The mouse buttons didn't work well.

2. At some point I couldn't work with it anymore, so I had to bring it to the lab. The machine is 2 years old, the warranty is for 3 years - should be a no-brainer.

3. Since the lab is at a remote location, I brought it to a computer shop/lab that works with LG and provide a service of sending/receiving stuff to/from the lab. So far so good.

4. After almost 3 weeks, the laptop was back.

    a. They fixed the mouse-buttons.

    b. The freezing was answered by the so-annoying "you must reinstall Windows".

    c. When I got home I realized that the battery didn't work anymore!!! When I sent it to the lab, the battery was still able to provide me with ~2 hours of work. Now I got it back completely broken: 0 juice, 0 recharge!!!

5. I sent it back to the lab, got it back after again almost 3 weeks, with the even more frustrating answer that the warranty is not valid for batteries. I talked to the lab director, but bumped into a solid wall.

6. Last night I reinstalled Windows. Guess what - when I worked with it now it got frozen once again...

I rest my case...

Thursday, August 30, 2007

Running the same application as Windows Application and Console Application

Say you have a Windows Application (i.e. with GUI and all), and you want to add to it the option to be executed as a Console Application as well. Here are the two steps necessary:

1. Adding Console Application support

You must create your application as a Windows Application. Then open the Project Properties, and under the Application tab set the "Output type" to "Console Application". Once this is set, you must update your Main function to support dual application types. By default, when you create your application as a Windows application, your Main looks like this:

static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}



To support both Console Application and Windows Application, you must change it. For example, you can decide that if it receives as sole argument the string "OpenForm" it will open as a Windows Application, otherwise as a simple Console Application (in which case you'll probably want to take care of the arguments). So you should change your Main as so:


static void Main(string[] args)
{
if (args.Length == 1 && args[0] == "OpenForm")
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
// TODO: Take care of arguments
Console.WriteLine("This is a console application");
}
}



2. Remove the annoying background console


The above code is nice, but has one annoying side-effect - when you open the application as a Windows Application, you constantly have a console open in the background (closing it will close your form). To work around this you must reopen the application (i.e. creating a new process) with the console hidden. This is done as so:


static void Main(string[] args)
{
if (args.Length == 0)
{
Process current = Process.GetCurrentProcess();
string fileName = current.MainModule.FileName;
ProcessStartInfo si = new ProcessStartInfo(fileName, "OpenForm");

si.CreateNoWindow = true;
si.RedirectStandardError = true;
si.RedirectStandardOutput = true;
si.UseShellExecute = false;
Process.Start(si);
}
else if (args.Length == 1 && args[0] == "OpenForm")
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
// TODO: Take care of arguments
Console.WriteLine("This is a console application");
}
}



Explanation:

The assumption is that if you want the application to run as a Windows Application, it doesn't need any argument (though this could also be done easily if required). So if the application starts with no arguments, it will create a new process of itself (through the MainModule we extract the running process' file name), but this time with no console in the background (all the settings on the ProcessStartInfo object). This time, it is called with an argument that knows to load the form (the "OpenForm" argument).



The result is an application that can be run both as Windows Application and Console Application. When you run it as a Windows Application there is a console that opens and closes immediately in the background, but that's all.


Thanks to Ami Bar for helping me with the second step.

Maintainability

A short while ago Oren Eini stated that in his opinion, the only metric that counts is Maintainability. He even gave an excellent way to measure it.

;-)

Ever since I read these two posts, I've been trying to find ways to concretely prove him wrong. The farthest I got was with Performance, where you may have good reasons to improve performance at the expense of harming maintainability. But in good code, this is done only if the improved performance are part of the requirement. In this case, you've got to measure the code compared to some other alternative that still meets the requirement - leaving you once again to measure maintainability only.

My tiny addition to Oren's statement would be - as long as the requirements are fulfilled.

Sunday, August 26, 2007

The C# ?? operator

I needed the C# ?? operator today. This operator returns the left-hand operand if it's not null or the right-hand operand otherwise. I remembered it had the ? sign in it, but couldn't remember the exact syntax. Anyway - I'm keeping it here in my blog for the next time...

Thursday, August 23, 2007

A possible improvement to my Google Image Search API

I discovered today the following article, which mentions my API. An interesting approach they propose is, if I understand correctly, to use some common .NET class to load the HTML, and somehow extract the images from the HTML. When I wrote the API, some 2-3 years ago, I searched for such a thing but didn't find any - maybe I missed it?

If this works, it can remove completely the API's major liability, which is the dependence on the regular expressions. Right now, the API parses the HTML response returned by Google and when the format of this response is changed - the whole thing breaks. On average, since I initially published the API, the response format changed 1-2 times a year.

The downside, of course, is performance - loading the whole HTML will always be much more CPU and memory intensive than using a regex. Yet, for most applications I guess it's a price that can be paid.

Once I have a few spare hours I'll check it out. Or maybe next time Google change the response format and I need to dig into it again. We'll see.

Each line of code should do one thing

I was writing some code today that looks like this:

int counter = 0;
while (/* some condition */)
{
// Do some formatting
counter++;
FormattingProcessStatus(counter);
}

Now I could have done it differently like so:
int counter = 0;
while (/* some condition */)
{
// Do some formatting
FormattingProcessStatus(++counter);
}

which would have "saved" me one line of code. I hate this - I always have. Ever since I started learning C/C++ (over a decade ago) and while trying to solve an exercise discovered a situation where two different compilers generated different results. But today, for the first time, I understood why I hate it so much - it's against a very basic rule that EACH LINE OF CODE SHOULD DO ONE THING.



This is a very simple rule I don't remember having read anywhere, but it's the basis for readable code. Writing code, and even more so - reading code, requires a lot of brain effort. You need to be able to see the whole architecture, and how that particular object and method fits in. Sometimes you need to keep a whole stack of variables (state) in mind to really understand what's going on, etc. The difference between having to read a line that does one single thing and reading a line that does more - is very big, and complicates the reading of the code exponentially.


So if you want your code to be readable - start by making sure each line does exactly one thing!

Fighting car accidents - my five cents

Recently a family was torn apart when a truck driver smashed into a car, killing the father an daughter and injuring the wife and son. The truck driver had a history of over 190 (!!!)  traffic convictions !!!!!!!

Of course, this made a lot of noise, and many people keep asking how someone like that still drives, where have the judges left their sharp brains while judging his cases, etc.

The thing is that there is no concrete incentive to restrain these mad-men. A thing that could help would be to change the system completely - instead of having the insurance policy made on a per-car basis, make per-driver. That is, if I have a driving insurance, it would be valid no matter whose car I drive (much like already exists for mechanics). In addition, all traffic convictions should be made publicly available. The result would be that companies would avoid hiring people with many convictions - because their insurance policies are more expensive and they are dangerous.

The rules of the market will be such that dangerous drivers will have a really hard time to find jobs (especially when the job involves driving a company vehicle), and that, ladies and gentlemen, is one hell of an incentive!

If course, it's not without flaws, but I think it's worth being investigated further.

Marketing: How to give your clients something valuable without any costs

Yesterday I got a letter from Orange, saying something that reads more or less like this:

"Dear Ilan Assayag,

We are approaching the birthday of your client-ship. On August 21, you will be our client for X years. As such, we would like to give you a present you will appreciate. Therefore, during the whole day of August 21, you can talk to anyone on our network for FREE. That's right, on August 21 you won't pay for any conversation to Orange users!!!

bla, bla, bla..."

The thing is - I got this letter on August 22...

WITH keyword in SQL

A feature I didn't know in SQL 2005: WITH can be used to create ad-hoc table-like entities within a query (they call it CTE for Common Table Expression). Check it out here and here.

Wednesday, August 22, 2007

The most hilarious academic paper ever...

It's pretty old, but I discovered it only a few days ago. Some of Israel's brightest minds (such as Shimon Schocken - former dean of the the Efi Arazi School of Computer Science at the Interdisciplinary Center Hertzlia and Yossi Vardi - one of the most prominent hi-tech entrepreneurs and founder of tens of companies) joined forces to write a technical paper claiming that Snails Are Faster Than ADSL. The title is funny, the content is hilarious - take the time to read it and enjoy yourself!

Sunday, August 05, 2007

Getting the system uptime in Windows

Here's something I often need, especially when I need to find out when/why some server rebooted...

To get the system uptime, type this:

systeminfo | find "System Up Time:"

And in general, looking at the results of systeminfo is pretty interesting as well, showing stuff like product ID, uptime, type of processor(s), system directory, language and regional settings, physical memory and page file settings, installed hotfixes, basic network parameters.

Thursday, July 26, 2007

Replacing dates to sortable strings in SQL

Try this:

select replace(replace(convert(nvarchar(19),@Date,120), ':',''), ' ', '_')

Monday, July 23, 2007

Yet another Windows WTF

I am now working on a brand-new machine, running Windows XP 64 bit, with 4GB of physical memory. Being a big fan of hibernation, I wanted to set my system to support it. Guess what - it's not supported!

A quick check on Google showed me this:

"

This issue occurs because hibernation is disabled on computers that have more than 4 GB of RAM.
Hibernation requires sufficient disk space to contain the contents of the computer's memory. Performance is poor on a computer that has more than 4 GB of memory and that has support for hibernation. Therefore, Microsoft has disabled support for hibernation on such computers.

"

The source, BTW, is from Microsoft's knowledge base.

Now you tell me - why do they decide for me what performance is unacceptably poor and what is not? If I have 10GB of ram, I know that hibernation will be slow, and if I choose to use it anyway - it's my decision to take, not MS's!

I haven't tried the workaround proposed yet, we'll see if it helps...

Sunday, July 22, 2007

Enabling xp_cmdshell in SQL Server 2005

It is already known to every SQL newbie that the system xp_cmdshell stored procedure is a huge hole in SQL security. Basically, it allows anyone with permissions to run it to be able to execute shell commands on the SQL machine. To provide a more secure system, in SQL 2005, this stored procedure is not available by default (unlike SQL 2000).

To enable this stored procedure, you should run the following script (for more details about the permissions required see here and here):

exec sp_configure 'show advanced options', 1
go
reconfigure
go
exec sp_configure 'xp_cmdshell', 1
go
reconfigure
go



REMEMBER - this is extremely dangerous and exposes your server to a wide variety of attacks, so be careful!

Thursday, July 19, 2007

New Israeli Blogger - Ami Bar

I strongly recommend you to check out my friend and colleague, Ami Bar's, new blog. He's just started, but now that we are once again working together I intend to push him into blogging as much as possible. Believe me - this guy knows stuff you'll want to know!

Just to show you why, check out his excellent SmartThreadPool on Codeproject.

Good luck, Ami, and may the Schwartz be with you!

Wednesday, July 18, 2007

Changing the number of maximum Internet connections

I know it's an old story, but every time I need it I have to go and search for this information, so I'm posting it here for later reference.

For a reason I don't know (and don't really care), Windows limits the number of concurrent Internet connection available (with XP I think you get 2 concurrent connections in HTTP 1.0 and 4 in HTTP 1.1).

With contemporary computers and the bandwidths of these days, this limitation is archaic to say the least.

So, if you need to be able to handle more simultaneous connections, you just need to add two entries to the registry. To simplify it, just copy the following lines to a file with a .reg extension and then double-click it. It will change the configuration to allow 50 simultaneous connections ;-)

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]
"MaxConnectionsPerServer"=dword:00000032
"MaxConnectionsPer1_0Server"=dword:00000032