Showing posts with label best practices. Show all posts
Showing posts with label best practices. Show all posts

02 April 2013

Why the PhyloPic Relaunch Took So Long

Or, A Lesson in Development Strategy.

As I announced last week, my website, PhyloPic, has been relaunched with a massive update. One of the key updates is a public API for developers. A lot of people have been looking forward to this, and it was actually almost ready for release last summer. So why didn't I release it?

Failure to Branch

Basal tracheophyte.
Public Domain.
As I was writing up the documentation for the API, I learned of Bootstrap, a CSS/JavaScript framework. I realized that it could solve a lot of the design issues I was having — problems with the site on mobile devices, older browsers, etc.

What I should have done: Created a new development branch for adding Bootstrap while continuing to polish up the API branch. That way, I could have released the API shortly while still being able to work on the design issues in parallel.

What I actually did: Continued working in the same branch, ensuring that I couldn't release the API update until the Bootstrap update was complete.

Having Other Projects

By the end of summer I was mostly done with the revisions, but there was still some cleanup to do. By now some other projects I'm attached to, one with other collaborators, were suffering. So I spent most of my free time in the autumn working on those. (I have a full-time job and a toddler, so that isn't much.)

Homo habilis.
Public Domain.

Becoming Enamored of New Technology

In the autumn, Microsoft release a preview version of TypeScript, and I quickly saw that it was going to be extremely useful. So I rewrote PhyloPic's client-side code — it wasn't too hard and it made further development a lot easier. This caused some delay up-front, but I don't regret it.

Becoming Enamored of the Wrong New Technology

Around this time I also realized that I could finally do away with the last bit of Flash on the website: the Image Submission Tool. HTML5 had become mature enough to do all the image manipulation in the browser itself. I did a lot of research, learning about the Canvas, Typed Arrays, etc. And after a lot of work I actually created an image-processing workflow that work in HTML5-enabled browsers. As a bonus, I got a little standalone project out of it: Pictish.

But there were problems. One is that the best existing JavaScript library for creating PNG files doesn't use Typed Arrays — it uses strings, which means that it is slow for large files. I tried creating my own PNG encoder, or adapting that one, but soon realized it was far too much work. Another problem is that I was no longer supporting older browsers (although this was a trade-off against supporting mobile platforms, so I didn't feel too bad about it).

But there was a much more fundamental danger: doing the image-processing in the client side meant that the API had to trust the client to do it properly. What if some developer used the PhyloPic API to add images to the database but didn't do it right? That could be disastrous.

Octopus bimaculatus.
Public Domain.
I realized I would have to do things the old-fashioned way: on the server. After a bit of research, I identified Image Magick and Inkscape as the best tools. The new methodology was so completely different that I ended up making a lot of database changes, too. Until recently, all files were stored in the database — now they're just stored as flat files. The good news is that this makes load times faster.

Doing Things the "Right" Way

Throughout all this I had been making an effort to "dogfood" my own API, i.e., to use it on the site itself. This has the advantage of making load times faster, since the basic page can be cached and then the data can be loaded in secondarily in a much smaller format. Unfortunately this meant a lot of rewrites for how the pages are rendered.

After a while, the code to generate pages from the data had gotten really complex (mostly involving on-the-fly element generation using jQuery). Around the time I was redoing the Image Submission Page, I realized my whole approach was untenable. I needed a cleaner way to divorce presentation logic from control logic.

I ended up using Knockout for the entire site. It made things a lot more manageable.

In Summary

The biggest problem was my branching model, or, rather, my lack of one. Solitary developers often fall into this trap: we think that, since we're doing all the work, there's no need to have more than a single branch of development. At work, we've been using this model and found it very successful. Going forward, I plan to do this on PhyloPic as well. No more massive updates where everything is different. Just incremental features and fixes.

17 April 2008

Comments on the Flex Best Coding Practices

Adobe recently published preliminary coding guidelines for people making contributions to the Flex framework (mx packages). Here's the link:



Although it's specifically meant for the Flex project, the vast majority of their guidelines are applicable to ActionScript 3.0 code in general. Overall, I really like their direction. But I thought I'd take some time to comment on what I don't like or find questionable.

1. Acronyms

When using acronyms in code, the programmer faces a dilemma: convert the case to whatever is appropriate for the context, or leave them all in caps? They opt for the latter, and usually this is fine. However, names that use two acronyms can suffer from ambiguity, as in their hypothetical example loadCSSURL (which some programmers would prefer be rendered loadCssUrl).

Personally, I think there's no good solution here, so I just go with their approach. But I recognize that this approach has problems. As they say about loadCSSURL, "[T]ry to avoid such names."

2. Package names should always be nouns or gerunds

Actually, guys, a gerund is a noun. You're thinking of participles, which are verbs and, in English, look exactly like gerunds. (Gerund: "Walking is fun." Participle: "I was walking.")

Anyway, I don't see why this should be so. I've named a lot of packages after verbs, myself. Is it really that bad to name a package of things that draw something draw as opposed to drawers or drawing?

3. Start interface names with "I"

I've gone back and forth on this one and have finally decided that I actually hate it. Suppose I start out making something an abstract class and then later decide it should be an interface (or vice versa)? Why should I have to rename it when, to external code, nothing has changed? In most cases, external code shouldn't care whether an entity is an interface or a class (the obvious exception being when external code is expected to implement the interface).

I tend to use adjective for interfaces when possible, but often I just use plain old nouns. What's the harm?

4. Brackets on their own lines

They never explicitly recommend this, but all the examples show it. To illustrate what I mean, they recommend this:
function foo():void
{
if (test())
{
doSomething();
doSomethingElse();
}
else
{
doAnotherThing();
}
}
Over this:
function foo():void {
if (test()) {
doSomething();
doSomethingElse();
} else {
doAnotherThing();
}
}


Now I've heard people swear by the former, saying it makes blocks of code much easier to spot. But to me, it seems like a huge waste of space. I can only see so many lines at once, and if half of them are brackets, I'm going to have to be paging up and down an awful lot. Besides, I've been using cradled brackets for over a decade and I don't have any problems spotting blocks.

That said, I've never tried the other way, so I reserve final judgment until I give it a fair chance.

5. Event handler names

The recommend the form eventNameHandler. I like the older ActionScript convention onEventName. Not only is it more succinct, but it has the added benefit of placing all your handlers together when you sort methods alphabetically.

6. Postfix vs. prefix operators

They recommend postfix over prefix operators, despite the fact that prefix operators are generally faster. This completely baffles me. If this:
for (var i:int = 0; i < n; ++i) {
trace(i);
}
...is faster than this:
for (var i:int = 0; i < n; i++) {
trace(i);
}
... then why on Earth would you ever use the latter? It's not like one is more readable than the other. They're equally legible, and one is faster—no contest.

7. Single-statement if blocks

They recommend leaving brackets off. Personally, I prefer to always use brackets—it's more visually cohesive, and it makes things easier when you later realize you do need another statement in there, after all.




By this time it probably sounds like I hate their ideas, but actually, these are the only ones (and I follow that first one, anyway). Everything else is great and much of it had me going, "Yes! Preach it!"

This is something every ActionScript coder should read. Like me, you may not agree on every detail, but overall, it's an excellent guide.