Complex GUI Architecture Discussion?
XNuke asks: "I have been searching for intelligent discussion (on dead trees or otherwise) of the issues involved in designing very complex GUIs. Things on the level of TecPlot, AutoCad, 3DS, etc, where there may be very many different views of the same data and there are many degrees of freedom for the user. I am not interested in 'where to put the buttons', but rather the nuts and bolts of making the 'Well Designed UI' work. I guess I am looking for a sort of 'Design Patterns applied to a big deskptop application' sort of discussion. It is no problem to find discussions of Model-View-Controller concepts at the component level, but at the application level there seems to be nothing. Too often the architectural level discussions encompass non-interactive, server side design issues and not the extremely chaotic problems a client side application with many degrees of freedom has. Short of wading through megabytes of source code for KWord et. al., does anyone know of any digested information? There is obviously no 'One Solution' to this, but there must be something out there."
Find a good model and see where your needs diverge. When we started on a project like this, the UI was a mess until we based the initial design on an existing piece of software where the user interactions were similar in nature (e.g. office productivity app, multiple views of data = MS Outlook). So if your app has similarities to AutoCad, Photoshop, or any other commercially successful UI, use it as a starting reference model for your UI, and see where the needs of your users diverge from the UI model that app presents. To do this you need to generate typical usage cases, and rank them in terms of how often they will be performed, and make sure those operations are obvious and easy to perform. The other advantage to this approach is users will appreciate that it works just like "software app X" and won't need much additional training.
... especially if it is a very complex application that exists to do a single logically coherent - but complex - task. Instead of trying to fit into a WIMP/Menu/Command line paradigm, think of yourself building a control panel for the action. Look at information on industrial designs. But for God's sakes don't look at GUI guidelines for the platform you're building it for. The main argument for this is that you then have to train the user in your GUI. But, if the task is complex enough to need a complex interface, it's complex enough to require training to use. Finally, link the panel to conceptual actions, events, or information in the conceptual task space.
That is all.
I don't think he's asking this either though. He seems to be asking how to properly stucture your internal data and the appropriate design patterns to use to cleanly access this to make it easy to fit to a complex GUI, a GUI where the same data is viewed from several different perspectives and needs to 'look' and 'act' different depending on how it's being viewed.
He listed autocad (and others) only as examples of complex GUIs with no judgement on whether it's good or bad. And he's not looking for good GUIs or bad GUIs or how to make either. He's looking for how to go about connecting the GUI to the underlying data.
or that's how it reads in braille.
Actually, Google's interface is one of the best examples of design and functionality going.Check out their cleanly laid out News area.Beats CNN, etc.
That's got to have had something to do with its' universal appeal
C:> ?? Been a while eh... C:\> (ala prompt $p$g)
(B) + (D) + (B) + (D) = (K) + (&)
I really like the book "The Humane Interface" from Jef RAskin.
I found it on amazon where one reader stated that "Once you read this book you will know why you have the programs you hate." He is right... I absolutly loath vi now (not that emacs is that much better of going after Raskin;-).
Regards, Tobias
Emacs
"Academicians are more likely to share each other's toothbrush than each other's nomenclature."
Cohen
Welcome to assholeforum.slashdot.com
The guy's already said he's looked everywhere for something similar, now he's come to the 'enlightened' forums of slashdot where the most helpful post some people can muster is RTFM. Since it isn't clear that there even IS a FM, maybe you can cut someone a little slack, offer a helpful suggestion or shut the fsck up.
Technological eletism helps no one. If you think what he's looking for can be found on Google... find it and prove us all wrong. If it isn't exactly what he's looking for, you can go crawl back under your hole where we will all leave you to peacefully revel in your astounding ability to program in assembly, while your festering glee grows with your ever-expanding intellect.
Currently I am on a project where a 'web' form takes 20 days to build but the store procedures that manage the data take 2 or 3 days.
This is typical of UI issues in general, and I wish to heck more non-technical managers would realize this. The amount of coding and hard thinking that goes into making an interface reliable, idiot-proof, and easy to use can be truly astounding, and is often the largest part of implementing an interactive application. A ratio of 85% UI code to 15% non-UI code isn't at all unusual. Nor should this be surprising: interfacing with a database using a set of well-defined logical rules is almost easy compared to interfacing with the unreliable sack of semi-random chemical reactions sitting at the keyboard. Even when they're not clueless and stupid, people are among the most complex real-world phenomena any programmer will ever deal with.
Proud member of the Weirdo-American community.
I think part of the reason such discussions seem to be lacking out there is that each GUI toolkit has its own way of conceiving of event-based GUI interaction, and separating the presentation of a GUI element from the logic that handles it. Thus there is no real standard set of design patterns for GUI implementation (there are tons of sites I found using Google on GUI "Design Patterns" which are basically just HCI best practices for communicating certain kinds of concepts). For example, Qt uses the signal-slot mechanism. wxWindows uses EVT_ macros to associate an event with an action method. These encourage different ways of structuring GUI code.
I am not saying it's impossible to come up with a set of rules of thumb for general GUI development and implementation in the same way that general design patterns for OO development exist to solve certain kinds of problems that are commonly encountered, but I'm doubtful they would be as useful as you would think.
You mention MVC. This is a very useful abstraction, but you're right in saying that it doesn't address the larger question of application architecture. One kind of global abstraction that seems to help for large interfaces is some kind of messaging system. For example, you can use a global queue of update events (sent by Models when things change) which all interested Views can lsiten to, and react accordingly.
Some real problems come when you want views to react to changes so some other view (but NOT the underlying model data). e.g. changing from 2d to 3d display, you might want various menus to appear, disappear, or have entires change/gray-out. This breaks down the MVC abstraction to varying degrees.
At the end of it all, I also haven't seen much in the literature on architectures for large GUI apps. I think this is because very few of them are really ever produced. Most apps you see are, at the base of it all, fairly simple, and require only one or two views with pretty straightforward control architecture.
Read his F'ing post man: "I am not interested in 'where to put the buttons', but rather the nuts and bolts..." [Do you moderators even read the posts carefully?]
He doesn't want fluffy designer stuff. He wants to implement a complex U/I with multiple views on the same data. Designing the interface is trivial. Implementing it is the problem. His question has no obvious answer other than: "just jump in; you'll get it right on the 2nd or 3rd try like the rest of us."
BTW, MVC is crap. It falls down for much smaller problems than what you're looking at.
I am a designer for a CAD/CAM program that is used to control and make parts for metal cutting machines. The first thing you will need to realize that these types of application are considered vertical market applications.
Everyone has a use for a word processor but not everyone has a use for one this programs but when you do you need it bad. When you design the architecture and the UI you need to keep flexibility in mind. This is not so much for the user but for you so you can met the needs of a SPECIFIC customer. It is my experience that customers really want the vertical market software they buy to aid their current way of doing things, not to change what they are doing to meet the needs of the software.
A specific industry has a lot of common needs but there is enough variation that if you don't design flexibility in mind it will drive you crazy with tech support and lose buyers who can't get the software to do what they exactly want.
There two things you need to consider for such programs. The architecture and the UI.
I following many of the standard advice on designing UIs but here are a couple that I try to keep in my mind.
1) Keep the focus of the screen in the center of the screen. Try to add widgets to the top AND bottom to keep the screen's focus in the center. For example there was a version of my software where the sheet of metal was bumped down so that it's center was a lot further down then the center of the screen. This is bad. The next version I redesigned that screen so that the widgets were equally distributed between the top and bottom. This way the user's eyes when they move to the monitor has the sheet exactly where it is needed.
2) Work-flow, you should provide either a means via keyboard or mouse to accomplish common tasks. You can do one, the other, or both. However what you shouldn't do is mix the two. If the task has keyboard components you should try to enable the user to complete the task without moving from the keyboard. The same for tasks involve the mouse. Tasks that involve a lot of moving from mouse to keyboard leave user unhappy.
Try to have a keyboard way and mouse way to do all tasks. Sometimes it isn't possible but if it is do it.
3)Softkeys, toolbars are nice it is my experience that users respond better to text then icons. User like big fat buttons on the screen. What I come up with the idea of softkeys. If you look across the top of your keyboard it probably has 12 function key arranged in groups of 4. What I do is have eight buttons on the top or bottom of my screen split into two groups of four. The first four correspond to F1 to F4 and the second four to F5 to F8. I use F9 to F12 for special actions. F9 is generally used for "flipping" the softkeys. This give me room for 16 commands per softkey group.
On the more complicated screen I have multiple groups of softkeys. For example Zoom, Cut, Edit Path, Sketch, Rotate, etc. Each having up to 16 commands. I also provide a way to switch between the groups.
The advantage of this that the user can see exactly what they can do in front of them. They can use the mouse to click on the command or use the corresponding function keys. While I do use some toolbar buttons most of commands are accessed through the softkeys.
4) Make important tasks very easily accessible. Use single letter or buttons to tie into the task. For example Edit Cutting Parameter is a command often used in my software. So I tie it into not only a softkey but a toolbar button accessible no matter what softkey group you are in.
Architecture.
First get Design Patterns and Refactoring Software, regardless of what langauge you use they will be very useful.
The goal of Architecture is to have flexibility to meet customer needs without introducing a lot of bugs into your software because you changed something. I am not sure what to call what I use but it builds heavily on Design Patterns.
Data Structures
Application Structure
UI Interface
Commands/Installable Libraries
UI Implementation
Graphic Framework
Data Structures (Sheets, parts, etc)
Application Structure (I use an idiom of Jobs comprised of sheets with parts, with a separate Shop Standard that is refered too by all Jobs, and a list of installable libraries ).
UI Interface (nothing but Interfaces)
Commands (these use the command pattern to implement )
Installable Libraries (like reports, part creation, file types, etc)
UI Implementation (implements the UI interfaces with methods accessing commands and libraries).
Graphic Framework (Delphi, Qt, KDE, Gnome, VB Forms, etc).
The reason for UI Interface -> Commands -> UI Implementation is so that commands that just manipulate the UI (switch screens) can be written. The actual implementaion is last because the implementation needs to know what commands are available to assign to various screens and widgets.
I hope this helps
How do I best seperate the UI code from the code that actually talks to the database.
Actually, in this question lies the answer. On a sheet of paper, draw a line separating the paper into two halves. In one half write "UI Module" and in the other half write "Database Interface Module".
These two modules can be written, so that the UI module uses only the public interfaces of the database module. This is the high level design of the application.
Designing each module well is an entirely different challenge, since the quality of the database module's interfaces determine how resilient the application is to changing requirements.
I guess the lesson here is that the really high-level design is trivial, but the design of each module is very hard and should be done by someone experienced in such things. Reading good books on the subject is only the beginning.
Healthcare article at Kuro5hin
On a sheet of paper, draw a line separating the paper into two halves. In one half write "UI Module" and in the other half write "Database Interface Module".
Actually, this is considered bad form in an OO design. The UI "Module" (classes) should only talk to the Model classes, while the Model classes may or may not talk directly to database classes. They may be mapped to database tabels thru an indirection layer.
There is some great discussion of this at Martin Fowlers website.
If you would read the actual Apple HIG, they say that apps which are meant to replace a real-world item/function (such as Calculator, iCal, iTunes) should be built with the brushed metal look.
They break this numerous places: in fact, virtually everywhere.
By the definition above, *everything* should be brushed metal. Word processor replaces pencil/typewriter. Spreadsheet replaces graph paper. Sherlock replaces phonebook/dictionary. Photoshop replaces sissors/paste/darkroom.
If you try and tighten it down to obvious objects like iTunes replacing a radio, then why is iChat brushed metal? Why is iMovie brushed metal and Final Cut Pro Aqua? They do exactly the same thing!
This is one area where Apple is just out to lunch. The HI folks had nothing to do with brushed metal: it's clearly a Steve "That's cool: go with it" decision.
"Seven Deadly Sins? I thought it was a to-do list!"
about complex GUI's is: don't! :) I still like pov-ray because I can just enter what I want in a text editor rather than a modeler like 3D-S. Several smaller GUI's built for specific purposes would probably be better than one big GUI. Just break the GUI down into easy ways to do specific tasks. Try to have a consistancy among them. Really, this would be a great place to put object-oriented methods to use. Make consistant components that are groups of other UI elements. It's easy to do in Java using interfaces, but you can do it in C++ as well with inheritence and virtual functions, or call-back functions in C(ech!). I'm sure .Net has a sane way to do it(err, no I'm not really... they probably want you to drag components to a form and use cut and paste, but then you have to update every component to fix a bug, add font settings, etc.), but I really don't know. Any GUI architecture worth it's size in bits has some kind of control grouping whether it's OO, or just faking OO.
Karma Clown
You say you "absolutly loath vi" after having read this book. Did you like it before? Because I find vi to be an excellent editor; it lets me keep my fingers on the keyboard where they belong and gets a lot of work done with relatively few keystrokes. And if you also liked it before reading the book, I would think it's sad to change your opinion just because a book told you so.
"Hardly used" will not fetch you a better price for your brain.
Bjarne Stroustrup says, (not in exact words) separation is easy, but the hard part is communication. This so true if you ever worked on a non-trivial sized project. It's very easy to think up a neat(seemingly) structure and draw some pretty diagrams. But only when you actually goes to implement them that all sorts of flaws begin to appear. This is where experience and maybe talent comes in. Everybody knows loosely coupled code is good. But how to design the architecture so that communication is not thwarted is the real challenge.
If you would read the actual Apple HIG, they say that apps which are meant to replace a real-world item/function (such as Calculator, iCal, iTunes) should be built with the brushed metal look. All other apps should use the default, untextured look. Just thinking over the apps included in OS X, it seems to me like they follow this guideline fairly closely.
Except that they only added that to the HIG after 10.2 was released. Not to mention that some of their choices are questionable in terms of both using and not using the brushed metal look. Let's not even go into the fact that QuickTime on Windows breaks almost every design guideline for Windows (and most people didn't even realize there were guidelines for Windows, it's a much smaller document than Apple's anyway).
-PainKilleR-[CE]
It's a shame the post with the correct one word answer got categorized as "funny".
Emacs is the right programming architecture for GUIs. The Emacs command set and visual appearence are, obviously, not that great for many users -- but the programming architecture is right.
By being interactively extensible, emacs makes it easy to fine tune an interface while you play with it.
By being lisp based and by having many fine abstractions, emacs let's you do a lot with very little code.
The emacs architecture provides some very fine bits and pieces for achieving excellent accessability features.
By being interactive and self-documenting, Emacs is good at helping people teach themselves to program.
View-tree toolkits, such as underlie Gnome and KDE are inflexible dogs that leaded to bloated yet feature-anemic tools. You know what they're good for? They're good if you have a command-and-control army of drone programmers who can write reams and reams of code. That's why Microsoft apps will remain far more featureful than their free competition until that competition switches to an architecture that works for a society of free individuals.
Yes, it's true: the way you structure your programs has political implications. It defines jobs. It defines the power of managers and project managers. It establishes the degrees of freedom your users have to extend or customize their tools.
I haven't found design patterns to work as well as rule-based coding.
A philosophy I build into all of my GUI applications is "show the user as much useful information as possible". Users make thousands of decisions a day and informed decisions are easier to make. To that end, I eliminate useless information as much as possible to make room for the good stuff.
There are simple facts that need to be remembered while designing a UI:
- eyes move more easily than fingers
- buttons don't provide useful information (but can!)
- scrolling is useless and should be avoided
- minimize clicks, mouse moves and keystrokes
- informed decisions are better decisions
- context-based mouse clicks make sense
- keyboard shortcuts save time
- don't invent new keystrokes for old functions
- everything should work as expected
- file managers should show more files, db apps should show more data
- people can't choose from more than 7 items unless they are grouped
BTW There's no such thing as information overload. There's only useless information. If everything you show on a GUI is well organized it's all useful.
I think the MVC concept is mostly interpreted as a simple design pattern. But it is a much older (measured in IT eons) concept than a design pattern.
MVC is about separating data and behavior (Model) representations (Views) and user input (Controllers).
It can be applied to command prompt operated programs, batch processed tasks, web apps and GUI's. IMO, the narrow interpretation stems from the use of Observer-Observable-Event implementations of GUI widget libraries (Smalltalk, Java Swing/AWT, MFC, VB,...)
But MVC can be applied as an architectural pattern to. Implement and identify objects that are conceptual, logical parts of the application. That embody state and behavior. They have to make up the top level 'model'. Every view that is implemented must use the same basic Model, and register different listeners/observers to it or to parts of it.
The most complicated part is to figure out what kind of event messages to send from the Model (and it's parts) to the registered View(s) and their parts. (the idea of a queue I read in one of the responses seems very good, must try it sometimes)
Controllers can be unique for each user input source (keyboard, mouse, joystick, drawing tablet...) but when using GUI libraries, a dedicated Controller for each View is probably more natural to implement.
In this way it is possible to implement very different views on the same Model. Let's take a 3D drawing program. Objects as 'Car' 'WheelFL' 'WheelFR' etc. would be part of the Model. What kind of views can be implemented ?
- GUI for drawing 2D x-y
- GUI for drawing 2D x-z
- GUI for drawing 2D z-y
- GUI for drawing 3D x-y-z
- reporting view, web based
- reporting view pdf
Each 2D view can represent a wireframe/rendered image constructed from 'WheelFL' in the same application. The pdf tool can be a batch process that opens all drawings and iterates over all of it's objects and creates a pdf with names, coordinates, etc. User input (controller) can be nothing more than a command line argument, or a configuration file, in the last case.BTW, I have learned most of this the hard way, but I'm more than ever convinced of the necessity of MVC on different levels (app -> widgets) to make maintainable large (GUI) applications.
I'd actually been searching around for something like this too and havent' found it, so it's been a trial and error thing figuring out a pattern for my app.
/r
What i've found to work is to use MVC in spirit but split up my application into
+ Tasks
+ Models
+ Controlers
+ Actions
+ Views
That's supposed to be a tree. This design came out of planning, reviewing the app's purpose, and environment constraints. I am developing my app in java/swing and i took the strengths it had but combined them into higher-level structures to help me make the app more modular.
Basically,
Tasks are general tasks that the user will perform. For example, an administrator managing customers of a web store.
Views represent the actual UI: trees, tables, text areas, fields, etc. Views register with the Tasks for appropriate model change notifications. I can provide a variety of views for my tasks and data, and incorporate tasks into higher tasks with complex views.
Actions represent the actual actions that a user will perform in that task's domain. for example, in the Administer Customers task, the user can "Delete", "Add", "Search For", "Edit" customers.
An object for each of these tasks is created and given a string representation, an inconic representation, and it implements the ActionPerformed function. this is taken straight out of swing.
Actions are then registered into the views and ui elements.
for example, in my customer manager window i provide a menu, but also buttons across the bottom. So now one action can provide the title of the menu or button text, the icon for the button, and the state for both menu and button.
finally, when either the item or the button are selected my one action gets the notification.
The action then trickles the command up into the task where the logic for enabling/disabling ui elements resides.
The Task then notifies the model (my data) so that proper manipulation can take place. Finally the model notifies the task and the task notifies the uis and actions for appropriate state change (enable disable commands) and view updates (change data in tables, etc.)
it works pretty well, and i've managed to extend things without having to code complex application state notification or validation so close to the UI. it works nicely in java/swing because up until recently most UI coding had to be done programmatically (didn't use resources like a windows rc) so i can tie UI objects fairly easily to controls. but i'm still not happy with it. however, it was the best i could come up with in a pinch.
hope this helps.
My experience definitely agrees... I've found that constructing an interactive (not necessarily graphical) interface to non-interactive code takes 2-10 times longer than writing the non-interactive code itself.
I attribute this to the huge difference between batch processing and running an event loop. Programming languages are very well suited to "do this, then do that" style batch programs. But it is much more difficult to handle interactivity ("on click, do this, on keypress, do that") since you have to keep track of dependencies between internal data structures and the external interface.
e.g. say you have a rule that when MyApp::toolbar_visible == true then the toolbar must be shown. But most programming languages don't allow this kind of declarative specification. Instead, you have to track down every line of code that modifies MyApp::toolbar_visible, and tack on extra code to hide/show the toolbar depending on its new value... Or, if you have a slider control that is supposed to reflect the value of some variable. You again have to track down every point where that variable can be modified, and insert code to update the scrollbar.
MVC helps here, but it's still annyoing - instead of the simple "MyApp::toolbar_visible = true;" you end up writing something like "MyApp::toolbar_visible = true; MyApp::notify_toolbar_change();" Ideally you should only need the "= true" part, and the language runtime should figure out that the toolbar needs to be shown.
I've seen some attempts to use declarative specifications for interface elements, like NeXT's interface builder and TCL's "watched" variables. But none of these are really mainstream. (I don't have much Visual Basic experience - is that declarative?)
Then the second level of the design -- how do I reveal an overview of the complex issues behind the simple display? For example, assume that in an "executive dashboard" type GUI, you have a bar graph showing the status of some part of a mission critical project as "yellow", i.e. may be in trouble but isn't "red" yet. Assume that by clicking in the GUI, the executive can get an overview and that further clicks drill down to the details of why the project is at risk.
Similarly, maybe the project manager for the component sees a similar dashboard, but instead of the higher level view, it shows the parts of the project, including the critical yello piece. You can progressively use the same type of display for different job functions, and the meaning behind the yellow bar changes, but the GUI doesn't. To the data entry person logging parts into the warehouse, maybe yellow is how he looks for back orders, finds the missing component that the widget group needs, scans it in, and the effect up the chain is to "lower the amount of yellow" because it was the critical piece. The GUI code to make this happen is complex, but the design and analysis make the meanings simple to comprehend.
The best example I can think of is the heads up display in the later versions of the USAF and USN fighter aircraft -- the pilot's had way to much data to handle, so they simplified the "GUI" and projected to where it could be seen as part of the pilot doing the job without nearly as much effort. The same type of data could then be fed back to the commanders, etc. in displays so that without bothering the pilot "how much fuel do you have left?" they have a heads up that in essence tells them to get the "next set of patrol aircraft ready because Viper needs to come off-station in 20 minutes" -- because Viper two shows up yellow on the commander's head's up display. So The "++" is that if you do the design right, you can eliminate a whole lot of extra (e.g. opportunities for bad) coding and/or business decisions in the systems interfacing between between the executive level and the data entry clerk --or whatever the particular user sets might be.
...Open Source isn't the only answer -- but it's almost always a better value than the alternatives...
Why not use accessor methods instead of exposing the variable directly? Then you could call your notify method in the setter for toolbar_visible.
...
Some languages (such as C#, VB.NET, or Python) even provide built-in support for accessors -- this uses the same syntax as a regular field access, so it is transparent to the user.
For example, in C#, you could write this as part of MyApp:
private bool mToolbarVisible = false;
public bool ToolbarVisible
{
get { return mToolbarVisible; }
set {
mToolbarVisible = value;
NotifyToolbarChange ();
}
}
and then later:
MyApp app =
app.ToolbarVisible = true;
and it would call notify automatically.
You've brought a rare thing to "Ask /.":
A good question that can't be answered without advice, that doesn't score a bazillion howto-hits on Google and that isn't shure to be absolutely above the heads of the slashdot crowd.
Nice to have some good question asked. Thanks.
Now for my shots at closing in on answers:
I have no larger mentionable expierience in UI design apart for the fact that I do have some webdesign expierience and a professional artist training, but I have used and operated a wide range of professional tools in the professional manner in which they were meant to be used and operated!!!
And that's a very important part of my/the answer allready:
All extremly complex professional GUI-tools each have their very own distinct, standards-pushing look and feel acustomed to their application family more than, let's say, the CUAS. And that's what makes up a good tool.
People who use Avid use it almost exclusively and for hours and years on end - and often on special hardware too. Same goes for Softimage or Houdini. Or check out the difference between Freehand, Illustrator and Corel Draw. The distinct, special funtionality of vector-drawing apps is approached in a different way by each. That's the same reason why you've got a wider range of Video NLE apps that do all the same but with often different workflow aproaches.
See what I'm saying: If you're tool is gonna be complex due to very special funtions that only a few people will need or even know, there is no point in trying to find a standard for GUI design. You won't be able to apply it properly.
What to use? Photoshop layers or Photopaint objects? How to join vectorcurves: Corel connect and combine or Freehand extend and join? The latter is a very good example: 2 totally different but valid approaches to a very important problem. For those that need solid vector graphics power.
Bottom line:
Programms that are so complex that they are most likely to become stand alone tools (maybe even with custom hardware!) *can't* follow design standards - because there are none! Such a programm gains recognition by having a distinct character and one team of professionals in it's userfield that really know what they're doing and set up their own set of rules and preferences as to which way the app has to work, behave, look, feel and is intended to be operated.
And believe me, nothing sucks more than trying to make a complex powerapp like, let's say, a 3D modeler, instantly 'usable' for people who only know office gui standards. Check out kpovmodeler to see what I mean.
We suffer more in our imagination than in reality. - Seneca