Tuesday, December 23, 2008

Fields vs. Properties

One element of C# that is very useful is the Property member.  Back in the days of C you would declare a struct and the members of that struct (the fields) were all public.  When C++ came along it gave use the concept of hiding our fields behind accessor methods, namely getters and setters.  Java continued this design.  C# introduces a new member type called the property, which makes managing your field getters and setters a little bit easier.  So where you might have Java code like:

public class MyClass
{
  private int myValue;

  public int getMyValue() { return myvalue; }
  public void setMyValue(int value) { myValue = value; }
}

Your C# code might look like this:

public class MyClass
{
  private int myValue;
  public int MyValue
  {
    get { return myValue; }
    set { myValue = value; }
  }
}

It's a subtle difference, but the IDE and language pickup on that syntax and make organizing your "function" methods seperately from your "attribute" methods much easier.  In fact, the latest version of the .NET framework includes a handy syntax feature called auto-properties which let you condense that declaration to:

public class MyClass
{
  public int MyValue { get; set; }
}

Here the private variable is auto-generated by the compiler.  The advantage to providing getters and setters, regardless of your language choice, is that you can later create a derived class that provides additional actions based on the setting or getting of the attribute.  So you might have:

public class MyClassWithSmallValues : MyClass
{
  public override int MyValue
  {
    get { return base.MyValue; }
    set 
    { 
      if ( value > 10 || value
      {
        throw new ArgumentException();
      }
      base.MyValue = value;
    }
  }
}

That example is pretty contrived, but you get the idea.

So where does that leave our old friend the public field?  It is still legal syntax to declar a public variable on your class, i.e.

public class MyClass
{
  public int MyValue;
}

At the base class level, this class would behave identically to either the Java or C# implementation above, and it saves you a bit of coding.  So why is this considered "bad practice"?  Well, as mentioned above, you are now trapped with that attribute on your class.  No matter how many levels of derivation you go, you will always have a MyValue and you have no way of reacting to request or change to that variable.  Still, there are times when this construct can be useful.  If it were bad in all cases the language maintainers would simply strip it out.  Here is a case where I find the public field to still be useful:

public class MyClass
{
  public readonly byte[] MyByteArray = new byte[4];
}

The goal in this implementation is to provide a class that has an array of bytes that is exactly 4 bytes long.  It can never be less, it can never be more.  Each element in the array always has a legal value for a byte.  The readonly keyword above is to instruct the C# compiler that this value can only be set once, and only at the time the class is created.  It can never be written to again, but it can be read.  A user of the class could change the values at each index of the array, but they could never modify the array itself.

The net result is that you save yourself from creating a lot of error catching code.  You don't have to check for the array to be too short or too long, nor for the array being null.  The property is indexable right off an instance of the class, and that without needing to create your own Collection class (which was a bear until MS introduced generics in the framework).  

The one drawback I can see to this implementation is that certain framework components will inspect class properties, but do not perform reflection to find public fields.  So where a DataGridView will data bind to all of the properties in a class automatically, it completely ignores your public fields.  That's just as well, because I don't think that control behaves properly with arrays, but it is worth mentioning.

So to all of the OO programmers of the world: do you still have a use for the public field?  Or is this a concept that can be eliminated from modern compilers?
 

Monday, December 22, 2008

Google Calendar Sync

I am giving up my BlackBerry in at work and reverting back to the use of my PDA (thus the previous posts looking for a cell phone).  As part of this process, I've been looking into different ways of keeping sync'ed, both with my work items and home items.  I tried an open source product called GMobileSync from RareEdge.  On paper it had everything I wanted - it would pull appointments from my Google Calendar and put them on my PDA calendar, and would also push appointments on my PDA to my Google Calendar.  This would allow me to use my PDA as a single source for all of my home and office appointments (and would allow my wife to easily check my availability for doctor's appointments or schedule me as away for any family related things).  Unfortunately, the execution is quite there.  The code is at version 1.3.6, and while it will update my PDA with appointments from my GCal, it won't go the other way (NullReferenceError).  I considered grabbing the code and debugging it, but I'd rather have a solution that just works out of the box.

Enter Google Calendar Sync from Google.  This application runs on the desktop rather than on the PDA, but it does 2-way synchronization between your Outlook calendar and your Google Calendar.  This is perfect, because my PDA syncs with my Outlook calendar anyway.  Now all of my work appointments show up on my Google Calendar, and all of my personal appointments show up on my Outlook calendar.

Wednesday, November 26, 2008

Vista Frustration

Vista is a well beaten dead horse.  Microsoft is embarassed of it, and is rushing to get Windows 7 out the door in the hopes that the world will forget Vista ever happened.  In the meantime, the world is largely ignoring Vista and staunchly sticking to their XP installations.  Personally, I've installed Vista on my work laptop and on my home PC, while leaving the PCs that my wife and kids use on XP.  

For the typical home user there is no compelling reason to upgrade to Vista.  There is nothing that Vista offers you that you aren't already getting from your Windows XP machine.  If you are one of those hold-outs hanging on to your Windows 95/98/Me edition machine....you could get a lot of of XP, but don't go all the way to Vista yet.

One feature that I have grown to like in Vista is the universal search on the Start button.  Hit your Windows key and you can start typing.  Type the name of the application you want to run, and it hunts down the shortcut.  Type the name of the document you want and it lists all matching files.  Type in a URL and it gives you a link to that website.  It is really handy, and I find myself missing it when I move back to an XP box.  Aside from that, the Aero interface is pretty but adds no tangible value.  You would be hard pressed to name any other Vista improvements that would compel you to switch.

What you will find are a bunch of frustrations though.  First, most of your older hardware just flat won't work.  Have a printer that is more than a couple of years old?  Won't work.  How about that scanner you've had for three years?  Nope, that won't work either.  Webcam?  No.  Grrr..  Vista will also gladly gobble up any extra memory you have around.  Remember two years ago when the whole Vista Capable effort started?  At the time, Vista was just on the horizon and PC manufacturers were selling units with the Vista Capable sticker to let you know that it would run Vista perfectly well.  Not so much.  These machines, outfitted with modest graphics cards and 1GB of memory or less, were horrible Vista platforms.  Vista gladly gobbled up that 1GB of memory for itself and then asked hungrily for me, denying the applications that you wanted to run any memory for themselves.  It consumed the majority of your hard disk, and it busied your graphics cards with moronic things to do like rendering the desktop in 3D, or animating your wallpaper.

On top of those intentional frustrations, there are also a number of unintended frustrations.  For one, you may notice that after time the Network, Sound, and Battery indicator icons in your system tray fall of the end never to be seen again.  For reasons unknown, Vista will occassionally reset the preference to display these, forcing you to find the arcane place where you can ask to have them displayed again.

One frustration I recently dealt with had to do with my CD drive and iTunes.  When iTunes installs, it installs a custom CD driver to assist in burning discs.  Unfortunately, this driver is exactly comfortable running on Vista x64.  Recent revisions of iTunes are much better, but the hangup is that if you ever decide to uninstall iTunes, your CDROM is going away with it.  You see, the custom driver doesn't uninstall properly along with iTunes, and it leaves Vista thinking that the drive is broken.  You have to perform a registry hack to get it back (documented here).

So here's some friendly advice from a geek.  If you have never owned a PC before, and you have no existing equipment that you want to run on a new PC, go ahead and purchase a PC with Vista installed.  Most PC's today with Vista installed have the necessary memory and graphics to get the job done, and you won't experience the pain of trying to get all of your old stuff to work.  If, however, you've been using a PC for more than 2 years, don't bother with Vista.  If you absolutely must buy a new PC, ask for it to be downgraded to XP, or see if you can get a refund for Vista and use the money to buy a copy of XP.  You'll save yourself a ton of frustration, and won't be missing anything.

Thursday, November 20, 2008

BeginRead Weirdness

I've run into a bit of an interesting problem with some code I'm working on.  It deals with asynchronous reads on a stream.  Here is a simplified version of the problem:

I have a network device that communicates by a TCP socket.  The client software connects to that TCP socket and issues commands.  Every command should receive a response from the device.  A new command must not be sent until the response to the last command was received.

So initially I wrote some code that looked like this:

public class Reader
{
private readonly Stream inStream;

public Reader( Stream in )
{
inStream = in;
}

public byte[] ReadResponse()
{
byte[] buffer = new byte[256]; 
inStream.Read(buffer, 0, buffer.Length);
return buffer;
}
}

This code worked just fine...as long as the device responded to my command.  Sometimes, the device wouldn't respond.  This might be because the device was unplugged before the response was sent (in which case my Read attempt would eventually return indicating the end of the stream was reached) or the device simply failed to respond to the command.

So now what I wanted was a way to deal with the device simply not responding to a command.  I needed some mechanism that would allow me to block on the read for only a little while.  A perfect place to use the asynchronous read!  So I modified my code to this:

public byte[] ReadResponse()
{
byte[] buffer = new byte[256]; 
IAsyncResult waitHandle 
= inStream.BeginRead(
buffer, 
0, 
buffer.Length, 
null, 
null);
bool waitResult 
= waitHandle.AsyncWaitHandle.WaitOne(
5000, 
true);
return buffer;
}

This change will read back the response if one is returned, or stop blocking after 5 seconds elapses without a response.  This works as I expected - the WaitOne returns as soon as data is available, or after the timeout period.  If the waitResult indicates that the timeout occurred, I can send my next command.  Here is where the weirdness is: the BeginRead attempting to read the response to the first command now reads the response to the second command!  This results in my latest command never receiving a response. 

So my question is, how can I block on a read for a specified period of time and avoid consuming the next byte arriving on the stream if the timeout occurs?  

I've tried a couple of things, and I have a working solution, but I'm not satisfied with it.  My current solution is to use a NetworkStream rather than a base Stream.  I would prefer to use the basic Stream type as it allows me to apply this reader to any Stream source and not just NetworkStream sources.  The NetworkStream has a DataAvailable property that returns true when data is available to be read on the stream.  I poll the DataAvailable property until data arrives or my 5 second timeout occurs.  This avoids the erroneously consumed byte.  However, in addition to the reliance on a NetworkStream source, it also introduces inefficiency as I poll the DataAvailable property.  I can either cause the CPU to spike by continuously polling the property, or I can introduce a Sleep.  The Sleep will allow the CPU usage to remain low, but also means that if the data becomes available while the thread is sleeping, I'm wasting time that could be spent processing the data.

What I really need is a way to cancel the thread that is waiting for the response asynchronously.  Unfortunately, the .NET framework doesn't support this concept.  So my only option to get this working the way I really want is to craft up my own Asynchronous read method.  Unfortunately, I can't think of a way to do this that avoids the polling scenario I have already implemented.

Saturday, October 25, 2008

Drive Space Recovery

If you are like me, when you bought your computer it had an enormous amount of hard drive space that you thought you would never fill.  As time passed and you continued to use the machine, you saw that seemingly impossibly large drive accumulate more and more cruft until one day you get the dreaded "Insufficient Disk Space" message.  Then you make a mad scramble to see just what you can delete safely and not regret later.

The article at 


is a really useful guide for folks using the Vista operating system on how to get some of that missing drive space back.  This works for Windows XP users too, although to a somewhat lesser degree.  Right click on the drive you want to cleanup, then choose properties.  The General Tab will have a button for Disk Cleanup right next to the pie showing you how little space you have left.  If you make use of all of the options in this tool, you can get a suprising amount of drive space back.  Even better, check-out the advanced cleaning options and eliminate all but your last restore point.  Restore points consume a ridiculous amount of space on your drive.

After taking advantage of the advice from that article, I managed to recover 22.3GB of hard drive space.  That's a little more than 10% of the drive!  Even better, I didn't have to make any difficult decisions about backing up or deleting music, pictures, videos, documents, or projects that I had worked on over time.

Sunday, September 18, 2005

Tinkering

It's been way too long since my last post. A couple of weeks ago, the whole family came down with some sort of sinus infection. I'm still not quite done with it, but I think I'm through the worst. This weekend I felt well enough to tinker around with my old Gateway PC. One thing had been really frustrating me for a while: I couldn't boot from a CD-ROM. Not only that, but if I tried using something like SmartBootManager or another Torito stack trick to boot the CD-ROM, I would get an Error 0xAA message. So booting from the CD-ROM was a no-go, even with a boot floppy. I thought maybe it had something to do with the fact that I had upgraded the CPU a couple years back using one of the Evergreen Spectra kits. I took the PC apart and put the old 100 MHz chip back in and flashed the BIOS back to the gateway supplied one (1.0.10.BR0T). It was kind of nostalgic to see that Gateway 2000 logo popup again when I booted the PC.


Anyway, booting from the CD-ROM was an option again in the bios, so I flipped it on and put in my SLAX live CD. Unfortunately, I got an ISOLINUX error. Evidently it was able to try to boot from the CD-ROM, but it ran into some other hurdle in the process. Fortunately, I have lots of spare CD drives hanging around. I took the spare Dell one and put it in, and sure enough it booted up fine. Something about that Plextor CD-R/W was not happy about booting. So then I thought, well maybe I can get this guy to boot to CD-ROM with the upgraded chip back in there. Well, it doesn't work perfectly, but using the SmartBootManager disk I can get it to boot to CD-ROM with the 400 MHz chip installed. Huzzah!


That leads to tonight. I've been trying to get the latest distro of Slackware Linux (10.2) running. It's installed, and I can use it, but it won't recognize my USB mouse. I have a PS/2 mouse plugged in now, and it likes that, but it is sort of a pain because the cable from the KVM is USB. So now I have 2 mice on my deks, one for the Dell, and one for the Gateway. Solving problems like this is part of the "joy" of using Linux. I'm sure I'll have it figured out in the next couple of days, or else I'll just switch to the next distribution.

Wednesday, July 27, 2005

FINDSTR

I learned how to program in a UNIX environment. In a UNIX environment, almost everything is done from the command line (or can be). Sure, there was a GUI that you could click around on, but if you really wanted to get something done, your just wrote a script for it and fired it off on the command line. One of the tools that was really useful was the "grep" command. This command would take a search string as an argument, and then search through all of the files in the directories you specified for that string. It was very useful when debugging code, because you could quickly determine all of the code files that touched a particular class or header file.


Sadly, grep was missing from my list of command line utilities when I moved over to developing on a Windows platform. In fact, the command line was pretty well shunned. Instead, Visual development was the word of the day. I still missed my friendly grep command though. Sometime last fall, I discovered the FINDSTR command in windows. On the command line, the FINDSTR command works much like grep in that it will search for a given string in the subdirectories you specify. It's much handier (to me anyway) than the graphical search tool because I don't have to worry that it isn't skipping files it doesn't recognize as text files. If you want to use it, here is the info:



Searches for strings in files.

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file]
[/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]
strings [[drive:][path]filename[ ...]]

/B Matches pattern if at the beginning of a line.
/E Matches pattern if at the end of a line.
/L Uses search strings literally.
/R Uses search strings as regular expressions.
/S Searches for matching files in the current directory and all
subdirectories.
/I Specifies that the search is not to be case-sensitive.
/X Prints lines that match exactly.
/V Prints only lines that do not contain a match.
/N Prints the line number before each line that matches.
/M Prints only the filename if a file contains a match.
/O Prints character offset before each matching line.
/P Skip files with non-printable characters.
/OFF[LINE] Do not skip files with offline attribute set.
/A:attr Specifies color attribute with two hex digits. See "color /?"
/F:file Reads file list from the specified file(/ stands for console).
/C:string Uses specified string as a literal search string.
/G:file Gets search strings from the specified file(/ stands for console).
/D:dir Search a semicolon delimited list of directories
strings Text to be searched for.
[drive:][path]filename
Specifies a file or files to search.

Use spaces to separate multiple search strings unless the argument is prefixed
with /C. For example, 'FINDSTR "hello there" x.y' searches for "hello" or
"there" in file x.y. 'FINDSTR /C:"hello there" x.y' searches for
"hello there" in file x.y.

Regular expression quick reference:
. Wildcard: any character
* Repeat: zero or more occurances of previous character or class
^ Line position: beginning of line
$ Line position: end of line
[class] Character class: any one character in set
[^class] Inverse class: any one character not in set
[x-y] Range: any characters within the specified range
\x Escape: literal use of metacharacter x
\ xyz\> Word position: end of word

For full information on FINDSTR regular expressions refer to the online Command
Reference.