This is the story of two little olives.
Hello, my friend, what have you been doing?
Let me tell you about my deadly battle with a fierce toothpick.
Don't you say! How impressive, what valour!
The toothpick was about this thick.
Tell me no more, I can't bear to hear it!
Now more than ever, we olives have to stand together.
No more toothpicks, only red peppers will pierce our hearts!
Script - Oralia
Puppets - Luciana
Photos - Federico
This is how a GtkBox lays out its children. Yellow is the spacing that you specify in gtk_hbox_new() or gtk_vbox_new(). Beige is padding, which I'll convince you to set to zero. Orange is the actual child widgets inside the box.
In the first example, you see a box with a spacing of 2 (trust me, that yellow is 2 units). The children are thus uniformly spaced, and everything is nice and easy to understand.
In the second example, you see a box with the same spacing of 2 units between children, but each child has a different padding. The leftmost child has a padding of 1 unit, which you see on both sides of that child. The second child has a padding of 2 units, the third child has a padding of 3 units, and the rightmost child has no padding. This is a big mess.
Spacing is the uniform space that GtkBox puts between child widgets.
Padding can be different for each child, and it gets applied on both sides of each child. So each child gets an allocation of at least (padding + requisition + padding).
Other containers like GtkTable also have their own padding parameters for children (GtkTable lets you set different paddings in the X and Y directions).
Summary: if you are using a padding different from zero, you are making a mistake in 99% of cases. Use a good spacing, and a padding of zero. Otherwise you make it really hard to align other widgets in the container hierarchy when someone else has to modify your code. If you really need padding, it's generally better to use a GtkAlignment around your widget and pad that instead of messing up the parent container.
This has been a public service announcement.
Henne Vogelsang pointed me to a great document on applying "A Pattern Language" to online communities.
Go and watch this scary/funny/excellent presentation of turning everything into an online game.
... And now go watch this presentation on why we should use online games to solve real-world problems.
That would be something very cool. Do a little guerrilla gardening? Get +10 points for gardening experience, +5 points for neighborhood-improver, +8 points for community-building if you garden with a neighbor.
Why are you reading, replying to, or posting in foundation-list? Why are you wasting your own time and eveyrone else's? Instead, go and make GNOME better. Fire up that text editor. If you don't "git push" today, your day was a waste of time.
One thing that Seth says is that sometimes designers come up with a design, and then programmers dissect every pixel of it asking for an explanation. Why did you put this here? Why is that a 3-pixel border instead of 4? This is extremely unnerving to designers, as when you are skilled at something, you don't consciously think about all the decisions you make while doing something. Their skill told them that that place is where the thing would look more balanced, or give you the most economy of mouse movement. Their skill told them that 3 pixels looked just right, while 4 pixels would look too fat. I mean, just look — can't you see the difference? (Programmer: no, I can't; that's why I asked you, and 4 is an easier number for me to deal with).
Programmers also tend to burden designers with many questions because it is them, the programmers, who will actually have to go through implementing everything that the designer said. Also, it is very hard to restrain yourself from posting your pet peeves when someone is doing a design — I know, I've done it myself.
For designers, having to justify every decision keeps them from doing good work (or from doing anything at all). Just see what happens with the OpenOffice.org usability train-werck — nobody wants to change the user interface because they would have to go through a bureaucratic process of justifying every single thing they did, write a spec, get it approved, etc.
However, Seth's tongue-in-cheek recommendation of "just trust designers" is not 100% wise. See what happens out there in the physical world when we trust starchitects like Daniel Libeskind and I. M. Pei. They will just jerk off on your city and they will spooge a monstrosity which no one dares to demolish because it was so expensive to build.
|Photo||What||Comments from a programmer|
|An apartment building.||Pretty, unpretentious, respects its surroundings.|
|An apartment building according to Daniel Libeskind.||Yeah, you can live in the pointy end of frozen shark fin's soup.|
|Islamic art.||It's fractal, colorful, and has 1400 years of tradition.|
|Museum where I. M. Pei wants to show Islamic art.||Luciana is getting pretty good at stacking blocks like that.|
Fortunately, human interface designers are not starchitects. They are very reasonable people, trying to build tools that are rewarding to use.
Programmers get annoyed at designers who don't show a hint of knowing how software is implemented. This is like builders who get annoyed at starchitects — yes, mister Gehry, your fucking roof leaks because you designed a surface with a local minimum and no drain. Water will pool in local minima. 2000-year-old fix which you didn't do just to be interesting: cascade of roofs.
A designer who is not involved in the implementation cannot be a good designer, and I will explain why. Designers should not deliver gold-framed drawings drawn with the finest inks on parchment, expecting that the lowlife builders will follow the designs to the letter. Designers need to be involved with the construction. That will teach them what is necessary and what is superfluous, and it will make them better designers. Seth mentions that he and Marco worked very well together when Marco questioned him, because there was an interaction between designer and builder.
You may not be the best programmer or the best designer, but if you work to acquire programming and design skills that are above average, then you have already won.
Design of something as complex as software is best done iteratively. You use the scientific method: design a bit, code a bit, test the outcome. How do you avoid testing mostly screw-ups until you hit the right design? You follow a few rules.
Which rules? Allow me to introduce you to the monumental work of Christopher Alexander.
Introduction: A Pattern Language, or architecture for humans
In the 1970s, Christopher Alexander and other architects at Berkeley went to various places around the world, trying to see if there were reasons for why some places and buildings are comfortable, livable, and nice, and some are not. They distilled their findings into a list of good architectural patterns, and published three books — the first two being The Timeless Way of Building and A Pattern Language.
A Pattern Language is remarkable for several reasons. First, it is immensely practical. If you are building something, you can grab the book and instantly get hundreds of ideas for your project. Second, it is not about a particular style or about superfluous decoration. The book doesn't tell you, "make this shape of flourishes in the handrails"; instead it tells you, "a house should have its rooms placed such that sunlight enters them according to the right time of the day - East for the bedrooms in the morning, West for the living room in the afternoon". Third, you can see a whole philosophy of good living emerge from the book. It advocates a process that allows you to construct an environment that respects your needs as an individual, as a social human being, and as a living being that should not damage its environment.
For us programmers, this book is also interesting because it was the inspiration for Gamma et al's Design Patterns, and a whole slew of pattern-minded thinking that we are used to.
Let's look at five little examples of patterns from the book.
Positive outdoor space. You can feel it in the small, cozy public squares in medieval towns. You can most definitely not feel it in the huge parking lagoons in shopping malls along the highway. Positive space is more or less convex, it is partially enclosed, and it has a definite shape. It is not just leftover space. Here, negative and positive space between buildings (note how old versions of the GIMP were a pain in the ass to use because the program's windows looked like the version on the left):
Light on two sides of every room. This diffuses the light, thus making a more comfortable environment. There is no glare from the window. There is no time of the day when you don't get good sunlight. Here, light on two sides, and light on only one side:
Intimacy gradient. The entrance to your home is semi-public space. The living room is communal space. Your bedroom is private. If you must cross the bedroom to reach the bathroom from the living room, then having visitors will be uncomfortable. So, you design your home so that the connections between rooms form a sequence from public to private.
Structure follows social spaces. Communal areas need to be ample and have high ceilings, and they need to be "in the center of things". Intimate areas like reading alcoves and your study desk need low ceilings and separation from the rest (through doors or half-height walls) to make them private.
Open shelves. Deep cupboards make you put things behind other things, so you can't see them nor reach them. They also have a big footprint. Cupboards that are one-item-deep automatically stay tidy, and you always know where everything is. Things that you use frequently should not be behind doors.
So you can see the essence of design patterns: good, tested recipes that don't constrain your implementation in unnecessary ways.
But where did the patterns come from?
Although the list of patterns is tremendously useful, and universally applicable to urbanism and construction, Alexander was not satisfied. Where did the patterns come from? Can we make new patterns from scratch, or must be we content with what traditional architecture has produced so far? Are patterns necessary at all?
Alexander spent the next twenty years researching these questions. He arrived at the following conclusions:
Nature creates things that all have about 15 properties in common (I'll show you later). This happens solely through natural processes, although it is not quite clear why very different processes produce similar results.
Traditional architectures, or towns which just evolved over time, also have those properties. You can derive all the patterns in A Pattern Language from those properties.
Each property can also describe a transformation to the existing space.
The only way to achieve good design is by using those transformations, one at a time.
This was published in 2003-2004 in four volumes titled The Nature of Order.
The fifteen properties
The first book in The Nature of Order deals with fifteen properties that appear in all natural systems.
You should really look at photos and drawings of the fifteen properties to understand them. I'll just summarize them super-briefly here.
|Levels of scale. There is a balanced range of sizes. You don't have abrupt changes in the sizes of adjacent things.||Strong centers. You can clearly identify parts of the space or structure.||Thick boundaries. Lines delimit things. In living systems, edges are the most productive environments (e.g. all the critters that live at the edge of the water).|
|Alternating repetition. High/low, thick/thin, shape A and shape B. Things oscillate.||Positive space. Space is beautifully shaped, convex, enclosed. It is not leftover space.||Good shape. The sails of a ship, the shell of a snail, the beak of a bird. They attain the optimal shape, which is beautiful.|
|Local symmetries. The world is not symmetrical at large. But small things tend to be symmetrical, because it is easier that way. Your house is not symmetrical, but each window is.||Deep interlock and ambiguity. The crooked streets of old towns. Axons in neurons. Two strong centers are made stronger if a third center is placed between them, so that it belongs to both.||Contrast. You can distinguish where one thing ends and the next one begins, because they don't fade into each other.|
|Gradients. Things fade into each other where they need to. Concentrations in solutions, snow or earth banks, the wires that support a bridge.||Roughness. The world is not frictionless and smooth. Irregularities are good.||Echoes. Things repeat and echo each other. Things are unique in their exact shape, but those shapes repeat over and over.|
|The void. Sometimes you get a big blank area for quietness of form. A lake, a courtyard, a picture window.||Simplicity and inner calm. Things are as simple as possible, but no simpler.||Non-separateness. Everything depends on everything else. You can't separate a fish from the pond and the aquatic plants. You can't separate a column from the base of the building.|
The second book in The Nature of Order describes how each of those properties also defines a transformation. For example:
Thick boundaries. You can sometimes transform something beneficially by adding a boundary to it. You plant a hedge around a garden, which then serves as beauty, as a wind-break, and as a productive system on its own. Scrollable boxes without a GTK_SHADOW_IN frame are hard to distinguish from the window's background. You put a cornice at the top of a building, so you don't get an abrupt transition between the building and the sky.
Local symmetries. Small parts of built things are easier to build symmetrically — because they are turned on a lathe, because they need access from both sides, because they fold like a book. Making things asymmetrical "just to be interesting" takes extra work and it is harder to make them work well.
Positive space. Feeling too exposed when in your desk? Add a waist-high bookshelf beside you to delimit your space, but not to completely close you off.
Each of these is a structure-preserving transformation. You make a change in the existing structure not by tearing it down and remaking it, but by tweaking one thing at a time according to those properties and transformations.
The fundamental process
Over a long argument, Alexander explains why following this process of applying structure-preserving transformations is the only way to achieve a good, functional design. This is not just for buildings, but for everything we construct. We mimic nature, but we do it faster.
So, how do you do one step in your design/implementation process?
1. Start with what you have — an empty lot, or an already-built building, or a program that looks ugly and is hard to use.
2. Identify the centers that exist in that space. Find the weakest center or the least coherent.
3. See how to apply one or more of the fifteen structure-preserving transformations to strengthen that weak center. Does it need to be delimited? Does it need to be blended with its surroundings? Does it need more detail? Does it need to be de-cluttered?
4. Find the new centers that are born when you apply the transformation to the old center. Does the new combination make things stronger? Prettier? More functional?
5. Ensure that you did the simplest possible thing.
6. Go back to the beginning for the next step.
A super-short summary could be, "find the bad parts; make them better in the simplest way possible; repeat until it is all good".
What the hell does this have to do with software design?
Let me give you some examples.
Refactoring is just applying structure-preserving transformations. You don't change what the program does; you just change how it is built internally, piece by piece.
You do not rewrite software; you fix the software that exists. Otherwise you lose all that knowledge, even if it looks ugly in its curent state.
You don't design the whole user interface for a big program in a single step. You go from big to small or small to big (levels of scale); you test each part individually until it is good (strong centers); you make sure the parts are not too disconnected from each other (non-separateness). You move a few widgets where they are easier to reach, or where they are closer to the data to which they refer. You remove some frames and separators to reduce clutter.
Free software and cities
We software developers are building cities. I include code hackers, designers, translators, documenters, etc. in the term "developers" — building cities of software programs interconnected with each other through IPC. Each program is a building, large or small, simple or complex, each with a different purpose and layout.
Designing a whole system (kernel, libraries, tools, shell, programs) would be like trying to design a whole city. A good city cannot be designed; it has to emerge from the interactions between its inhabitants, over many years. Good cities are emergent, not designed. Ecosystems emerge from the interactions of living and non-living beings; they are not designed and they always evolve.
Remember that no one can work on all of free software. You cannot design a whole system by yourself, and you cannot make everyone agree on everything for a perfectly consistent design. But if you follow the structure-preserving transformations and the fundamental process, you can build your part of a big system and it will automatically be harmonious with everything else — and you will have fixed the bad parts first, making the overall goodness much better.
So, go forth and design and build and iterate.
GTK+ tip o'the day.
Do you have a GtkTable and some row/column is expanding when you don't want it to, and yet all of those row/column's children have EXPAND|FILL turned off? Put a GtkAlignment in the empty slots in that row/column, also with EXPAND|FILL turned off. It seems that GtkTable will let a row/column expand if some of the row/column's slots are empty, regardless of what the other children want.
This is the old gnome-display-properties:
And this is an improved version:
This is in the display-capplet-ui-cleanup branch.
With these changes, it should be more obvious which options belong to the currently-selected monitor. The dialog now fits in 640x480 pixels, which is nice for netbooks. The mouse cursor changes to a hand when you move it over the draggable monitors, so the ugly label with instructions is not needed anymore.
Luciana was munching on sausage slices. She grabbed the curved end of one sausage, looked carefully at it, and exclaimed, "look, a little vault!".
I guess that's what she learns in this house.
New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.
Keep up with the latest Advogato features by reading the Advogato status blog.
If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!