Sunday, February 7, 2010

Day 23

A light weight and 'humble' user interface is the way to go. When making a UI for some application of website it is important to make sure you draw a line between your logic and your interface. Typically you don't want anything important happening in a text box or a button. You want the button to only know where it is, when its clicked, and how it looks.

Say your making a calculator application. This calculator has a screen, to display results, and a bunch of buttons for numbers and operations.

First lets look at what happens if you program this the bad way.
You start making the application by first making a main class to store which buttons have been pressed and all the needed info, and then by creating a bunch of buttons. You write a test to make sure there is a number '1' button, and then you make this button. Then you test that when pressed, this button will output a 1. You proceed to do make a new button for all the number 0-9, each button being specifically designed for its number. Every single one of these buttons have a set of tests that are virtually identical, checking to make sure this button is a certain size, making sure it is clickable, making sure it changes form when being clicked, making sure it tells your main class to record the button's info. All of these tests for every button, and then you add 1 different tests that makes sure then number 1 button outputs a 1, and a 2 outputs a 2, and so forth.

Already you have huge amounts of duplication and a rigid form, but it gets worse. Next you start making the operation buttons. You make an add button, once again repeating all the steps for a button but this time adding a few extra tests to make sure this button takes inputs from the main class. Then you make a multiply button (and here is where it gets bad), but you realize your gonna just have to do some addition several times, and you don't want to rewrite the addition code... So you tell your multiply button to 'press' the add button over and over to get multiplication. This is sick. Buttons should not be pressing other buttons! But you persevere. You proceed to make subtraction and division in the same manner with the button's 'clicked()' function doing all the math.

Finally you put all these buttons on a panel and have main display the inputs and outputs on some text panel and show your friends your cool new calculator. Then one of them asks "Hey this is really swell, but can you make a version for the terminal? I want to be able to type 1 + 1 = ? and get a result,". You of course, being the savvy and eager coder that you are, say "Most certainly! I already have all the logic, I just have to change the inputs!". So you go back to your program and start trying to figure out how you will change the inputs. As you scour for ways, you realize even if you changed the inputs all of your operations are inside the buttons! You can't just erase all your code and you know you shouldn't copy paste it somewhere else because then you loose all your tests. You can't bring your tests because they all test the operations by pretending to click the buttons. And you realize you are stuck...

Then you commit the sin of all sins, and make your terminal based calculator by getting the text inputs and then telling your terminal app to... press buttons...

Not only does tying logic to the UI force you to repeat a ton of code that can't be reused, it also makes for rigid tests that are dependent on your UI.

When you do it the correct way, you make a very light UI and keep all your logic behind closed doors. You start by making your main calculator class. Then you add in all of your operations, no buttons yet, making sure that they don't care who is using them, they just take numbers in and spit numbers out. Once you have all your operations done and tested, you design a single button. This button is simple, it just knows about buttony things like where it is and when its pressed.

Next you make a view class, which has a bunch of instances of these buttons, but all with different names like '1' and 'ADD', and yet all they do is get pressed and tell the view they were pressed. The view, or this humble dialog, will keep track of all the basic information. When a button is pressed, the view records it and saves the needed data. If an operation button is pressed, the view makes sure it has the needed data, and then sends it all to the main calculator class and tell it do perform the operation. The main class then sends the result right back to the view, which promptly displays it.

Using this sort of design, you can keep all of your business logic well isolated and tested, and you get to make any sort of UI you want. Say your friend sees your new calculator and asks you to make the terminal version now. This is easy as pie, all you have to do is make another humble view!

No comments:

Post a Comment