ARTICLE

The Zen of GUI Programming

Posted by Mike Gold Articles | Design & Architecture March 13, 2008
This article describes some important rules to follow when creating an application that contains a presentation layer.
Reader Level:

 Edited by Nina Miller

BadGuiDesign.jpg

 

Figure 1 - Spaghetti Code in Action

Introduction 

On my last two projects I encountered a common design nightmare. The problem to which I am referring is a growing epidemic, familiar to all consultants who take on program applications previously developed by junior software developers. The problem is that the application logic is embedded inside of the GUI code. Code is designed in this faulty manner is the by-product of inexperienced software designers who believe they can simply skip the design phase of a project with no repercussions.. Bad code also results from using the RAD features in Visual Studio as a crutch to do everything conceivable in the GUI. The outcome?  A complete and utter mess of undecipherable code!   How often is this coding flaw seen in the industry? More times than you'd ever want to imagine. 

Why is Putting Application Logic in the GUI bad?  

Some junior programmers reading this article may be asking themselves this question. I certainly asked the question in my early days of programming. If I hear the question now, I cringe. Putting application logic in your GUI is a recipe for disaster for the following reasons: 

1) The code becomes unreadable. 

2) There is a tendency to compound cohesion when lumping application logic into GUI logic. 

3) Combinatorial problems pop up from the many inputs being tracked against the input into the application logic. 

4) The code becomes completely inflexible and almost impossible to maintain. 

5) The only way to change the face of the application will be to rewrite it. 

6) The application logic often contains expertise that you as a GUI programmer don't have, so the real expert (usually not you) has to go wading through your GUI code to tweak it.

7) It's hard to swap in  modular behavior. You could end up with a fat-fat client that is a resource hog and memory pig. 

Top Rules of a GUI Programmer 

You are on your way to becoming a very successful GUI programmer if you follow a few simple rules: 

1) Don't mix the application logic code in with the GUI code 

2) Don't mix the application logic code in with the GUI code 

3) Don't mix the application logic code in with the GUI code… 

 ... 

100) Don't mix the application logic code in with the GUI code 

Sound redundant? It is, but if this rule is drilled into your head and you follow it, you will be hailed as a hero by all your cohorts in the field. Another way to think of this is to ask yourself the following question: 

1) "Does every piece of code tailored to a specific function of expertise live in a different assembly or class?"  

What do I mean by this?  Next time you write an application and you are mucking around in the GUI, ask yourself the following question, "Before I go ahead and type this line of code, does the code require knowledge outside of the GUI?".  If the answer is yes, DON'T TYPE!!  Sit back and decide where the code should exist (outside of the GUI). Is there an assembly or class where that expertise belongs? Do I need to create an assembly or class to put that piece of expertise?   

Another question to ask yourself is: 

2) "Does the line of code I'm about to type inside the GUI have anything to do with presentation or input?" 

If the answer to the question is no, DON'T TYPE!!  It probably doesn't belong in the GUI. 

The only exception to putting non-presentation related code in the GUI is to call a nicely encapsulated API that handles the expertise outside the GUI. 

MVC 

A pattern called Model View Controller was created to help the application developer separate out the presentation layer (GUI) from everything else. The View (GUI) talks through the controller to the Model. The model contains the data and application logic.  Unfortunately, the way .NET is designed methods like event handlers which belong in a Controller end up in the View. This is another reason why inexperienced programmers regress into the habit of dumping application logic into the GUI. The environment is encouraging this behavior! Microsoft seems to have intended controller to be "taken care of" through .NET's internal plumbing. The way to tighten the controller concept is to create your own controller that lives in these event handlers and deals with communication from the view to the model through the controller's method calls. The model you are communicating with consist of a separate set of classes, interfaces, legacy dll, database, and/or hardware, that performs all the complex behavior(s) specific to the requirements of your application. The expertise of your application only lives inside the model and is isolated from the GUI (view). To understand more about how model-view-controller can interact with C#, check out Matt's article on MVC. 

Black Boxes 

When you start to design your model and are considering where all your expertise should live, make a clear distinction between the different types of expertise required by the system and create a list of categories to house them.  For example, I may have an application that requires logging, configuration management, reading a list of customers from a database, and running some scripts.  Each one of these functions requires completely different expertise  to implement, and they are all are mutually exclusive. Each function should be controlled by a different assembly or class (none of which live inside a Form class!). You can then define more specific functions that live inside each of these areas of expertise. For example, say you need to be able to log errors and log alerts. You may end up defining a method called LogError and LogAlert or Log(LogType x) or whatever fits your design needs. What you end up with is a black box defining that particular functionality,consisting of inputs and outputs. You don't care what lives inside.  Particularly, your GUI doesn't care what lives inside. In fact, your GUI should never have any knowledge of what lives inside. You may be laughing at this point, and saying, "Duh, I know that—hey, by the way, why not just use the WriteStream class in the middle of my Form to log stuff since it's already part of the .NET framework?". This is where the black box concept often falls apart in the hands of a beginning programmer. Inevitably, down the road the client will say, "Hey, can you print that log to the console, not a file please?"  At that point the novice GUI programmer finds himself going through every WriteStream and replacing it with Console.WriteLine. Multiply this sort of code changing a hundred-fold, and you end up with a pissed-off client.  This leads me to question number three: 

3) "Does the line of code I am about to type in my GUI have any low level framework calls?" 

If the answer to this question is yes, DON'T TYPE!!  All low level calls should be delegated into specific areas of expertise in the model and should never live inside the GUI (ever). 

Keeping it Simple 

How can someone tell at a quick glance whether a software design was applied to a C# Windows Form GUI or not? One way to tell is to open the main Form and look at the methods. If there are more than 20 lines of code in most of the methods there is a good chance that the GUI code contains application specific logic.  If the code is littered with loops within loops, if-else structures, and switch statements, I guarantee that the application logic is in the GUI. If the form is rigorously using the .NET library and low level classes, it probably contains application logic that doesn't belong there. Which brings me to my final question to ask yourself as a GUI programmer: 

4) "Does the lines of code I am about to type in my GUI require a lot of thinking?" 

If the answer to this question is yes, DON'T TYPE!!  You are probably ready to type in some horrendous structure that the next programmer will spend a good portion of his formative years debugging.  All the thinking should be in your well-designed model.  The GUI is stupid, mindless, and uncomplicated. Its only purpose in life is to accept input and present output. It should require very little thinking. The moment you find yourself thinking of some logic structure to put inside your GUI, please stop. It belongs in the model, period. 

Conclusion 

In my entire programming career, half of my responsibility was to clean up messy applications which had no boundaries between the presentation layer and the application logic. If you adhere to some of the rules in this article, a lot of bad code can be avoided. I know I am not alone here, so please feel free to tell your story in the comments at the bottom of the article. As more programmers become aware of the disasters that are easily created and difficult to fix, this knowledge will hopefully lead to better design and happier clients (and less work for me!), In the meantime, if you are new at this game, my best advice is: model your programming so that others will view your efforts with respect and admiration when working with C# and .NET.

Login to add your contents and source code to this article
post comment
     

 

Thanks Mike

Separation of concerns or responsibility seems easy enough to implement in WPF. The other thing that get talk about allot is testability. I can see times when there will be lots of UI only code, say to convert some business valve into a 3D gizmo in silverlight, the complexity of the UI code may surpass that of the business and communication code. Then We'll need to break out a UI controller for testing. I think I'm getting it, maybe.

Posted by Greenway Mar 21, 2008

If you have a class that is separate from the remote that handles communication and another class that controls the car, these classes encapsulate the functionality for each.  You can call these classes through the UI.  If however, you are putting assembly code in your UI (Remote Control), however, to send signals like  PORT 1 = HIGH, then your code will look like cr*p.  It is okay to put UI related stuff in your form that is related to the form itself.  If the UI stuff is related to hardware or remote control, then it does not belong in the form directly.

 

 

 

Posted by Mike Gold Mar 21, 2008

I'm starting out on my first real WPF project and I want to get it right. Can you tell me if I understand the first 100 rules? I'll use a radio controlled car as the vehicle for communicating my understanding. Let the remote control be equal to the UI, the car is the business logic and the radio waves the communication between them. The car only understands forward, backward, left, right and sends out a speed signal in feet per minute. In the UI's code behind I'll do the calculations to convert the movement of a pen input via ink and sent those four directional messages to the car code. The UI code behind, can also listen for the speed signal and calculate and convert the speed into MPH for instance. Why do I need any more separation? The radio controller / UI doesn't know or have anything to do with how the car turns or how it is propelled. All the calculations in the UI are only for the UI. I can see an improvement, make it possible for them communicate via the inevitable better carrier wave. Provide snap in modules for car and remote that can use any communication standard. This way I can drive the car with a beat up old (winforms) remote or use a shinny new silverlight remote and I can move from 'class to class' communication on one machine to 'web services' for the really long distance stuff. There is code in the UI, but this ain't your daddies UI. Did I get it or am I screwed up?

Posted by Greenway Mar 21, 2008

Unless you're a neat freek ;-)

Posted by Mahesh Chand Mar 14, 2008

Thanks for this great article. It surely "ll help in devolping a good software architectre

Posted by Asif Mar 14, 2008
COMMENT USING
PREMIUM SPONSORS
DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and add new content to existing PDF documents from within your applications.
Join a Chapter
SPONSORED BY
  • PDF reports have never been easier to create. With our included WYSIWYG Designer, you can layout your reports, set up your data source and let DynamicPDF ReportWriter do the rest.
Join a Chapter