Awesome Princess

Welcome to Awesome Princess Sign in | Join | Help
in Search

Princess Programming Blog

  • Abusing IEnumberables in C#

    The IEnumerable<> class is cool because it can be used to represent lazy lists. A lazy lists is just a sequence of data calculated on demand, rather than calculated at the time you create a list. Lazy sequences can represent arbitrarily large datastructures, even lists containing an infinite amount of data, without consuming an infinite amount of memory.

    The match of IEnumerable comes from the yield operator, and it works thing like this:

            static void Main(string[] args)
            {
                IEnumerable<int> list = GetNumbers();
                IEnumerator<int> enumerator = list.GetEnumerator();
     
                Print(enumerator);
                Print(enumerator);
                Print(enumerator);
                Print(enumerator);
                Print(enumerator);
     
                Console.Write("\nPress any key to continue. . .");
                Console.ReadKey(true);
            }
     
            static void Print(IEnumerator<int> enumerator)
            {
                enumerator.MoveNext();
                Console.WriteLine("Print: enumurator.Current: {0}", enumerator.Current);
            }
     
            static IEnumerable<int> GetNumbers()
            {
                Console.WriteLine("GetNumbers: Returning 1");
                yield return 1;
     
                Console.WriteLine("GetNumbers: Returning 2");
                yield return 2;
     
                Console.WriteLine("GetNumbers: Returning 3");
                yield return 3;
            }

    When you call GetNumbers(), you get an IEnumerable<int> back.

    When you call MoveNext(), the code in the GetNumbers() method executes until it gets to the first 'yield return', then it returns from the method and assigns enumerator.Current to whatever what returned from the method. In this case, the first time you called MoveNext(), the function returns 1.

    The next call to MoveNext() causes the GetNumbers() method to resume its execution on the line immediately following 'yield 1', it continues on until it hits 'yield 2'. Another call to MoveNext() resumes where it left off until it hits 'yield 3'.

    Every 'yield' tells the method to pause execution, and every call to MoveNext() tells the method to resume execution from where it has paused.

    The output of the program above is:

        GetNumbers: Returning 1
        Print: enumerator.Current: 1
        GetNumbers: Returning 2
        Print: enumerator.Current: 2
        GetNumbers: Returning 3
        Print: enumerator.Current: 3
        Print: enumerator.Current: 3
        Print: enumerator.Current: 3

    Notice when the method finally exits and there is nothing left to yield, the enumerator.Current simply holds the last returned value of the function. Since the enumerator.MoveNext() method returns true if a value was yielded from the method, and false otherwise, we can enumerate manually through our list using a simple while loop:

            static void Main(string[] args)
            {
                IEnumerable<int> list = GetNumbers();
                IEnumerator<int> enumerator = list.GetEnumerator();

                while (enumerator.MoveNext())
                {
                    Console.WriteLine("Print: enumurator.Current: {0}", enumerator.Current);
                }
               
                Console.Write("\nPress any key to continue. . .");
                Console.ReadKey(true);
            }

    This prints:

        GetNumbers: Returning 1
        Print: enumerator.Current: 1
        GetNumbers: Returning 2
        Print: enumerator.Current: 2
        GetNumbers: Returning 3
        Print: enumerator.Current: 3


    Of course, there's almost never any reason to enumerate manually through our list when we can use a foreach to do the same job:

            static void Main(string[] args)
            {
                foreach (int i in GetNumbers(5, 10))
                    Console.WriteLine("i: {0}", i);

                Console.Write("\nPress any key to continue. . .");
                Console.ReadKey(true);
            }

            static IEnumerable<int> GetNumbers(int start, int max)
            {
                for (int i = start; i <= max; i++)
                    yield return i;
            }

    This prints:

        i: 5
        i: 6
        i: 7
        i: 8
        i: 9
        i: 10

    Notice you can pass in parameters to your IEnumerable method and return a sequence of numbers. If you follow control flow of the program, notice that each item in the list was calculated on demand, rather than all at once; this is a lazy list.

    Lazy lists are fascinating because they can, in principle, represent an infinite series of items. Here is an infinite list of primes:

            static void Main(string[] args)
            {
                IEnumerable<int> primes = Primes();
                IEnumerator<int> primeEnumerator = primes.GetEnumerator();
     
                Print(5, primeEnumerator);
                Print(7, primeEnumerator);
     
                Console.Write("\nPress any key to continue. . .");
                Console.ReadKey(true);
            }
     
            static void Print(int numberOfPrimes, IEnumerator<int> primeEnumerator)
            {
                Console.WriteLine("Next {0} primes", numberOfPrimes);
     
                for (int i = 1; i <= numberOfPrimes; i++)
                {
                    primeEnumerator.MoveNext();
                    Console.WriteLine(primeEnumerator.Current);
                }
                Console.WriteLine();
            }
     
            static IEnumerable<int> Primes()
            {
                int i = 1;
                while (true)
                {
                    int max = (int)Math.Sqrt((double)i);
                    bool isPrime = true;
                    for (int count = 2; count <= max; count++)
                    {
                        if (i % count == 0)
                        {
                            isPrime = false;
                            break;
                        }
                    }
     
                    if (isPrime)
                        yield return i;
     
                    i++;
                }
            }

    This prints:

        Next 5 primes:
        1
        2
        3
        5
        7
     
        Next 7 primes:
        11
        13
        17
        19
        23
        29
        31

    Now, if we wanted to, we can really abuse the hell out of our prime generator by making it recursive and using it like a prime sieve.

            /*
            WARNING: the code above is for entertaniment purposely only.
            If you use this in production code, you will lose your job
            and shame your family.
            */

            static void Main(string[] args)
            {
                IEnumerator<int> primes = getPrimes().GetEnumerator();
                for (int i = 0; i < 20; i++)
                {
                    primes.MoveNext();
                    Console.WriteLine(primes.Current);
                }

                Console.Write("\nPress any key to continue. . .");
                Console.ReadKey(true);
            }

            static IEnumerable<int> counter()
            {
                int i = 2;
                while (true)
                    yield return i++;
            }

            static IEnumerable<int> filter(int prime, IEnumerator<int> listen)
            {
                while (true)
                {
                    listen.MoveNext();
                    int i = listen.Current;
                    if (i % prime != 0)
                        yield return i;
                }
            }

            static IEnumerable<int> getPrimes()
            {
                IEnumerator<int> myCounter = counter().GetEnumerator();

                while (true)
                {
                    myCounter.MoveNext();
                    int num = myCounter.Current;
                    yield return num;

                    myCounter = filter(num, myCounter).GetEnumerator();
                }
            }


    This returns:
        2
        3
        4
        5
        11
        13
        17
        19
        23
        29
        ...

    I have to give credit where credit is due: the inspiration the prime sieve implementation above is ripped from Rob Pike's talk on NewSqueak. I noticed that Pike used channels as sequence generators, which can be represented as IEnumerables in C#.

    My code runs out of stack space after the first 50,000 primes of so. Pike's implementation, on the other hand, efficiently exploits a feature in NewSqueak that allows a programmer to literally replace the current stack frame with a call to another method (a remarkable feature to find outside of functional languages), a luxury that doesn't exist in C#.

    This is an inefficient way to generate primes, but a remarkable exercise in generating sequences.

    Posted Aug 21 2008, 02:00 PM by Princess with no comments
    Filed under:
  • Communicating Between User Controls In ASP.Net Pages

    In general, when I'm creating websites in ASP.Net, I tend to create a lot of user controls. More or less, all of the user interface of embedded in user controls, so that I can encapsulate and reuse specific functionality on any page of my website.

    For example, lets say I have a screen that asks a user to login: on a successful login, the screen displays a welcome message to the user. I would create two user controls, one for the login panel and one for the welcome message, and display them like this:

    The diagram above is a fairly simple layout, and a fairly typical way of designing controls. You might imagine that, on a successful login, the LoginPanel disappears, and the WelcomeMessage displays something along the lines of "Welcome, Bob! You have two new messages."; maybe on an unsuccessful login, the WelcomeMessage displays something along the lines of "Oops, wrong username or password."

    Since our LoginPanel is contained in its own usercontrol, it does not know of the existence of the WelcomeMessage control; since the WelcomeMessage usercontrol is also self-contained, it does not know about the LoginPanel. Yet, we have to make the WelcomeMessage change its state when a user is successfully authenticated from the LoginPanel -- somehow, our LoginPanel and WelcomeMessage controls need to communicate with one another.

    Here is some sourcecode to show the problem in a more concrete sense:

    -----------

    LoginPanel.ascx

    <%@ Control Language="C#" ClassName="LoginPanel" %>
    <script runat="server">
        public bool IsAuthenticated
        {
            get
            {
                return ViewState["IsAuthenticated"] == null
                    ? false
                    : (bool)ViewState["IsAuthenticated"];
            }
            private set
            {
                ViewState["IsAuthenticated"] = value;
            }
        }

        protected void btnLogin_Click(object sender, EventArgs e)
        {
            IsAuthenticated =
                (txtUsername.Text == "user" && txtPassword.Text == "secret");
        }
    </script>

    <div>
        Username: <asp:TextBox runat="server" ID="txtUsername" /><br />
        Password: <asp:TextBox runat="server" ID="txtPassword"
                    TextMode="Password" /><br />
        <asp:Button runat="server" ID="btnLogin" Text="Login"
            onclick="btnLogin_Click" />
    </div>


    WelcomeMessage.ascx

    <%@ Control Language="C#" ClassName="WelcomeMessage" %>
    <script runat="server">
        public void SetMsg(string msg)
        {
            lblMsg.Text = msg;
        }
    </script>

    <div>
        <asp:Literal runat="server" ID="lblMsg" />
    </div>

     

    Default.aspx
    <%@ Page Language="C#" %>
    <%@ Register src="LoginPanel.ascx" tagname="LoginPanel" tagprefix="uc1" %>
    <%@ Register src="WelcomeMessage.ascx" tagname="WelcomeMessage" tagprefix="uc2" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "
    http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
           
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <uc1:LoginPanel ID="LoginPanel1" runat="server" />
            <uc2:WelcomeMessage ID="WelcomeMessage1" runat="server" />
        </form>
    </body>
    </html>


    -----------

    (The WelcomeMessage control is admittedly pretty lame.)

    So, we have two user controls. When a user logs in, we need to display the correct view in mviewControlPanel and set the welcome message appropriately. Now, there are a few "obvious" solutions to this problem; I'll run through a list of possible solutions and comment on them:

    #1) You could simply check the LoginPanel1.Authenticated property on Page_Load, and set everything appropriately. For example, on Default.aspx, you could replace the Page_Load event with the following:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack)
            {
                if (LoginPanel1.IsAuthenticated)
                {
                    LoginPanel1.Visible = false;
                    WelcomeMessage1.SetMsg("Hello, User!");
                }
            }
        }

    That looks like it should do the trick, but it doesn't actually work because the code exceutes in the wrong order. Oops! The ASP.Net page life cycle processes the events in the following order:

    - Default.aspx.Page_Load
    - LoginPanel.aspx.btnLogin_Click

    Since the Page_Load event reads the IsAuthenticated property *before* it gets assigned, your page processes incorrectly.


    #2) To solve the the little "events not executing in the right order" problem above, you might be tempted to move the code above out of the Page_Load event, and into the Page_PreRender event so that it happens later in the page lifecycle.

    This works, but its a notoriously bad work around. The Page_PreRender event gets called on every postback, and its not reasonable to check the LoginPanel.IsAuthenticated variable and re-setup all of the dependent user controls everytime. Setting up a user control for Authenticated/Unauthenticated mode might require a number of database queries or heavy data processing of some kind.

    Additionally, this solution simply scale very well. If we had a large number of interacting controls, the Page_PreRender event would begin to get very bloated. Similarly, if we had a requirement to make the WelcomeMessage talk back to the login control (for example, by putting a logout button in the WelcomeMessage), it would simply be a nightmare to program correctly: on the one hand, you hide the LoginPanel when its IsAuthenticated property is true, on the other you show the LoginPanel when the WelcomeMessage's LoggedOut property is true. What happens when a user logs in, then logs back out? How do you know which order to check the variables?

    Ideally, when a user logs in (or logs out), you want all of your controls to respond appropriately on demand.


    #3) We want the WelcomeMessage text to be set on demand whenever we log in, so the WelcomeMessage needs to respond to an event raised by the LoginPanel. Since ASP.Net is an event-driven language, its trivial to create an event handler

        public event EventHandler UserLoggedIn;
       
        // ,..

        protected void btnLogin_Click(object sender, EventArgs e)
        {
            IsAuthenticated =
                (txtUsername.Text == "user" && txtPassword.Text == "secret");

            if (UserLoggedIn != null)
                UserLoggedIn(this, EventArgs.Empty);
        }

    Now, we can wire up Default.aspx to this event handler:

    <%@ Page Language="C#" %>
    <%@ Register src="LoginPanel.ascx" tagname="LoginPanel" tagprefix="uc1" %>
    <%@ Register src="WelcomeMessage.ascx" tagname="WelcomeMessage" tagprefix="uc2" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "
    http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">
        protected void LoginPanel1_UserLoggedIn(object sender, EventArgs e)
        {
            if (LoginPanel1.IsAuthenticated)
            {
                LoginPanel1.Visible = false;
                WelcomeMessage1.SetMsg("Welcome, User!");
            }
            else
            {
                LoginPanel1.Visible = true;
                WelcomeMessage1.SetMsg("Bad username or password");
            }
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <uc1:LoginPanel ID="LoginPanel1" runat="server"
                OnUserLoggedIn="LoginPanel1_UserLoggedIn"/>
            <uc2:WelcomeMessage ID="WelcomeMessage1" runat="server" />
        </form>
    </body>
    </html>


    The event-driven approach is definitely superior to the methods enumerated above: we change the state of our WelcomeMessage the very moment we click the 'login' button, and we don't have to worry about the page lifecycle. Additionally, if the WelcomeMessage needed to trigger some kind of response in the LoginPanel.aspx control, we could just create an event on WelcomeMessage, catch it on Default.aspx, and call the right methods LoginPanel.

    Notice that LoginPanel and WelcomeMessage do not talk directly to one another. Since they don't know about each others existence, the web page itself acts as a kind of proxy to channel communication from one control to the next.

    Now, while the code above looks pretty good, it is not scalable in the least:

    - Since the web page is our proxy, we can only we can only notify WelcomeMessage of events triggered in LoginPanel through WelcomeMessage's public methods. This forces us to expose a lot of implementation detail to our web page whenever we need two controls to communicate.

    - The example above is somewhat contrived because LoginPanel and WelcomeMessage located on the same container. In the real world, there are probably going to be multiple layers of containers between your LoginPanel and your WelcomeMessage control, similar to this:

    It is too cumbersome and tedious to raise your UserLoggedIn event up through all of its parent user controls, then pass the information back down through all of the nested user controls. As a result, your pages become bloated with code to pass events up and down through controls, and your pages become difficult to modify because moving or deleting any control on your website causes a compilation error.

    - What if, for some reason, you wanted to add another control, such as a NewMessages control, which listened for the UserLoggedIn event? Well, now you have to write more code to funnel events to the WelcomeMessage control and NewMessages control at the same time.

    - Even the graphic above is too generous. For example, if your LoginPanel control is on a master page, and your WelcomeMessage control is on a child page, you don't have the luxury of even knowing what controls exist on a page to funnel messages through, you don't even know if an instance of WelcomeMessage exists to handle your events.

     

    Hopefully now we can see the problem with the method above. We need a more robust message-passing interface to satisfy the following conditions:

    - We don't want to go through hierarchies of controls. No matter where controls are placed on a page, no matter how deeply nested inside other controls they are, we never want more than one proxy of communication between any two controls at a time.

    - We cannot assume that our controls are conveniently embedded into our user interfaces at design time, rather than dynamically created on the fly at runtime.

    - We do not want to expose the internal implementation of our controls if we can avoid it.

    - We need to accomodate new controls who need to listen for events transparently; that is, without needing to change any lines of code in our message-passing interface


    #4) We can satisfy all of the requirements above very easily if we just think about the problem a little differently. It really helps to seperate out message-passing logic from our user interface, so we should create a class which serves the role as a proxy between our LoginNotifier and any other controls:

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.SessionState;

    namespace Notification
    {
        public interface ILoginListener
        {
            void NotifyUserLoggedIn(bool authenticated);
        }

        public class LoginNotifier
        {
            public static LoginNotifier SessionInstance
            {
                get
                {
                    HttpSessionState session = HttpContext.Current.Session;
                    if (session["LoginNotifier"] == null)
                        session["LoginNotifier"] = new LoginNotifier();

                    return (LoginNotifier)session["LoginNotifier"];
                }
            }

            private LinkedList<ILoginListener> notifiers = new LinkedList<ILoginListener>();

            private LoginNotifier() { }

            public void Register(ILoginListener listener)
            {
                notifiers.AddLast(listener);
            }

            public void Unregister(ILoginListener listener)
            {
                notifiers.Remove(listener);
            }

            public void Notify(bool authenticated)
            {
                foreach (ILoginListener listener in notifiers)
                    listener.NotifyUserLoggedIn(authenticated);
            }
        }
    }

    Now we have an adequate proxy to notify controls of the UserLoggedIn event. To use this class, we need to re-write the LoginPanel.btnLogin_Click event as follows:

        public bool IsAuthenticated
        {
            get
            {
                return ViewState["IsAuthenticated"] == null
                    ? false
                    : (bool)ViewState["IsAuthenticated"];
            }
            private set
            {
                ViewState["IsAuthenticated"] = value;
            }
        }

        protected void btnLogin_Click(object sender, EventArgs e)
        {
            IsAuthenticated =
                (txtUsername.Text == "user" && txtPassword.Text == "secret");

            Notification.LoginNotifier.SessionInstance.Notify(IsAuthenticated);
        }


    Now, we need to register WelcomeMessage.ascx with the notifier. I'd prefer to implement the ILoginListener interface on my control; however, since I originally wrote the WelcomeMessage.ascx file using inline script blocks, but I want to provide my own constructor and implement an interface, which means I need to convert to the code-behind model.

    WelcomeMessage.ascx:

    <%@ Control Language="C#" AutoEventWireup="true"
        CodeFile="WelcomeMessage.ascx.cs" Inherits="WelcomeMessage" %>
    <div>
        <asp:Literal runat="server" ID="lblMsg" />
    </div>

    WelcomeMessage.ascx.cs:

    using System;
    using System.Web.UI.WebControls;
    using Notification;
    public partial class WelcomeMessage : System.Web.UI.UserControl, ILoginListener
    {
        public WelcomeMessage()
        {
            LoginNotifier.SessionInstance.Register(this);
        }

        public override void Dispose()
        {
            LoginNotifier.SessionInstance.Unregister(this);
            base.Dispose();
        }

        public void NotifyUserLoggedIn(bool authenticated)
        {
            string msg = authenticated
                ? "Welcome, User!"
                : "Bad username or password";
            SetMsg(msg);
        }

        private void SetMsg(string msg)
        {
            lblMsg.Text = msg;
        }
    }


    Everything simply works like magic. My default.aspx page never needs to know or care about the LoginPanel or the WelcomeMessage controls anymore. More imporantly, this code is reusable; an indefinite number of controls can register themselves with this notifier, and I don't need to add any new code to pass messages up and down through any control hierarchies whatsoever.

    As of right now, if we wanted to create a new event to listen on, we'd have to create a new interface and listener class. There are a lot of ways to make the pattern above a little more generic and reusable, for example:

    public class Notifier
        {
            public static Notifier SessionInstance
            {
                get
                {
                    HttpSessionState session = HttpContext.Current.Session;
                    if (session["EventNotifier"] == null)
                        session["EventNotifier"] = new Notifier();

                    return (Notifier)session["EventNotifier"];
                }
            }

            private Dictionary<string, EventHandler> eventPool;

            private Notifier()
            {
                eventPool = new Dictionary<string, EventHandler>();
            }

            public void Register(string eventID, EventHandler handler)
            {
                EventHandler temp;
                if (eventPool.TryGetValue(eventID, out temp))
                    eventPool[eventID] = temp + handler;
                else
                    eventPool.Add(eventID, handler);
            }

            public void Unregister(string eventID, EventHandler handler)
            {
                EventHandler temp;
                if (eventPool.TryGetValue(eventID, out temp))
                {
                    temp -= handler;
                    if (temp != null)
                        eventPool[eventID] = temp;
                    else
                        eventPool.Remove(eventID);
                }
            }

            public void Notify(string eventID, object sender)
            {
                Notify(eventID, sender, EventArgs.Empty);
            }

            public void Notify(string eventID, object sender, EventArgs e)
            {
                EventHandler temp;
                if (eventPool.TryGetValue(eventID, out temp) && temp != null)
                    temp(sender, e);
            }
        }

    The class above allows a client to register named events. For example:

        Notifier.SessionInstance.Register("UserLoggedIn", SomeEventHandler);

    There are many variations on the pattern above, such as notifying listeners asyncronously, using generics to pass more specific type information than the EventArgs base class, etc.

    As a final note: none of the code above is threadsafe. Make sure that you put locks around any code that adds, removes, or enumerates through items in a collection.

    Posted Aug 10 2008, 12:02 AM by Princess with 1 comment(s)
    Filed under:
  • Beautiful Code and The Beast

    I’m one of those programmers who emphasizes heavily on the aesthetic appeal of code. I describe certain pieces of well-written code as beautiful and elegant, and poorly written code as ugly or dirty. I like Eric Raymond’s explanation of beautiful code:

    Writing these [large Perl programs of significant complexity] left me progressively less satisfied with Perl. Larger project size seemed to magnify some of Perl’s annoyances into serious, continuing problems. The syntax that had seemed merely eccentric at a hundred lines began to seem like a nigh-impenetrable hedge of thorns at a thousand. “More than one way to do it” lent flavor and expressiveness at a small scale, but made it significantly harder to maintain consistent style across a wider code base. And many of the features that were later patched into Perl to address the complexity-control needs of bigger programs (objects, lexical scoping, “use strict”, etc.) had a fragile, jerry-rigged feel about them.

    These problems combined to make large volumes of Perl code seem unreasonably difficult to read and grasp as a whole after only a few days’ absence. Also, I found I was spending more and more time wrestling with artifacts of the language rather than my application problems. And, most damning of all, the resulting code was ugly—this matters. Ugly programs are like ugly suspension bridges: they’re much more liable to collapse than pretty ones, because the way humans (especially engineer-humans) perceive beauty is intimately related to our ability to process and understand complexity. A language that makes it hard to write elegant code makes it hard to write good code.

    The elegance of code seems to coincide with its readability, brevity, and intuitively obvious implementation.

    The Ultimate Measure of Software is User Experience

    From a realistic point of view, the ultimate goal of writing software should be to satisfy users. Users only care about their user experience, they couldn’t care less what your beautiful code looks like.

    Its tempting to think that there’s no point to writing elegant code if users are never going to appreciate it. I used to agree with this sentiment before I started developing software professionally, before I really saw the effects of bad code in the real world.

    Thank you, come again

    Every year, my company attempts to start selling a new piece of banking software. Two years ago, the company wrote up specs on a piece of teller software, eTeller [actual name of software changed to project job], and decided it would be easiest to outsource this software to contracters in India. Our relationship with India was simple: my company would make the business decisions and request features, and India would deliver the code.

    After a year of unsupervised development, we started selling version 1.0 of eTeller. As we expect in the normal lifecycle of any software, we got bug reports, enhancement and new feature requests, etc. India was happy to make the changes...

    ... until around 6 months into the project when India began to slip; they simply weren't able to keep pace with the change requests. After v1.0 was installed, the list of known bugs was on the rise, development of new features came to a stagnant halt, and user satisfaction was taking a dive. The application had serious stability problems, such as crashing or freezing 40 to 50 times a day (not an exaggeration) and a general inability to keep cash drawers balanced.

    When bank presidents started putting the president of my company on speed-dial to demand bug fixes or threaten to find a new software vendor, we realized we had a problem. Since India was unable to make changes to the software, we decided that we simply couldn't rely on India to do their jobs right; we requested access to their sourcecode repository to make the changes ourselves. And that’s when we saw it for the first time:

    The Beast

    Every programmer will eventually encounter The Beast: an application exceeding 10,000 or 100,000 or 1,000,000 lines of the worst, most twisted, most utterly evil, fantastically wicked, atrociously written code on the planet.

    These multi-megabyte monsters are born when large companies attempt to save a few pennies by hiring unskilled amateurs to do professional work. Beasts often rear their heads most often in mission-critical systems such as banks, hospitals, insurance companies, air-traffic controllers, grocery stores, routers.

    Even for a Beast, eTeller was a fright to behold. Here is a brief list of evil:

    • More than 130,000+ lines of tangled, completely unmodularized C#.
    • Excluding form files, there were only 2 classes used in the entire application:
      1) A static class called “Globals”, which held 1000s of variables to maintain the state of application. There were no other datatypes used in the Globals class apart from bool, string, decimal, and dataset.
      2) This SQLHelper class copy/pasted from the internet.
    • 20,000 lines of code embedded in a single file called frmMain.cs. All other code in the application accessed frmMain directly in this fashion:
      ((frmMain)this.MDIParent).UpdateStatusBar(hstValues);
    • To look up accounts, the programmers did something like this:
      bool blnAccountExists =
          new frmAccounts().GetAccountInfo().blnAccountExists

      As bad as it already is creating an invisible form to perform business logic, how do you think the form knew which account to look up? That’s easy: the form could access Globals.lngAcctNum and Globals.strAcctType. (Hungarian notation? What is this, 1997 all over again?) 

    • Parameters were rarely passed between functions, since all state was held in the Globals class. In the rare instance that parameters were passed, they were passed as strings for convenience.
    • Nearly all methods and functions had side-effects, no matter the purpose the function, usually modifying 1 or more variables in the Globals namespace. For example, one of the form validation methods had a mysterious side effect of calculating over and short payments on loans for whatever account was stored Globals.lngAcctNum.
    • Some forms had invisible labels. The programmers used the .Text and .Tag properties to hold miscellaneous data.
    • No objects existed in the application. The only datastructures used were ArrayLists, HashTables, and DataSets — none of which guarantee type safety. The programmers actually invented bizarre pseudo-objects using just ArrayLists, HashTables, and DataSets:
      - ArrayLists of hashtables
      - HashTables using arraylists as keys and other hashtables as values
      - Arraylists of arraylists
      - HashTables using DataRows as keys and ArrayLists as values  

      For a static Accounts class in particular, the programmer created a seperate HashTable for each concievable property of an account: a HashTable called hstAcctExists, hstAcctNeedsOverride, hstAcctFirstName.

      The keys for all of those hashtables was a “|” seperated string. Concievable keys included “123456|DDA”, “24100|SVG”, “100|LNS”, etc. (Most of these hashtables were easy to convert to typed Dictionary objects at first, and eventually into a unified Account object.)

    • CTRL-C, CTRL-V was a favorite key combination employed by India. For example, the 500 lines of code required to print receipts was copied across 7 forms. The code required to implement the "customizable grid" feature was copy/pasted verbatim across 12 different forms.

    • There was an unusual threading model, which I call the Thread-And-Timer model. Every form that used threading had 1 or more timers on it (1 timer per thread). The Thread-And-Timer model looks like this:
      bool finished = false;
      Thread backgroundThread;
      public void SomePublicMethodThatsEnevitablyInvokedRandomlyByAnotherForm()
      {
           try
           {
               backgroundThread.Abort();
           }
           catch { // swallow }
           finished = false;
           backgroundThread = new Thread(someMethod);
           timer1.Enabled = true;
      }
      
      publiv void someMethod()
      {
          // do stuff in the background
          finished = true;
      }
      
      private void timer1_Tick(object sender, TimerEventArgs e)
      {
          try
          {
              if (finished == true)
                  backgroundThread.Abort();
          }
          catch { // swallow }
      }
       

      Each time you click a button, it would start a new thread. If you click the button before the thread finishes its job, then the thread is aborted so that another new job is started. After starting a thread, a timer would check some bool at intervals of 100 milliseconds. When the bool is set to true, the timer aborts the thread for some reason and the resulting ThreadAbortException is ignored.

      This bizarre pattern was found in a dozen different places throughout the application. Naturally, every thread in the application freely accessed any variable, including the ones in the Globals class, without locking.

    • Spectacular abuse of the ternary operator. Here are some actual snippets of code pulled from the application:

      strDrCr = chkCredits.Checked && chkDebits.Checked ? string.Empty : chkDebits.Checked ? "D" : chkCredits.Checked ? "C" : "N";
       
      if (strDefaultVals == strNowVals && (dsTranHist == null ? true : dsTranHist.Tables.Count == 0 ? true : dsTranHist.Tables[0].Rows.Count == 0 ? true : false))

      if (Validations(parPostMode == "ADD" ? true : false))

    That is only a small tip of the iceburg, barely a fraction of all of the errors in eTeller. The most damning part of the application was the total absence of unit tests. Not a single test, for a single one of the 130,000 lines of code. It was evident why the programmers were unable to make changes.

    Crisis-Driven Development

    After seeing the state of eTeller’s ugly code, my dev team became heavily involved with the development and maintenance of this application. From Nov 2007 to Jan 2008, we entered a state of crisis-driven development.

    Banks were demanding to have bugs fixed on the same day they were reported. Each new bug sent us into crisis-mode: we fixed bugs as fast as possible and send a new release to QA almost immediately. Inevitably, 5 new bugs would be documented within minutes of QA testing, so we’d fix those up as quickly as possible.

    Against the recommedations of QA and developers, we were releasing new versions of eTeller once every 2 to 3 days for a couple of months. There were many occasions where we’d be writing bug fixes to a release minutes before updates at a bank.

    Over time, we stablized our product just enough to add new features and respond to bug reports at a reasonable pace. eTeller is continuously being refactored, piece by piece, into a better application everyday.

    What did I learn from The Beast

    While my team was working on eTeller, I discovered how ugly code has a psychological effect on programmers. The amount of frustration working with the code simply sucks the vitality out of programmers, it makes programmers ashamed of their own creations. Unhappy programmers don’t produce quality code or good tests, which holds back the development of application in the long run. Unahppy programmers tend to look for new, less stressful jobs, which also hurts development.

    My team has been hacking through the jungle of eTeller code since Nov 2007. We’ve made significant improvements (especially with regard to type-safe objects and seperation of business logic from UI). We’ve re-written about 25% of the code in eTeller (which, fortunately, corresponds to about 90% of the core eTeller functionality) to the point where the code is marginally palatable. The application line-count is down to around 53,000 non-trivial lines of code, and drops at a rate of 20kb per week. We estimate the final 'gold' version of this application will drop to around 25,000 non-trivial lines of code.

    Don’t let anyone tell you that the beauty of code does not matter to users. High quality code, more often than not, corresponds to a high quality product and satisfying user experience. If programmers want to satisfy our users, then we’re obliged to write high quality, beautiful code in all of our applications.

    (In case you're wondering, we eventually terminated our contract with India.)

    Posted Aug 06 2008, 07:37 PM by Princess with no comments
    Filed under: ,
  • __doPostBack throws error 'object doesn't support this property or method'

    When I was setting up Community Server on this site, I modified the site templates to include a PayPal donation button. After getting positioned where I wanted it, everything seemed to work fine and dandy. Today, I attempted signing out and back in to test some other changes, and Community Server started throwing a javascript error:

    object doesn't support this property or method (line 39, char 9)

     Which happened to correspond to the line of code highlighted in red:

    <script type="text/javascript">
    //<![CDATA[
    var theForm = document.forms['aspnetForm'];
    if (!theForm) {
        theForm = document.aspnetForm;
    }
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }
    //]]>
    </script>

    It was a strange error, because the code is autogenerated by ASP.Net. I thought my browser was screwed up, so I tried restarting it, testing the page in different browsers, looking for malformed HTML, but no luck.

    I happened to have a copy of Community Server that actually worked. I diff'ed a page from my working copy against a page of my non-working Community Server and didn't notice the error at first, The only changes between the two pages was the addition of a URL and IMG tag for my donation button. I took a closer look at HTML and noticed the following:

    <img src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">

    The code I copy/pasted from PayPal include an item with a name attribute with the value "submit". The __doPostBack function calls the 'submit' method on the form... howver, there's an HTML element already on my form called submit. Javascript thinks the code is trying to do something with the IMG element, but it gets confused and throws a fit.

    Solution to the error: remove the superfluous 'name' attribute from the IMG tag.

  • Managing Open Forms in an Multi-Form Application

    My programming team inherited an enormous application written by Indian contractors whose programming strategy appears to have been "write as much code as badly as possible". The contractors were apparently paid by the line of code, because even the simplest tasks were done impossibly badly. One of simple these tasks was opening forms.

    The application is a MDI form application with dozens and dozens of child forms. These child forms could pop up on demand; however, no more than one instance of a child form should be shown at any given time. Its not reasonable to create a singleton instance for each form, because that would put too much burden on the programmer to clean up any previous dirty state on the form left over whenever a form is opened more than once at different points in the application. India's method of handling this requirement resulted in (approximately) this disaster:

        public static class GUIUtils
        {
            public static DialogResult OpenForm(Form form)
            {
                Form tempForm = form;
                foreach (Form f in Application.OpenForms)
                {
                    if (f.Name == tempForm.Name)
                    {
                        tempForm = f;
                        break;
                    }
                }
     
                // show the form and return its DialogResult
            }
        }
     

    All forms are opened up through the GUIUtils.OpenForm method. To call this method, you'd do the following:

            GUIUtils.OpenForm(new frmClient(123456));

    Notice that you have to pass an instance of whatever form you want to open into the method. If, as was frequently the case, the form was already open, then the form instance you passed into the method is just thrown away. Creating forms is not a trivial operation; they can be quite large and require a significant amount of initialization. Its extremely wasteful to create forms without even using them.

    Obviously, we only want to create an instance of the form if it doesn't already exist. The easiest solution appears to be:

        public static class GUIUtils
        {
            public static DialogResult OpenForm<t>()
                where t : Form, new()
            {
                Form tempForm = default(t);
                foreach (Form f in Application.OpenForms)
                {
                    if (f is t)
                    {
                        tempForm = (t)f;
                        break;
                    }
                }
     
                if (tempForm == null)
                    tempForm = new t();
     
                // show the form and return its DialogResult
            }
        }

    Now, instead of passing in an instance of a form, we are passing the type. And rather than comparing forms by their Name property, we compare them by their type. Of course, this still isn't a good solution, because not all forms have a default constructor (for example, some of our forms which display user account information take in an account number). As a result, we can't open certain forms with the method as it stands right now.

    A coworker had an idea that we can pass the constructor arguments as an object array like this:

        public static class GUIUtils
        {
            public static DialogResult OpenForm<t>(params object[] constructorArgs)
                where t : Form
            {
                Form tempForm = default(t);
                foreach (Form f in Application.OpenForms)
                {
                    if (f is t)
                    {
                        tempForm = (t)f;
                        break;
                    }
                }

                if (tempForm == null)
                    tempForm = (t)Activator.CreateInstance(typeof(t), constructorArgs);

                // show the form and return its DialogResult
            }
        } 

    That works, but its not type safe. If we pass the wrong number of arguments into 'constructorArgs', or pass the wrong datatypes, we get a runtime error. We want to be able to pass arguments into our constructor, but we also want it to be type safe so that the compiler can discover type errors at compile time rather than runtime. Taking some inspiration from functional programming, this problem seemed to be easily solved by wrapping up the construction of the form in a function, and passing that function to the method instead:

        public static class GUIUtils
        {
            public delegate t OpenFormDelegate<t>();

            public static DialogResult OpenForm<t>(OpenFormDelegate<t> constructor)
                where t : Form
            {
                Form tempForm = default(t);
                foreach (Form f in Application.OpenForms)
                {
                    if (f is t)
                    {
                        tempForm = (t)f;
                        break;
                    }
                }
     
                if (tempForm == null)
                    tempForm = constructor();
     
                // show the form and return its DialogResult
            }
        }
     
    To call this method, you'd use:

        GUIUtils.OpenForm<frmClientForm>(delegate() { return new frmClientForm(123456); });

    Now our application will only create instances of forms when they are really needed, and we guarantee type safety all at the same time.

    (Naturally, we passed more parameters to the method than shown above to handle cases when we want to replace an open form with the instance returned by our delegate, open the form as modal, etc.)

Powered by Community Server (Non-Commercial Edition), by Telligent Systems