Wednesday, August 22, 2007

Going overseas

The next podcast will be a bit delayed - I am travelling to Europe to run some developer trainings, and I have not had the time to get my next podcast done. Stay tuned!

Tuesday, August 7, 2007

Lightning Brain Podcast: Click here to listen to "Writing code like a story"

Book mentioned in podcast:

Code Craft
The practice of writing excellent code
by Pete Goodliffe
ISBN 1-59327-119-0

Rough transcript of podcast:

Writing code like a story

Hi, my name is Kris Coppieters from Rorohiko. This is the third Lightning Brain podcase - writing code like a story.

I've been programming for over 30 years now - and my programming style has changed over time, to suit new languages, to suit new ideas, to suit programming styles.

If I look back at code I wrote, say, ten years ago, the changes are not all that great when compared to code I wrote earlier; I seem to have settled into a number of habits that work well, and have not felt much need to change.

Many of the things I do also seem to coincide with the advice given in many books about coding style - most of it is common sense.

I want to make it clear that some of my preferences are just that - preferences; sometimes, as a coder, you get 'locked in' to a certain approach. There are often many other approaches that are at least as valid, but there is no clear benefit to switch between them, so you stay 'locked' into a particular way of doing things.

When I was younger, I would let myself be enticed into endless debates - things like where to put the braces {} and whether to use tabs or spaces, that kind of stuff.

Through experience, I've learned that those things are highly irrelevant. I have found that consistency is more important rather than what your are consistent in.

So, if you like the braces one way or another, you won't get any argument from me. But you will get an argument if your braces are sprinkled one way here, another way there. To me that's a bit the same as having to read a book where the font size jumps up and down at random: it makes reading the stuff harder for no reason.

I often have to work on other people's code - and currently, my approach is to follow whatever consistent coding convention is used in each individual source file. I have no trouble with a project that consists of source files created by individuals who all had different ideas on how to structure their code - as long as there is a consistency to it within each source code file.

I know of developers that cannot stand working on source code that is not exactly structured 'their' way. I consider such inability a major disadvantage: these people tend to waste large amounts of time on 'restructuring' some perfectly consistent piece of code.

I strive to write code with as few comments as possible. Yes - you heard that right. I think comments are a last-resort type of thing.

I try to write the code first and foremost in such a way that it is as clear and as easy to understand as possible; I think this might be more of an art than a technique.

I only use comments if I cannot make everything crystal clear by means of clean code. You do need as little comments as possible, but no less. Gratuitous comments that simply re-state what the code does are a no-no - things like:

// Increment i
i++;

// This is the constructor

make me cringe.

Comments are dangerous - they have a tendency to get outdated as the code around them evolves, and instead of being helpful, they often become a liability. So it is important to try hard to make the code so clear it does not need comments.

Instead, I restructure and rewrite my code until it is as close to self-explanatory as possible.

My priorities are always to write readable and understandable code first, and efficient code second. When someone else (often me) needs to pick up the code in a few months or years, the most important goal is to make it easy on the developer to grasp the meaning of the code. Not doing so is inviting bugs to be introduced during maintenance by a developer who only half-grasps or half-remembers what is going on.

Often, if the code cannot be made self-explanatory, that is a symptom that something is fundamentally wrong with the approach used, and you need to take a step back and rethink things.

Writing good code is almost the same as writing a good book or a good story: it has good content, is easy to understand, is consistent in as many respects as possible, is nicely laid out. Code also needs those traits.

I also pay a lot of attention to the code layout and neatness. Small example: I will often order all of the functions, procedures and declarations and alike in alphabetical order.

I know that many IDEs make it easy to 'jump' around to functions in a source code file - but sometimes I find myself separated from my finely honed development environment, working in an unfamiliar debugger, or staring at my source code in printed form, or using WordPad to view the code. Having everything alphabetical makes it easy to guess which direction to scroll to find something in the source code.

Just recently I also figured out a way to describe how I like to pick names for things.

One basic rule of thumb is: short scope allows short names. For example, if I need an index variable, and it will be needed for just two or three lines, I am perfectly happy to call it 'idx' or even 'i'. If the scope gets larger, and spans a few tens of lines, I will make the index name more descriptive - for example 'spreadIdx' or 'pageIdx'. If there are similar variables around, I find what sets them apart and name them accordingly, making sure they are not easily confused - unless in rare circumstances, I'll never use variables like 'idx' and 'idx2'.

Names that have large scope (e.g. span multiple source files) are often longer, and often tell a little story (but again - not too long; it's easy to go overboard).

When creating names, I also try to be consistent in how a name gets formed, and I will often build name that first states the more general and then the more specific.

Similar names have a similar 'lead-in', so in case they get ordered alphabetically (e.g. in a debugger or some IDEs), similar things end up 'close to' other similar things. For example, I'll use

const kFileName_Template = "bla.indt";
const kFileName_MainDocument = "yaya.ind";

instead of

const kTemplate_FileName = "bla.indt";
const kMainDocument_FileName = "yaya.ind";

Till next time!

Wednesday, August 1, 2007

Lightning Brain Podcast: Click here to listen to "Fun with Drop Shadows in InDesign"

Example Files:

Click here to download sample script and sample document

Example result:



Rough Transcript of Podcast:

Hi, my name is Kris Coppieters from Rorohiko, and this is my second 'Lighting Brain' podcast - about having fun with drop shadows in InDesign.

Initially, I'll try to create a number of podcasts in fairly quick succession, as to build up some content on the Rorohiko blog, but in the long run I aim to release a new podcast about once every two weeks.

This episode I wanted to talk a bit about some fun experiments I did with drop shadows in InDesign. My brain seems to be a magnet for ideas - which would be fine, if only all ideas that pop up would be useful. Sadly enough, some of my ideas are rather silly, and this podcast is based on one of the silly ones.

The podcast will also delve a little bit into some mathematical aspects of my experiments. However, even if you are not mathematically inclined you should still be able to have fun with the example document and example script - so even if the mathematics gives you the blue shivers, don't worry! Just download the sample files and have fun!

My idea was this: assume there are a number of page items scattered over a page or spread. Why not coordinate all these drop shadows so they cause some visual effect to occur? Standard drop shadows are rather dull. They simulate what would happen if there was a light source at infinite distance throwing light on a page item floating at a particular height above the page.

What I was wondering about was: what would happen if the simulated light source was not at infinite distance, but instead somewhere else - for example, located on the viewer's head, close to the paper, like a head-torch, or if the light source was simulating one of those swiveling desk lights.

The other thing I wondered about was: what if the page items that are throwing drop shadows would be pretending to float at smoothly varying distances from the page - for example: page items near the middle of the page would float higher, and page items near the edges would float lower above the page.

So, I set out to do some experiments using InDesign and ExtendScript, and it turns out the results are interesting - interesting enough to share as a podcast.

I started with the following assumptions and limitations:

All distances are expressed in points

Pages and spreads have a coordinate system: an X-axis pointing to the right, a Y-axis pointing down. The origin of the coordinate system can be pretty much anywhere, but often it is somewhere in the upper left hand corner of the page or spread. In the script, I rather arbitrarily use X-Y coordinates relative to an origin that sits in the middle of each page.

I introduce a third axis - a Z-axis which is assumed to point out of the page towards the viewer. A page item that floats above the page will have a positive Z-coordinate. A page item that does not float but sits on the page has a Z-coordinate equal to zero. Because pages are considered to be opaque, negative Z-coordinates don't make much sense in this model, as they would simulate page items behind the page.

I assume there is a simulated light source hovering at some point above the page. The point has some X and Y coordinates (which express the point on the page above which the light source is located) and a Z coordinate (which expresses how high above the page the light source is hovering).

As far as the page items go: in addition to their X- and Y-coordinate data, selected page items are assumed to also have a Z-coordinate which shows how high above the page these page items are supposed to be floating (so they can cast a shadow).

I simplified things by representing each page item by a single point - the page item's center, which is easily calculated as the mean values of the bounding box X- and Y-coordinates.

To get an interesting Z-coordinate I used a mathematical formula that takes these X and Y coordinates and returns a Z coordinate.

One of the formulas in the example scripts gives a Z coordinate that has its highest values for page items in the middle of the page, and gets lower for page items near the borders of the page (for the mathematically inclined: an elliptic paraboloid).

To calculate the parameters of the drop shadow of each individual page item, I went back to some of my high-school geometry formulas. Using the (X,Y,Z) coordinates of the light source and the (X,Y,Z) coordinates of each page item's center, I calculated the amount of X- and Y shift to apply to the drop shadows.

To work the magic, I also assumed that the script would only affect page items that are located on a page layer - I called the layer "magic carpet" (all lowercase, one space). Only page items on this layer are affected by my example script.

Finally, to get some visuals, I decided to first create a page filled with a regular pattern of square page items. The script will of course work with any kind and any amount of page items on the "magic carpet" layer, but I expected the best visual effect with a regular spaced grid of page items.

I created a new document, created a layer "magic carpet". Then I used two step-and-repeat operations to sprinkle a host of small, colored squares all over the page (about 6 squares horizontally and 11 squares vertically, with a good gap between them). You first create a single square, and use step-and-repeat with a horizontal displacement of..., then select the row of squares, and do a second step-and-repeat with a vertical displacement of ...)

The I ran my little script - and suddenly I was presented with quite a nice 3-D effect.

The script and example documents I used are available for download from this blog (rorohiko.blogspot.com).

Step-by-step:

On InDesign CS or CS2, you install the file 'ShadowDance.js' into the Presets - Scripts subfolder of your InDesign application folder. The script uses .js as its file name extension instead of .jsx - that way the same script works on CS as well as CS2 and CS3.

On InDesign CS3, you install the file 'ShadowDance.js' into one of the script folders - I installed it in Scripts - Scripts Panel.

Launch InDesign and create a new document.

Create a new layer called 'magic carpet'.

On this layer, create a single square, about 60x60 points in size (about 20 mm x 20 mm); position it in the top left hand corner.

Fill the square with a color.

Use Edit - Step and Repeat... to create five or six duplicates of the square, with a horizontal offset slightly larger than the side of the square (e.g. 72 pt or 25 mm), and a vertical offset of zero.

Select the whole row of squares, and create 9 or 10 duplicates of the row of squares, this time with a horizontal offset of zero and a vertical offset slightly larger than the side of the square.

You should now have a page that is covered with a regular grid of square page items, all of which sit on the 'magic carpet' layer.

Bring up your scripts pallette (Window - Scripting - Scripts in CS, Window - Automation - Scripts in CS2 and CS3. In CS3, look under 'Application' if you installed the script into the Scripts - Scripts Panel folder).

Double-click the script 'ShadowDance.js'. You should get a result that looks similar to what you find in the example document 'ShadowDanceCS.indd'.

Till next time!