# Coding for Kids #3. Bugs!

In the first post, we introduced the problem.  We’re writing a program that solves the problem of finding 100 point words, where each letter in the word corresponds to its position in the alphabet (A=1, B=2, Z=26).  In the second post, we coded the basic solution that allows the user to enter a word, and we calculate the result. We have a bug, though, because we made the assumption that the letters passed in are lower case.  The word “automated” is a 100 point word, but “Automated” is displaying only 99 points, because the first “A” in the word isn’t getting recognized correctly.  Remember, in computer programming, we need to be precise. There are a couple of ways to solve this.  The first way will be to simply tack on extra if statements to deal with capital letters, like so: if (c == 'a') return 1; if (c == 'A') return 1; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }But, we already decided this function isn’t all that efficient, and this doubles the number of if statements.  Fortunately, C#, and more specifically, the .NET Runtime that hosts the application, has a rich set of functionality in the base class libraries (that is, what’s “in the box”) that can do some typical work for us.   In this case, the string object contains a number of useful methods to convert the entire string to either upper or lower case characters. For example, we can modify the getWordValue function to something like this: 1: private int getWordValue(string theWord) 2: { 3: int wordValue = 0; 4:   5: foreach (char c in theWord.ToLower()) 6: { 7: wordValue += getCharacterValue(c); 8: } 9:   10: return wordValue; 11: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Notice on line 5, we’re calling ToLower() on theWord, which converts the entire word to lower case characters.  If we rerun the application (F5) and try the word “automated” with a mix of characters, we’ll see we get the correct value: Even though we fixed the bug, our code is fragile.  What that means is that there are assumptions about the code that, if not corrected, will cause errors or unexpected behavior down the road.  For example, the getCharacterValue function still assumes the character is lower case, even though getWordValue anticipates that.  Sometimes, and especially in small projects, you just accept that the code is not ideal and move on.  Before we move on to reading files and finding 100 point words, let’s solve a couple of problems here in the code.   The first thing to understand is that computers store all data as 0’s and 1’s … called binary.  Each binary digit is called a bit, and 8 of those are called a byte.  The way computers translate those zeros and ones into a letter and words is through encoding.   Encoding is a standardized way to convert a binary number into a character.   Going through the ins and outs of encoding is worthy of a number of blog posts, but think of it like a map.  The computer sees a binary number like 01100001 – which happens to equal 97 decimal.   The computer has a character map that says the number 97 is equal to the letter ‘a’ (specifically the lower case ‘a’).   Without a character map, the computer has no way of knowing this is supposed to be an ‘a’.   As you might guess, the character map says the number 98 is equal to ‘b’, and so on, where ‘z’ is 122.   And while we’re at it, that character map also says ‘A’ (upper case) is 65, and ‘Z’ is 90.   These numbers have roots in a character encoding set known as ASCII, and it was convenient because all western characters could be represented in a single byte (more specifically, it could really be done with only 7 bits).  Today, it’s common for applications, and our runtime, to use Unicode – a more modern way to map the binary data to characters using extensible code points.  By extensible, it’s possible for Unicode to have code points that encompass virtually any number of languages. The point of the above, though, is that for English use, Unicode maintains compatibility with ASCII.  So, we can rely on those character numbers (65-90 for upper, and 97-122 for lower case) to tell us if we have an upper or lower case number.   Computers can process numbers _real_ fast, so instead of doing an evaluation of the character as we have been, let’s evaluate the number instead: 1: /// <summary> 2: /// Returns the value of a given character, where the 3: /// value is determined by its location in the alphabet. 4: /// (A or a = 1, B or b = 2, etc.). Case insensitive. 5: /// </summary> 6: /// <param name="c">The character to be evaluated.</param> 7: /// <returns>The numerical value of the character, 1-26.</returns> 8: private int getCharacterValue(char c) 9: { 10: //get the numerical/ASCII value of the letter 11: int charValue = (int)c; 12:   13: //if the character is an lower case letter a-z 14: if (charValue >= 97 && charValue <= 122) 15: { 16: return charValue - 96; 17: } 18:   19: //if the character is an UPPER case letter A-Z 20: if (charValue >= 65 && charValue <= 90) 21: { 22: return charValue - 64; 23: } 24:   25: //not an A-Z or a-z character, return 0 26: return 0; 27: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } The first thing we’re doing on line 10 is creating a local variable, charValue, to hold the numerical value of the character, c, passed in.  (int)c is called a cast.   We know we have a character, but we want it represented as a number.  The cast allows us to do that.   We cast it to a variable (charValue) because it reads clearer and is more efficient than casting a char potentially many times over.  A word of warning:  you need to know what you’re doing when you cast.   It’s safe to cast a character as an int to get the numerical value, but when getting into more complicated scenarios, failed casts raise an exception which need to be handled (and exception handling outside the scope of this series).   In general, I wouldn’t recommend working with character values directly unless you really were sure of what is going on encoding-wise.  This is a good example of it being okay, because we have very specific rules and expectations, and the app is overall quite simple. Our if statements on line 14 and 20 look to see if the character’s numerical value falls in the given range.  The double ampersand (&&) is a logical AND operation so both conditions must be true for the if to evaluate to true.   If it’s a lower case letter, we simply return that value minus 96, which will give us a number of 1 to 26.   Same for the upper case, although we subtract 64 to get its value.  The code above is more concise, runs FAR faster (though, is _still_ not the best if can be), but it’s not quite as readable or obvious as to what it’s doing.  That’s where effective commenting comes in.  Notice, too, we solved the upper/lower case issue in a far better way – it’s not as fragile.   We do lose some flexibility, however – if the “game” changes and makes vowels worth double, for example, we’d have to go back to something else.  Also, notice we check for lower case characters first.  This is deliberate:  while it will handle either lower or upper case, if the characters passed in are more often than not lower case, we return the value and it’s one less if block that gets evaluated.   For the purposes of our program, it’s not significant except as an academic exercise in code optimization.  For now, we’ll call this “good enough” and move on to the next challenge:  finding words!

# Persisting User Settings in Silverlight

One topic that comes up frequently in dev circles is persisting data in Silverlight applications.  There are a number of ways to do this, and the right solution depends on the data that is being stored.  In ASP.NET applications, user settings are typically stored in a database and often abstracted through a mechanism like the ASP.NET Profile provider in conjunction with the ASP.NET Membership provider.  The make the end user experience a bit better, log in state (or simply the username) is persisted in a cookie.  In Silverlight, this is still a viable approach (although the data is typically exposed via webservices, depending on the application). Another approach, however, is to use isolated storage.  Isolated storage can be an effective tool for caching data (with a number of caveats).  In the example below, I’ve created a very simple class that contains the application settings I’d like to persist.   The key methods are Load() and Save().   Out of the box, this will work and you can simply add/remove properties as you’d like.  1: public class ApplicationSettings 2: { 3: [DefaultValue(6)] 4: public int MinZoom { get; set; } 5:  6: [DefaultValue(13)] 7: public int MaxZoom { get; set; } 8:  9: [DefaultValue(8)] 10: public int PlotDelay { get; set; } 11:  12: [DefaultValue(false)] 13: public bool RememberSettings { get; set; } 14:  15: public ApplicationSettings() { } 16:  17: public static WorldmapsSettings Load() 18: { 19: ApplicationSettings settings = new ApplicationSettings(); 20:  21: using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) 22: { 23: if (!store.FileExists(@"ApplicationSettings.xml")) 24: { 25: return settings; 26: } 27:  28: using (var isoStream = store.OpenFile(@"ApplicationSettings.xml", 29: FileMode.Open)) 30: { 31: XmlSerializer s = new XmlSerializer(typeof(ApplicationSettings)); 32: TextReader r = new StreamReader(isoStream); 33: settings = (ApplicationSettings)s.Deserialize(r); 34: r.Close(); 35:  36: if (settings != null && settings.RememberSettings) 37: { 38: return settings; 39: } 40: else 41: { 42: return new ApplicationSettings(); 43: } 44: } 45: } 46: } 47:  48: public void Save() 49: { 50: using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) 51: { 52: using (IsolatedStorageFileStream isoStream = store.OpenFile(@"ApplicationSettings.xml", 53: FileMode.Create)) 54: { 55: XmlSerializer s = new XmlSerializer(typeof(ApplicationSettings)); 56: TextWriter writer = new StreamWriter(isoStream); 57: s.Serialize(writer, this); 58: writer.Close(); 59: } 60: } 61: } 62: } [EDIT] Silverlight guru Tim Heuer pointed out I’m doing a lot of extra work I don’t need to.   The ApplicationSettings of the IsolatedStorageSettings allows us to stuff objects in it pretty cleanly – so the above could be implemented like so: 1: public static WorldmapsSettings Load() 2: { 3: 4: WorldmapsSettings settings = null; 5: 6: if (IsolatedStorageSettings.ApplicationSettings.Contains("foo")) 7: { 8: settings = IsolatedStorageSettings.ApplicationSettings["foo"] as WorldmapsSettings; 9: } 10: 11: if (settings == null) 12: { 13: settings = new WorldmapsSettings(); 14: } 15:  16: return settings; 17: } 18:  19: public void Save() 20: { 21: IsolatedStorageSettings.ApplicationSettings["foo"] = this; 22: } I can’t think of a good reason not to do it this way, unless some more complex serialization is called for, but even then I can’t come up with a good scenario for that.  [/EDIT]   Now for the caveat.  Isolated storage isn’t secure unless you take some measures to secure it manually.  While you could encrypt the contents, I’d probably recommend not storing data on the client if you’re saving sensitive data.  In the above example, I’m serializing the data using the XML serializer, so the data is obviously in plain text and stored locally: … and it contains the expected object: 1: <ApplicationSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2: xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 3: <MinZoom>2</MinZoom> 4: <MaxZoom>16</MaxZoom> 5: <PlotDelaySeconds>14</PlotDelaySeconds> 6: <RememberSettings>false</RememberSettings> 7: </ApplicationSettings> Isolated storage offers a lot of potential, but it’s also important to remember the security implications in both exposing the data as well as potential injection points.

# Prototyping a Cache/Disk Serializer

In the 4.0 release of the .NET framework, one of the enhancements I'm most looking forward to is the extensibility of the ASP.NET cache.  Up until 4.0, the caching system was built directly into ASP.NET, and although it was possible to use outside of ASP.NET, it certainly wasn't easy.  And while .NET 2.0 (and up) has a ProviderBase class to use as a point of extensibility, it's a bit of a task if you want to build a robust caching provider.  With 4.0, this will be much easier and more robust.But I'm not on 4.0 ... yet.I don't want to over-design a full fledged system, but what I needed to do was prototype a simple disk-based caching class.  Essentially, a simple way to serialize objects to disk.   While I do make extensive use of the ASP.NET cache in my project, I needed to supplement it because it's just not durable enough.  Reboots, app recylces, memory pressure ... all of these are minor considerations if building these cached resources are not time intensive.    But what if you want to cache a "large" item for a week?  (I say large not just in memory footprint, but also in resources used to construct such an object.)So here were some of my considerations:- Cache object will be the main source of the cache.  If cache miss, check "durable" cache.  It cache miss, reconstruct.- K.I.S.S.  4.0 will solve a lot of my problems.  Not looking to spend a lot of time on this.  (Writing this blog post will take more time than writing the code.)- Need to implement async capabilities.  - Need to implement proper locking.  The first step was to prototype (below) a simple serialization mechanism that handles the serialization/deserialization to disk.   .NET generics help make this a bit smoother, and I chose to use binary serialization primarily for speed over XML, but also flexibility.  Error handling needs to be flushed out, and there's an assumption that there's a single folder (Globals.DiskCachePath) for all objects.  Also, the class uses the HostingEnvironment instead of the HttpContext to MapPath since their won't be a context in an async thread.  This behavior would be abstracted in a more robust solution ... but for simplicity, this works fine. public class DiskCacher<T>    {        public DiskCacher() { }        public static void SerializeToFile(string name, T container)        {            string filepath = HostingEnvironment.MapPath(                Globals.DiskCachePath + name);            Stream stream = null;            try            {                stream = File.Open(                   filepath, FileMode.Create,                   FileAccess.ReadWrite, FileShare.None);                BinaryFormatter formatter = new BinaryFormatter();                formatter.Serialize(stream, container);            }            catch (Exception ex)            {#if DEBUG                throw;#endif            }            finally            {                if (stream != null)                {                    stream.Close();                }            }        }        public static DateTime Deserialize(string name, out T item)        {            item = default(T);            Stream stream = null;            string filepath = HostingEnvironment.MapPath(                 Globals.DiskCachePath + name);            if (!System.IO.File.Exists(filepath))            {                return DateTime.MinValue;            }            try            {                System.IO.FileInfo fi = new System.IO.FileInfo(filepath);                DateTime lastUpdated = fi.LastWriteTime;                stream = File.Open(filepath, FileMode.Open,                    FileAccess.Read, FileShare.Read);                BinaryFormatter bFormatter = new BinaryFormatter();                item = (T)bFormatter.Deserialize(stream);                return lastUpdated;            }            catch (Exception ex)            {#if DEBUG                throw;#endif                return DateTime.MinValue;            }            finally            {                if (stream != null) stream.Close();            }        }     }The two methods are static for simplicity.  I debated using an indexer to store/retrieve, but felt ultimately that functionality would belong to the provider, not the utility methods.  Not worth investing in until 4.0.  Using this is pretty simple.  The type of the object becomes somewhat irrelevant (as long as it can be serialized via the binary formatter).  The simplest example would be:string myName = "Brian";DiskCacher<string>.SerializeToFile("cachename", myName);... and then to rehydrate:string myName;DateTime lastUpdated = DiskCacher<string>.Deserialize("cachename", out myName);Returning the lastUpdated time allows the provider to make a decision as to whether or not expire the item.   A bit more of a realistic example would be:List<Customers> customers = GetMyCustomers();DiskCacher<List<Customers>>.SerializeToFile("mycustomers", customers);and...List<Customers> customers;DateTime lastUpdated = DiskCacher<List<Customers>>.Deserialize("mycustomers", out customers);Generics are certainly not required for this type of solution but do make things easier.  The provider itself would offer a cleaner interface for end users, but from a prototype perspective, this was pretty successful.  Conclusion:  I think .NET 4.0 will offer some great extensibility for disk-based caching and memcaching.  Can't wait to play with it!