ctodx

This Blog

News

Favorite Posts

Archives

July 2006 - Posts

  • More on swallowing and throwing...

    I've had some excellent replies to my original post on exception handling in our UI controls and some of the points made have given me much food for thought. I'd have to say though that John Gooding's reply most closely fits my view of things.

    If I may summarize the main points:

    • Our code should never show a message box to display an exception message
    • Adding the ability to log exceptions is good
    • The way it works at the moment (swallow exceptions for certain code paths) is acceptable in some cases (for simple apps, to fire off some default behavior)
    • There should be some way for the developer's code to decide whether an exception should be swallowed or rethrown
    • We should create and use our own exception classes

    Well the first item goes without saying, really. For example, I hate it if I'm baldly informed that a list index was out of bounds (so, what exactly do you want me to do about it?), and I certainly wasn't advocating that our UI controls should display a message box for a WinForms application!

    No, in my opinion, this is solely within the purview of the application developer. The poor application developer (and that means our customers, of course!) must test his application enough to understand the problems that can occur, and have programmed defensively against those exceptions he feels the application can automatically deal with or recover from. The others may be exposed to the user as a general "The application has encountered an error and needs to close" dialog box, perhaps with a More... button that shows the original exception and stack trace with a "phone home" capability to upload it automatically.

    Second, exception logging. To be honest, for me this is extremely important. Last job I had before Developer Express was for a company that wrote software that ran on many machines across the enterprise. Code was written in C++, VB6, and C#. If something went wrong we had to know about it and we had to have good enough logging to understand what led up to the problem so that we could trace through the code flow. All the user would see would be a dialog saying an unexpected error occurred and that they should look for more details in the log.

    I'm reminded of a problem I encountered in CodeRush 1.x. I wanted to change the behavior so that certain single key templates wouldn't be expanded. I made the change in the options dialog, pressed OK, and went back to my editing. Lo and behold it was as if my changes hadn't taken place. I went back into the options dialog made the same changes and pressed OK again. No change in the editor: those single key expansions continued to occur. I was just about to fire off an email when I remembered Mark talking about the messages log. I found it, discovered what the problem was (directory not found, essentially), fixed it, and everything was fine.

    That story has two morals: first, if an error occurs, it's best to let the user know about it somehow. Not by throwing a cryptic exception message in the user's face, but by displaying something to say that his task didn't complete and that further information is available somewhere about the exact cause of the problem. Second, have a log where all exceptions get recorded. Including stack traces if possible.

    (We implemented the latter at my previous job: a complete recording of the information in a .NET exception, including stack traces and recursing through inner exceptions, and cycling through all errors in a SQLException instance. To say it saved our bacon is an understatement. It also goes without saying that, by having this code in a production environment, we discovered many bugs that had simply been hidden by a previous catch-and-swallow strategy (including a situation where we weren't properly impersonating an authentication token the first time through some code.)

    So I definitely like the idea of having some kind of notification interface through which our controls can log exceptions before discarding them. It'll be up to the app developer then to implement a logging facility that we can call when we catch an exception (a first chance handler). I don't particularly want to go as far as having a generic logging interface through which we can log informational messages or warning messages, since we'd then get into a huge discussion about what we should log and when (on entry into a method? before we raise an event? Etc). Say something like this in our code:

    try {
      // do something risky
    }
    catch (Exception ex) {
      DxLogger.GetInstance.LogException(ex);
    }

     
    where DxLogger is some kind of Singleton class or interface we provide that you can extend using event handlers, or some such mechanism.

    Even better, perhaps:

    // somewhere in your startup code..
    DxExceptionProcessor.ProcessException += new ExceptionProcessor(MyFirstChanceExceptionProcessor);

    // in our code
    try {
      ..blah..
    }
    catch (Exception ex) {
      if (DxExceptionProcessor.GetInstance.ShouldRethrow(ex))
        throw;
    }

    Which would give you the opportunity to not only log the exception, but also to decide whether a given exception is bad enough to rethrow and thereby, presumably, terminate the application or at least get some other code involved in processing it (say the appdomain's exception handler).

    In fact that last design gives us a good start on providing a solution to most of the points made.

    • If you don't want to handle exceptions caught in our code, don't provide an exception processor. Our code will work as before.
    • If you want to log exceptions but otherwise do nothing about them, write an exception processor that does exactly that and returns false so that our code doesn't rethrow.
    • If you want to log exceptions and also make decisions about which errors to swallow then write an exception processor that does exactly that. The problem is you won't have that much information to make good decisions at this point (remember, this will happen in a low level in our code, not at a higher task-based level in your code).
    • If you want to log exceptions and also make sure they propagate up the call stack, then write a processor that returns true (to rethrow) after logging.

    Comments?

  • A sense of release

    To say it's been hectic around here is a wholly inadequate use of the English language. It's been ruddy nuts.

    Today, we released our ExpressPivotGrid for our Delphi customers as well as a raft of other minor bug fixes and enhancements for our other VCL controls. Those who have the VCL Subscription can start downloading it this weekend from their space in the Client Center. It will formally be released for sale on Monday, and at that time we'll have opened up the newsgroup for it.

    This is a great control (and it seems a little undeserving to call it a mere "control" given its functionality) that gives you some juicy data mining capabilities for your data, like drill-down, auto sorting and summarizing, arranging data into hierarchies, filtering data, and so on. More details can be found here.

    As usual with our Delphi products, it comes with full source code and is either free with your VCL subscription, $329.99 for just the product, or $249.99 for existing ExpressEditors Library v5 customers.

    The Developer Express VCL team have done an awesome job with this, but there's absolutely no rest for them -- cue evil CTO laugh -- apart from this weekend, that is, because they are working on some great enhancements for the grid and a rather hush-hush product that will come later this year.

    And then on Monday, after a week of almost being there, the IDE productivity team will be releasing v2.0.4 of CodeRush and Refactor! Pro. If you've been watching the newsgroups, you'll have seen the version number slowly, inexorably tick up from 2.0.2 to 2.0.3 to finally 2.0.4 without anything getting released, leading a wag to post that it appears as if at this rate we'll be releasing version 3.0 next Friday. Hah!

    This release is essentially a set of bug fixes with no extra functionality that I know about (but I dare say Mark will prove me wrong). Oh, and we've worked out the bug with Internet Explorer 7 beta so that you can now see the new training window when that browser is installed (Dustin tells me that a COM API was changed between 6 and 7 causing the problem).

    This release is free to all CodeRush/Refactor! Pro customers. I warn those customers who are on their free maintenance subscription period for the IDE productivity tools that it runs out Thursday, September 14. You'd better consider renewing otherwise you might miss out on the new functionality we're adding for *cough*ASP.NET*cough*.

    And then the .NET teams are working all hours to prepare and ready DXperience 6.2 for your delectation. It's getting really close now and there's some great stuff in it, including those spiffy AJAXed ASP.NET controls you've been seeing all over our new website. More news on that later on.

  • On swallowing and throwing...

    It seems that it's my destiny to talk about exceptions (see here and here on my personal site, as examples). But because this blog entry is going to be about them and it's right here on my work blog, you can rest assured that I'm going to talk about them now in relation to our products.

    I read Framework Design Guidelines by Krzysztof Cwalina and Brad Abrams, architects on the BCL team at Microsoft, a few months back just before I was interviewed for my current job at Developer Express. It's a great compendium of topics on designing a framework or a library that's going to be used by many developers. The thing is, as I realized at the time, it's not just about writing frameworks and libraries for sale, much as Developer Express does. The advice in this book also applies to internal developers who are writing reusable code for their colleagues. By following the conventions and standards what Microsoft have done in the .NET Framework (and by understanding the issues they faced and the solutions they took), the people who will use your framework will find it familiar.

    Anyway, one of the points in the book that really struck me was made by Krzysztof: "Each exception can carry two main pieces of information: the exception message explaining to the developer what went wrong and how to fix it and the exception type that should be used by handlers to decide what programmatic action to take." (Page 184) Hold that thought.

    I would argue that when we use a library or a framework, we expect it to let us know when things go wrong, when it encounters a situation that it can't handle. Suppose some method would fail if we passed in a null reference. We would expect the method to check and to throw a NullReferenceException. If a file wasn't found, we'd expect to see a FileNotFoundException. And so on.

    Sometimes we'd accept the framework wrapping a lower-level exception inside its own exception class. So that, for example, an attempt to open a configuration file might result in a file not found, access denied, etc, type exception, but the framework wraps them all inside an "Unable to open configuration file" exception (and to see the real reason why we can look at the InnerException property).

    Now this is where it gets interesting and I need some advice from my readers. Although we do have a couple of frameworks (XPO, and XAF in beta), we're mostly known for UI controls.

    So, would you expect a UI control like TextEdit to throw exceptions that it couldn't deal with? Or would you expect the control to perhaps swallow (that is catch and not rethrow) as many as it could, and only let out those it couldn't do anything about? Do you find the thought of possibly bad or catastrophic exceptions in your code being discarded by your control? Maybe you think that this question is a "beginner versus advanced" type topic, in that beginners would be confused by unforeseen exceptions so the more the control discarded the merrier, but that advanced developers already have a sophisticated exception handling subsystem and need to "see" them all (or at least those that are not recoverable).

    Let's take a concrete example from our code (this is from the hyperlink editor) so that we can get away from hand-wavy generalizations.

      Process process = new Process();
      process.StartInfo.FileName = (e.EditValue == null ? string.Empty : e.EditValue.ToString());
      process.StartInfo.Verb = "open";
      process.StartInfo.WindowStyle = Properties.BrowserWindowStyle;
      try {
          process.Start();
      }
      catch {}

    If the process, that is, the browser in this case, doesn't start, for whatever reason, our code just swallows the exception. You, the developer (or the user) don't get to understand why (unless you happen to be running in the IDE and you've activated the "get first-chance exceptions" option); it'll just seem as if the code isn't working. Even worse, the code in the try block may fail due to some entirely different reason, a catastrophic problem like out of memory or a thread abort and again you wouldn't know why. Of course, the entire call stack in the exception is also thrown away, so that you and we would have a much harder problem trying to understand a context-sensitive bug.

    My argument here is that, if the catch block were removed, you at least have the choice to do something about an exception that might be raised in this try block. Maybe you don't care about why it fails, just like the code as written, so just add a similar catch block in your code and discard the exception. But if you do care, suddenly you are in a whole better position than before. But either way, you have to do more work.

    My questions to you are these:

    • Is this kind of code acceptable in a UI control? Is a UI control just some kind of black-box where we don't care about errors?
    • If it isn't, and we cleaned up this and similar code so that you, as developer, started getting a whole bunch of exceptions, would you know what to do to catch them in your UI layer and properly process them (such as logging them)? Or would it be too disruptive? Would you be ready to have to do a lot more work in your forms?
    • For WinForms controls, that's certainly a problem but it's fairly solvable. What about ASP.NET controls? There your app is running an a server somewhere. There is no UI at the server. If you're not careful, your exceptions get sent to the client as an error page and you know how dumb that can be. But do you know how to catch and process exceptions like that?
    • Given the quote above, I would suppose you'd prefer different exception types for different errors. Or maybe not? Would Exception instances be fine?
    • Are you an advanced developer with a good solution to unhandled exceptions? Do you use something like the Exception Handling Application Block from the Patterns and Practices group at Microsoft?

    As you can see, I'm debating whether we should make some pretty major changes to our code, but only if there is support from our customers. Over to you...

  • Watch That Man

    There was a series of newspaper/magazine ads recently here in Colorado Springs (where I live) for a local bank. Each ad showed a particular VP or manager of the bank, described his or her position, and then gave his or her cell phone number. Not the bank's main phone number, mind you, the individual's cell phone number. The theory went that, if you had something to phone up about, good or bad, you could get to the person who was responsible directly. The ads, apparently, went down really well: it showed that all staff of the bank were approachable and were charged with interacting directly with customers.

    So in that vein: if you have something to say about Developer Express on the technical or technology side (I am after all Chief Technology Officer :-) ), that is, something to say about the products, the documentation, the support, the install -- whether what you have to say is good or bad -- you can reach me in two ways.

    Email: julianb@devexpress.com
    Main: +1 818 844 3383 ext. 206

    I would ask though that, if you do want to phone me, to please limit the hours between 9am and 5pm Mountain Time (GMT-7), Monday to Friday. You may find I'll answer outside those times, but I can't guarantee it (yes, I do have a home life too!).

    Please do note a couple of caveats though (ah ha! the fine print!).

    First, I'm really not a support engineer. If you want to know how to do A with our B component, I'm just not the person to ask; that's what our support team are for. They work day in day out with our components and know far more, far better than I. I'd be a complete bumbling idiot. But if you want to say "X was brilliant at solving my problem, he ought to get the employee of the month award" or "I can't seem to get a timely answer from anyone in support" then by all means contact me and let's talk about it.

    Second, I can't help you in any meaningful fashion with client services type things. I really can't: I'm just not connected to their systems in any form. So you should continue to use clientservices@devexpress.com or our main phone number +1 702 262 0609.

  • Guide to ORMs, part 2

    In the first part we outlined the worlds of the database and the application that, although superficially similar, are really different universes bridged by what are known as ORMs (or object-relational mappers). We also showed one problem of the mismatch between the universes, that of the identity of an entity (that is, a row in the database or an object in the class model). We did not try and sort out the identity problem, just noted that it was an issue.

    This time, let's explore the mismatch space between the database and the object-oriented application a little more.

    Suppose we want to design a UI control application that will provide controls to be rendered onto a screen. The developer calls certain APIs in our application and we'll serve up a fully-configured button or combobox or textbox and so on. Later, the developer can call other APIs and store a configured component under a particular ID for later retrieval. We'll be storing these objects in a database.

    Because we're great OO designers, we have a nice little class model that defines all this. So we have an ancestor Control class with properties like ID (we're assuming that this is the identity field for a control), Left, Top, Width, and Height, and various descendants like Button (which has a property called Caption), TextBox (which has properties like Prompt, Text, and so on), and ComboBox (with an Items property containing a list of the items in the combobox and an SelectedIndex property for the selected item's index in the list).

    But now comes the $64,000 question: what should our database schema look like? Think about it for a while before reading on.

    First thing to realize is that relational databases have no concept of inheritance. Zero, nada, zilch. This is a huge problem for our example: a Button is a subclass of Control, a TextBox is too, and so on. How are we going to be able to store our Buttons, TextBoxes and ComboBoxes? This is another big object-oriented relational mismatch: the problem of storing an inheritance object model.

    So it looks like we're going to have to fake inheritance in our database. Somehow.

    There are three accepted ways of doing this, as it happens. The first one is to have one table per class. So, in our example we'll have a table for the ancestor class, Control, that will have columns called ID, Left, Top, Width, and Height. Then we'll have a table for Buttons that will have a column for Caption. The problem is that we need to link a row in the Button table with its corresponding row in the Control table so that we can get the Left, Top, etc, properties. The best way is to have the ID column replicated in the Button table and then we can join the Control table to the Button table through this column.

    Notice that this solution to the inheritance model problem means that our SQL queries are going to always be pretty horrendous. Every time we execute a query that returns Buttons, say, we will have to join the Control table to the Button table.

    SELECT (c.ID, c.Left, c.Top, c.Width, c.Height, b.Caption)
    FROM Button as b
      JOIN Control c ON c.ID = b.ID
    WHERE b.ID = @ID

    And the SQL for adding or updating or deleting a button? I leave that as an easy exercise for my SQL-savvy readers.

    Here's an even worse scenario: suppose we wanted all controls that were at aligned on the left at 10 pixels? The query would have to join the Control table to every other table that stored concrete controls like comboboxes and textboxes.

    So, although the premise to the solution is easy to understand (one class per table), the mechanics of using it tends to be fairly nasty looking.

    The second solution to the inheritance problem is the one table per concrete class solution, where "concrete" means "can be instantiated to provide a useful object". This one actually fits our problem quite nicely as we'll see.

    The first thing to accept is that the Control class is never instantiated on its own. Yes, we may pass around Control instances or have arrays of Control instances, but they're all actually instances of other classes like Buttons, Textboxes and so on. The Control class is an ancestor class whose only reason for being is to store "common" data for all our controls. So, form the viewpoint of the database, we merely merge the properties of the ancestor class into each of the concrete control classes.

    So our Button table in the database will contain columns for ID, Left, Top, Width, Height, and Caption. The TextBox table will have columns for ID, Left, Top, Width, Height, Prompt, and Text, and so on.

    This makes the retrieval and update of our control objects a little easier to do since the SQL becomes a lot simpler. Our OO code in the application (the ORM, if you like) is a little more intricate, but OO code tends to be easier to write and test than SQL.

    We still have the problem though of a complex query to the "get all controls that are aligned left at 10 pixels" issue with lots of joins all over the place. Nevertheless, this solution tends to be the one that everyone uses.

    The third and final solution to the inheritance problem is the one table per inheritance tree solution. Here we just have one table for the entire class model. We'll store all types of controls in it. The table will have not only ID, Left, Top, Width and Height columns but it will also have a Caption column (for the Buttons), Prompt and Text columns (for the TextBoxes), and a SelectedIndex column (for the combobox, and I'm deliberately skipping the Items property here).

    There's another column that needs to be added as well since we need to be able to tell whether a particular row defines a Button, a TextBox or a ComboBox entity. We could try and be clever and use tests to see whether various columns are null or not to determine the type of the control, but generally we add a discriminant column of some type (say a character) that defines the type of the row (so a B in this column means the row is a Button instance, a T means Textbox, and so on).

    Although retrievals and updates with this solution are pretty easy (barring the need to worry about the discriminant column), the main issue with this solution is the number of empty values we'll be storing. A button, for example, needs no Prompt, Text, or SelectedIndex values so those columns will be empty for every button. Nevertheless, this is still an accepted and widely-used solution (I remember in my RPG days on the System/38 constructing views over data that replicated this solution to make it easier to leverage the RPG record processing cycle).

    Next time we'll start thinking about how XPO makes it easier for us to solve these issues.

  • From the Dept of the Ruddy Obvious :-) ...

    You must have noticed by now that we have a new look-and-feel on our main website and a Client Center that replaces the old MyDevExpress.com website (trying to go to the latter redirects you to the new Client Center). Congratulations to the team that did such stellar work on getting this ready to go live, and over the holiday day too.

    Our reasons for making these changes are many-fold:

    • The old website had been around for quite a while, way longer than I've been aboard at Developer Express (shhh, but I think it looked like that when I worked for TurboPower!). Sometimes, having a new look and feel is reason enough on its own, and I admit I like the freshness of the new layout. I dare say we'll be tweaking bits here and there over the next few days and weeks (yesterday, when we went live a few links were broken, for example), but I think we got the main "look" right.
    • We've been working on a completely new set of ASP.NET controls over the past few months and will be releasing them soon, in just a few weeks. What better way to talk about and show them off than to use and test them in our own website? (The term for this is dogfooding.) Unfortunately, the old website wasn't written in ASP.NET and so it indicated a rewrite.
    • Talking of dogfooding, our new ASP.NET controls are full players in the AJAX world. Can we talk about how efficient our controls are without having used them for real on a real website visited by many, many people every day? Er, no, of course not. So, real life AJAX testing? Check.
    • And since we were talking of dogfooding, we sell a product called eXpress Persistent Objects (known as XPO) and needed to show our customers that it too is fully able to do the heavy lifting for a full online store. So, we used XPO as our data access layer for the new site.
    • And even more dogfood than that (yep, we can't wait to have a filet mignon again), we've been working on an application framework (eXpress Application Framework), which is currently in beta. What better way to test and prove it and to show that it is getting ready for release than using it for the new Client Center?

    So tweaking the visuals a little bit and a lot of dogfooding. The latter, especially, means that you can have confidence in our controls and frameworks because we do too. Now, if you'll excuse me, the grill is ready for the filet...

LIVE CHAT

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners