Ask HN: I'm an experienced backend developer, but clueless about GUI app dev.
I'm a rather competent developer, but my areas of competency are perhaps quite narrow. I have been making software for over 10 years. I've made servers, device drivers, command-line utilities, big and small. I have never done any form of GUI development, and frankly, I don't even know where to begin. Whether it be native applications or Web 2.0 apps, I'm completely lost. The closest thing to a GUI that I have worked on was viewed in Netscape 1.0.
I can (and have) read API documentation, which is usually sufficient, but when it comes to GUI app development and design, I can't see the forest for the trees.
Are there any recommended books that cover a language or toolkit specifically for GUI development, but which also teach the process of good design from scratch?
5 comments
[ 42.6 ms ] story [ 70.1 ms ] threadAbout Face
The Design of Everyday Things
Don't Make Me Think
As well I think you may be looking at what you are trying to achieve in the wrong way. Human Factors exist above the technology and is more of philosophical discipline. The limits of the technology constrain design and you learn to work within the constraint of the particular technology. With that said optimal workflow is achieved by taking common design principals and adapting them to the technical medium. That being said, regardless of the technology you use, you should read at least one of the above 3 books. IT will help you understand what you are trying to achieve on behalf of the user. Once you understand that, it is easy to adapt the principles to the medium of your choosing.
As for what you should implement your fist UI in, that relies on a assortment of factors. If you are not familiar with web technologies, just understanding the technology soup that is HTML/CSS/JavaScript/Backend can divert focus from learning good usability practices, but if web is your end goal then it makes sense to go ahead and invest the effort. If it is not, then IOS and Objective-C is a good candidate, it really helps you work within constraints and makes you really contemplate the design. Finally if you are only learning for learning sake, then I would say Flash or Air should be considered, not because they are great technologies, but because you can hit the ground running immediately and if learning usability for the sake of learning it is your goal, they will get you to the end of that goal in the fastest manner possible.
1) Write a game.
It may sound cheesy, but it gives you a frame of reference to work from. Most people have played enough games to know when the interaction feels right or wrong. If, like me, you decide to write a game in the browser, it will also teach you many, many things about working with the DOM, optimizing for performance, managing memory, etc... Plus, it looks freaking fantastic on the resume. I recommend a 2D side scroller (I did Mario in JS) or top down (zelda would be cool). Be careful of anything with large numbers of moving things on the stage at once (contra, for example). Optimization can kill you with those.
2) Write in a framework.
For instance, if you write a iPhone app, the obj-c based framework tends to guide you towards a usable, responsive app. Same thing with Rails and QT. You can also find scaffolding for all of the above that will lay down the groundwork for you to expand on.
Most of them work on a callback manner, similar to how you'd deal with device drivers, e.g. someone pressed a button and you'd respond with showing/hiding another panel. However, if you wrote code like that, it'd be completely spaghetti. So you are asking a very valid question here.
The second issue is most GUI tookits will only allow you to interact with the toolkits on the UI thread. Each language/tookit have their own style of queuing up some functions to be run on the UI thread. You need to figure out what is the canonical way of dealing with this up front.
The third issue is most callbacks occur on the event thread. This means that you cannot run long processes as the UI literally freezes until you hand control back to the main event loop.
Testing is another source of pain. Most GUI toolkits were not built with testing foremost in mind. However, it is not necessarily easy to shim/mock the GUI components because they can hold quite a bit of state.
Now that we got that out of the way, I'd like to say that if you have developed headless utilities, then you are actually in a better situation than people who started programming by learning GUI.
You could start off by deconstructing existing applications.
First off, enumerate all the states a UI could be in e.g: New, Dirty, Validating, Saving, Saved. Note how these states are shown on the UI. There might be labels for error messages that are normally hidden, and made visible when validation errors occurs, etc. I like to have it all centralized in one subroutine, so that when the state changes, the routine makes sure all the UI elements are in the right state. These states also govern whether you need to prompt users to "Discard, Save or Cancel" when they close the application.
Secondly, if this is your first project, stay away from data binding. I usually have a model which essentially duplicates all the UI information, and have a pair of routines pushToUi(), pullFromUi() to marshal back/forth the visual state. While this is somewhat repetitive, it allows you to make minor changes your UI - (e.g. DatePicker instead of a TextBox, move a field to a panel that is usually hidden) and your program will still work.
Thirdly, a GUI app usually has three cooperating components - Model (your data), View (the toolkit) and Controller (the glue). Limit the interaction and your application will be more easily testable. For instance, you could have the Model pushing data to the View, the View pushing events to the controller, and the controller changing state on the Model. There are probably 6 ways you can combine the interaction, but try to avoid two-way interaction between all three components - it will be difficult to figure out.
Fourthly, asynchrony is a fact of life. Don't perform database calls (and definitely not a call to a web service) on the main UI thread. Put the job on a queue, and let the background thread do it. Microsoft .NET have a BackgroundWorker and thread pools to tackle this. You can use some of their ideas if your platform doesn't have this. An application that is full of callbacks can be difficult to grok. This brings me round to my original point that if you've written device drivers before, you already know this, and probably have some techniques to tackle it in a sane manner. If you don't - judicious use of coroutines via Duff's device, or the yield statement can do wonders for your code in terms of readability.
Fifth, be aware that event handlers attached to objects will prevent those objects from being garbage collected, even though they are no longer visible. Make sure you unwire the handlers before you lose your final reference.
As far as designing the UI goes, just bear in mind most people using the app couldn't care less about the app. All they want is to use it to get their work done and go home. So your task is to figure out which is the most common thing they want to do and unclutter the UI so they can figure out how to do it quickly. This is where your program design comes int...
My first GUI experience was to maintain a massive Java Swing app (back when v < 1.2), which left me with some type of mental trauma. I've been trying to recover by re-starting from where I feel comfort (ie terminal):
https://pixbyfunc.appspot.com/pub/term/v1.html
I know it's pretty stupid but it actually helped me hunt down another personal 'white whale', which is asking contingent questions via browser:
https://pixbyfunc.appspot.com/pub/term/ask.html
I am not sure if I can ever become a good UI guy at this rate but wanted to say you are not alone.
End of my 0.0219 (CAD).