HTML5 Fonts: Let’s Make them DRY

The Problem

Much fun can be had designing with the ever-increasing universe of fonts offered by directory’s like Google’s. Photoshop Tamagotchi is a thing of the past as you can rapidly iterate with a few keystrokes. But it’s still a few keystrokes too many …

A niggle with CSS3 fonts is they involve some redundancy. Here’s a real-world example:

  1. @font-face { font-family: Delicious; src: url('Delicious-Roman.otf'); }
  2. @font-face { font-family: Delicious; font-weight: bold; src: url('Delicious-Bold.otf'); }
  3. h3 { font-family: Delicious, sans-serif; }

What happened to Don’t Repeat Yourself? We have “Delicious” mentioned five times here! If we switch from the “Delicious” font to the “Pinboard” font, we’ll need to make five changes. And not everyone uses vim, yo. Moreover, we’ll need to locate a suitable font, e.g. Pinboard, and download it.

I get it, this level of indirection serves a purpose. We can give a handle to the font once and then use that everywhere else. Heck, we could even continue to call the font “Delicious”, but surreptiously switch the “src” to “Pinboard-Roman.otf”. But that wouldn’t be very nice, would it?

Now, a font directory like Google solves part of the problem by explicitly allowing you to link cross-domain to Google. In fact, if you want, it will even generate the stylesheet for you. But you’ll still have the same DRY issue in your CSS – for each new font, you’ll need to include the stylesheet and use it in your CSS.

The Solution

Bottom line, I decided to make this crazy snippet, by manually walking through the font directory and picking out every single possible font:

  1. <link href="http://fonts.googleapis.com/css?family=Droid+Sans|Lobster|Droid+Serif:regular,italic,bold,bolditalic|Nobile|Yanone+Kaffeesatz|PT+Sans:regular,italic,bold,bolditalic|PT+Sans+Caption:regular,bold|PT+Sans+Narrow|Reenie+Beanie|Tangerine:regular,bold|Molengo|OFL+Sorts+Mill+Goudy+TT:regular,italic|Vollkorn:regular,italic,bold,bolditalic|Cantarell|Inconsolata|Crimson+Text|Arvo:regular,italic,bold,bolditalic|Cardo|Neucha|Neuton|Droid+Sans+Mono|Cuprum|Old+Standard+TT:regular,italic,bold|Philosopher|Tinos:regular,italic,bold,bolditalic|Josefin+Sans:100,100italic,light,lightitalic,regular,regularitalic,600,600italic,bold,bolditalic|Arimo:regular,italic,bold,bolditalic|Josefin+Slab:100,100italic,light,lightitalic,regular,regularitalic,600,600italic,bold,bolditalic|Allerta|Geo|Allerta+Stencil|Puritan|Puritan:regular,italic,bold,bolditalic|Cousine:regular,italic,bold,bolditalic|UnifrakturMaguntia|Bentham|IM+Fell+DW+Pica:regular,italic|IM+Fell+English:regular,italic|IM+Fell+English+SC|IM+Fell+DW+Pica+SC|IM+Fell+Double+Pica+SC|IM+Fell+Double+Pica|IM+Fell+Great+Primer+SC|IM+Fell+Great+Primer|IM+Fell+French+Canon|IM+Fell+French+Canon+SC|Coda:800|Raleway:100|UnifrakturCook:bold|Covered+By+Your+Grace|Just+Me+Again+Down+Here" rel="stylesheet" type="text/css" />

I’ll repeat that below for ease of cut-and-paste:

<link href=”http://fonts.googleapis.com/css?family=Droid+Sans|Lobster| Droid+Serif:regular,italic,bold,bolditalic|Nobile|Yanone+Kaffeesatz| PT+Sans:regular,italic,bold,bolditalic|PT+Sans+Caption:regular,bold| PT+Sans+Narrow|Reenie+Beanie|Tangerine:regular,bold|Molengo| OFL+Sorts+Mill+Goudy+TT:regular,italic| Vollkorn:regular,italic,bold,bolditalic|Cantarell|Inconsolata|Crimson+Text| Arvo:regular,italic,bold,bolditalic|Cardo|Neucha|Neuton|Droid+Sans+Mono| Cuprum|Old+Standard+TT:regular,italic,bold|Philosopher| Tinos:regular,italic,bold,bolditalic| Josefin+Sans:100,100italic,light,lightitalic, regular,regularitalic,600,600italic,bold,bolditalic| Arimo:regular,italic,bold,bolditalic| Josefin+Slab:100,100italic,light,lightitalic,regular, regularitalic,600,600italic,bold,bolditalic| Allerta|Geo|Allerta+Stencil|Puritan|Puritan:regular,italic,bold,bolditalic| Cousine:regular,italic,bold,bolditalic|UnifrakturMaguntia|Bentham| IM+Fell+DW+Pica:regular,italic|IM+Fell+English:regular,italic| IM+Fell+English+SC|IM+Fell+DW+Pica+SC|IM+Fell+Double+Pica+SC| IM+Fell+Double+Pica|IM+Fell+Great+Primer+SC|IM+Fell+Great+Primer| IM+Fell+French+Canon|IM+Fell+French+Canon+SC|Coda:800|Raleway:100| UnifrakturCook:bold|Covered+By+Your+Grace| Just+Me+Again+Down+Here” rel=”stylesheet” type=”text/css” />

Now include that in your CSS and you can freely use whatever font you want, whenever you want:

  1. h3 { font-family: Neucha, sans-serif; }
  2. div { font-family: "Reenie Beenie"; }

Production Use

I haven’t tested it, but I’m informed modern browsers will thankfully download only the fonts they need, so this is actually a viable solution for sites which will be frequented only by modern browsers, though obviously the snippet itself is too big for sites where performance is critical.

Unfortunately, IE6-IE8 will actually download every single font specified! So really, you should only be using this for development, and ensure production sites only declare the fonts they need. However, don’t lose site of DRY! In the spirit of Agile, DRY, and Continuous Integration, it would still be worth looking at ways to automate that process, e.g. with a server-side solution that generates the minimalist “link” tag.

Of course, the snippet is limited only to the Google fonts, good enough for my aesthetically-challenged purposes, but the principle could be generalised to encompass other font directories. Or someone in a company which has licensed and/or issued a standard set of fonts via their style guide, could also generate a company-specific snippet fot this purpose, containing all fonts. They could then make this a standard stylesheet which could be linked to from any HTML document.

The Secret to Quick Node Hacks is

to ignore security and do everything local.

I’m at the inaugural Amped event, and you could immediately guess people were going to be using Node, from the fact they were breathing. So I pointed them to my , which is indeed a total hack.

Basically, you can do any multi-user app with a server of 10-20 lines. All you do is broadcast each user’s actions. In fact, such a server would make a great open source project (but I’m otherwise occupied playing with PhoneGap and Android). Sure, Node makes servers easier, but for version 0.01, this is all you need. A video sync app would get messages like this:

{ user: "john", time: "103094401", action: "join" }
{ user: "sue", time: "103095491", action: "join" }
{ user: "john", time: "103095822", action: "takeControl" }
{ user: "john", time: "103096111", action: "play" }
{ user: "john", time: "103096483", action: "fastforward", data: { position: 2.12 } }
{ user: "sue", time: "103098111", action: "takeControl"}

This is trading off security for productivity. There’s ZERO security here, because (at least the way I implemented the video sync) any user can forge a request from any other user. But that’s the point: It’s a hackathon. Unless you’re at a security hackathon, security doesn’t matter a hoot. Nor does maintability, readability, or most other -ilities.

If I was doing this for a “real” project, I’d start the same way. I’d be wasting my employer’s/client’s time if I was spending it if I did it any other way, since 9 projects out of 10 (</blatantly made-up stat>) never get out of feasibility phase.

UML Tools in the Cloud

We have several IDEs in the cloud such as:

(Update: How’s the timing? This blog post was written one day before Dion and Ben announced Bespin, the massively important open-source project to build an IDE in the cloud among many other things. Needless to say, Bespin has been added to the list!)

I would like to see more tools for UML tools to complement these online IDEs. I’m not talking about naieve enterprise silliness like model-driven architecture; I mean just some basic tools ot support basic sketching.

So here is a nice one Jeremy showed me: Web Sequence Diagrams. It’s based on a declarative text spec of the model, rather than endless, tedious, mouse clicking. A perfect example of the WYWSIWN (what you see is what you need) paradigm trumping WYSIWYG. Just a nice, simple, tool that lets you generate UML models in a matter of minutes, the most any agile practitioner would want to spend on them.

Did you hear the one about enterprise reuse?

Confirming that enterprise reuse can be a bit of a joke at times, Jason Gorman shares this fable on enterprise reuse (via another inspired Jason). Short summary: Two ladies could save 8 cents by boiling tea in the same kettle. But the cunning analyst forgets that, since they live 20 miles from each other, there will be overheads to the tune of a $20 cab ride and the travelling time.

Viewed from a high level, enterprise reuse is a noble goal; what’s the point of being a single company if everyone writes their own code? In practice, it can be fraught. Ironically, it’s usually easier to reuse publicly-available libraries (e.g. open-source libs on sourceforge) and public web services than those in the same company. The following things make reuse more digestible in an enterprise setting:

  • Language-agnostic, industry-standard, technologies Using obscure or proprietary technologies can work in an individual team, but rarely in a large enterprise; in most cases, there are simply too many factions with different skill sets and legacy code bases. There are companies that describe themselves as a “pure Java shop”, for example, but you will indefinitely find pockets working in Python, .Net, and so on. Getting an enterprise to truly standardise (not just lip service) on something non-industry-standard is futile. It takes several months for people to get really competent in a new language; in an environment full of contractors and staff turning over every few years, and full of legacy systems, you can count on the fact that there will be disparate technologies at play. It’s a good thing, too; no one language (or paradigm, for that matter), not even Java *gasp*, is the right solution to all problems.
  • Service-oriented SOA as in “built on a needs-driven basis”. The stuff that’s available for reuse is stuff that’s been abstracted from real-world projects, where at least one project already built it and at least one other project actually needs it. (Rails is successful because 37Signals uses it; there aren’t dozens of 24-month working groups involved.) Perhaps the biggest mistake enterprises make in this whole area is pushing out functionality no-one else actually wants to reuse.
  • Support trumps standardisation The best way IMO to encourage a certain technology or library is the carrot, not the stick. Make people actually want to reuse what you have to offer, rather than forcing them to do so. I am very sceptical about any situation where architects have to act as the reuse police; if the component or service was designed, documented, easily located, and served a genuine need, wouldn’t the developer be drawn towards it? Wouldn’t they actually want to use it, and maybe even give something back to it? In an ecosystem where components and services are high-quality and easily-accessed, you can forget about mandating reuse because it will happen anyway. See Web API Patterns and Documentation as Conversation for the kinds of things that will make this happen.
  • Online As a rule of thumb, offering a centralised web service is better than offering a reusable code component. The web service can (should) be easier to use and is language-agnostic. Obviously, there are sometimes situations where code components make more sense, especially from a performance perspective. I wouldn’t use an online service to create a polygon every millisecond, for example.
  • Easy to use As with any API, it should be easy to learn and make calls. For this reason, online services should be RESTful, not SOAP or CORBA or whatever MQ if you can help it.
  • Iterative progress Don’t try to bite off more than you can chew; if you start pretending *everything* can be reused, you’ll soon find that nothing gets reused.
  • Simple and parsimonious Factor out the trivial factors that relate only to one particular client. In enterprise reuse, this can be a big problem, where client projects may be the budget holder for anything reusable. It’s difficult, but someone needs to stand up and say “no, we’re not going to include feature X because no-one else would actually need it”. In software, deciding what to leave out is usually a greater challenge than coming up with new things to put in. Any feature that won’t be used by a significant proportion of client apps is going to create more clutter than its worth. In a broad-scale service, I’d say this minimum proportion should be something like 5-10% (e.g. Each method should be exercised by 5-10% of clients who used the class.) In an enterprise context, where there may only be a few clients, I’d say the criterion should be “at least 2 clients”. (There was a podcast interview a while ago, with PragDave I think, where he was asked what he would include in Rails 2.0. He essentially replied that he’s more worried about taking things out – push them out of the core distro and into plugins.)
  • Automated Sometimes, people think “it’s all under the same roof”, so getting access and learning about an API requires a call or a meeting with the owner of the reusable service/component. Whereas, if Google offers the same thing, it will provide online doco and a means of accessing it automatically, without any human intervention. An agile enterprise should aspire to do the same thing; it doesn’t have to be as polished as a public offering, but the spirit should be the same. Otherwise, it won’t scale, and the owner will soon become fed up doing the same thing over and over.

Ajax Diagnosis And Testing Patterns – Podcast

Welcome to Ye Olde Ajax Patterns Podcaste, the final in this series that began twelve months ago. 3+4+4+1 = 12 podcasts in all, covering 71 patterns (the 70 patterns in the the book as well as Dyanmic Favicons). Find them all on the podcast category – http://www.softwareas.com/category/podcast/ or subscribe to the podcast feed at http://www.softwareas.com/podcast/rss2. Thanks for listening!

This podcast covers eight patterns on debugging/diagnosis of Ajax Apps, as well as testing Ajax apps, and I’m joined by Craig Shoemaker from Polymorphic Podcast, also a co-author of “Beginning Ajax with ASP.NET”. After some announcements, the interview begans at 6:00. The podcast overall is 60 minutes.

<

p> Ajax Diagnosis Patterns:

<

p> Ajax Testing Patterns:

With the series now complete, the podcast will now resume regular Sotware As She’s Developed topics including but not limited to agile development, Ajax, the web, and usability. Also, more conversations – please drop me a line at [email protected] if you’d like to come drop in for a skype chat.

As always, credits on this podcast to My Morning Jacket for the lead-in track, “One Big Holiday”. All podcasts in this series licensed under CC.


Audio Note: Sorry about the noise at some stages in this recording – I now know a lot more about audio levelling (the problem of keeping both ends at the same level), but at the time this was recording, it turned out I had set Craig’s end at too low a volume. I used Levelator to level each end, leading to too much noise…next time I’ll need to pump up the volume at each end from the start. I’m also looking forward to resuming use of Bias SoundSoap, but there’s no easy way to get this running on an Intel Mac for now!

XML Descriptors, Be Gone!

Dion posted a story about Nokia’s new mobile widgets. This will be very cool if it’s as good as it sounds. However, what got me was the XML-based config – three separate files for config, skin, and widgets. The widget config:

  1. <widget name="Example widget" version="0.1">
  2.  
  3.   <info>
  4.     <creator>
  5.       <user>username</user>
  6.       <date>7.6.2006 12:00</date>
  7.     </creator>
  8.  
  9.   <!-- Configuration of servicehandlers which the widget needs to operate -->
  10.   <services>
  11.     <service type="syndication" id="feed1">
  12.       <reference from="feedurlrss" to="feedurl"/>
  13.     </service>
  14.   </services>

My comment here isn’t specifically about this project, because most APIs continue to use this convention. I don’t get why APIs continue to come out requiring complex EJB-style XML config, in three different files no less. Learn from Rails and Pico and use code for config.

The arguments for XML config are fundamentally flawed:

  • “Anyone can edit it, not just programmers”. And if you believe that, you’re still waiting for your manager to learn FORTRAN and COBOL, thus rendering programmers obsolete. Mwuhahah. Obselete, I’ll tells ya.
  • “It can be changed at runtime, no compilation required.” This might occasionally be useful if the app’s shipped off to another site, but that’s a slim minority – it will either be a hosted app which you can easily re-deploy after re-compiling (as with these widgets) or a desktop app which will hopefully offer a nice config UI rather than requiring the user to hack some XML files! We like to develop standards to serve the vast majority, not the slim minority.
  • “It’s neater.” In any modern language, you can easily develop an API that lets you perform configuration with a grammar resembling a domain-specific language. I don’t consider the above XML to be particularly neat, nor most EJB descriptors I’ve come across.
  • “It can be validated.” True, you can check the file’s grammar, but you can’t validate that a given attribute must be a class in your program, for instance. With code-based config, you can.

How Much Docs?

Nate’s talking about functional specs.

How much doco happens on a project is one part opinion and one part “what do you want to optimise for?”. I generally find there’s a dichotomy in attitude to software documentation.

1. Definitive (aka normative, exhaustive, complete, bureaucratic, rigourous, formal). The ideal here is that everything should be covered in documentation – the docs are a snapshot of every activity, plan, and state of the project. The aim is: (a) to let you carry on unhindered if “(stakeholder/worker) is run over by a bus” for all instances of (stakeholder/worker); (b) affect payments and provide legal evidence/cover. 2. Informative (aka agile, pragmatic, informal, half-hearted). Use docs pragmatically, to help explore ideas, reach consensus, remember what we said, etc. You cannot reconstruct a project from docs like this – if everyone is “run over by a bus” at the same time, there will be a delay and a subsequent divergence in the project direction.

That’s a clear distinction – in the Informative mindset, the docs are only there to reach a better quality result; in the Definitive mindset, we’re compromising some productivity for the sake of risk management (both (a) at a tactical level, i.e. if someone leaves; and (b) at a strategic level, i.e. upper management can theoretically be comfortable about how much is exposed and how much they’ll get back as a penalty if things slow down, etc.).

Both Definitive and Informative have a range of approaches. In particular, Informative use of docs can range from none at all, up to a project resembling a Definitive project, but when you look closely, the docs are lightweight and only subject to informal reviews rather than full-on inspections and audits. They may also the use of less conventional “documentation”:

  • Whiteboards
  • Post-it notes
  • Flashcards
  • Wikis and blogs.

As an agile proponent, I’d generally favour the Informative approach, but software isn’t developed in a vacuum. Organisations understandably want to be reassured about what gets delivered, which pushes them to rely on Definitive methods. The problem here, of course, is that Definitive-style docs require an almost impossible task of pinning down requirements, and furthermore, fixing requirements runs counter to the modern organisation’s goal of being agile.

There’s obviously no one solution, but one essential ingredient comes from multi-talented people. Too often, requirements are penned by business people on the assumption that software developers are left playing with their compilers. That’s changed a lot over the past five years, and organisations will do well when they hire business people who have an interest and competency with software, and software developers (fast becoming the majority) who can empathise with the business’s needs and are actually literate as well.

(I hope it doesn’t go unnoticed that Software As She’s Developed has actually posted about software development. That’s so ’04.)

8 New Ajax Patterns (Diagnosis and Testing)

Cool! The Best Practices/Processes Patterns are now complete. They are the final eight Ajax Patterns for now – “final” in the sense of “the list is not yet finalised”. The patterns had been sitting there unattended for about four months now.

More details on the new patterns later, but here’s a quick summary …

First, there’s a new demo – the Ajax Patterns Reader – the best version to try is at http://ajaxify.com/run/reader/logging/realService/. The reader grabs the AjaxPatterns.org content and presents them Ajax-style. You actually queue up patterns in a playlist and click “Next” to “play” them. Yeah, a bit contrived, but it helped illustrate quite a few patterns! If I have time, I’d like to enhance it into a proper reader, and also offer an easy interface to leave feedback, which would be automatically appended to the wiki’s Discussion tab for that pattern.

BTW This further refactoring of the Ajax Patterns Reader illustrates the Scriptaculous GhostTrain tool. If you haven’t seen GhostTrain, have a look – the Javascript will track your activity and build up a test case dynamically (covered in the new System Test pattern). All within the browser. I’ve been in contact with the developers (Thomas and Jon), and discovered it’s still proof-of-concept, but if they can tie it all together, it will be an excellent way to create a system/functional test.

Next, there’s four patterns on diagnosis:

And finally, four patterns on testing:
  • Simulation Service Develop the browser application against “fake” web services that simulate the actual services used in production.
  • Browser-Side Test Create automated tests of browser-side Javascript components.
  • Service Test Build up automated tests of web services, using HTTP clients to interact with the server as the browser normally would.
  • System Test Build automated tests to simulate user behaviour and verify the results.

Agile: Not Just an Attitude

Agile is a big theme these days. Not surprising that it should be a big part of “Web 2.0″, since Web 1.0 is often attributed as an inspiration. Paul Scrivens reminds us of [37Signals' association with agile principles](http://9rules.com/whitespace/fear_is_a_good_thing.php] and that’s evident, for example, in this talk by Jason Fried. Similarly, the agile manifesto was mentioned in a Web Essentials talk last week (I think Kelly Goto’s talk, towards the end). And, of course, you’ll see “Agile” bandied around in most magazine ads run by consulting and IT companies, complete with obWhiteboardSketches.

What you don’t hear much of, in these bite-sized message, is how to do agile. I’m sure the speakers and their organisations know how (though I’m not sure about all the magazine advertisers), but how about the audience? I have visions of some people thinking, “1. Loosen up a bit. 2. ???. 3. Profit!!!!!!”. Hopefully, some of them will do some investigation and learn the how part, but for others, this has the potential to end in tears.

To clarify:

  • Agile is not just taking your tie off.
  • Agile is not just the manifesto.
  • Agile is not just whiteboards.
  • Agile is not just programming.
  • Agile is not just adding functionality.
  • Agile is not just setting up a wiki.
  • Agile is not just “we have to try harder”.
  • Agile is not just taking your tie off.

Here’s why:

  • “Agile is not just taking your tie off” because you need specific technologies, technical skills, and techniques.
  • Agile is not just the manifesto, because that’s a set of principles, not a manual.
  • “Agile is not just whiteboards” because no-one ever got paid for delivering a whiteboard. (With the obvious exception of whiteboard manufacturers, and it’s also likely some retailers in the corporate sector have made a tidy profit in the whiteboard market.)
  • “Agile is not just programming” because it’s also continuous design and testing.
  • “Agile is not just adding functionality” because it’s also refactoring existing functionality.
  • “Agile is not just setting up a wiki” because it’s the content that counts. (And in any event, use the wall instead of a wiki. Support your local whiteboard manufacturer today.)
  • “Agile is not just “we have to try harder” ” because that’s not sustainable, and even if it was, it’s not optimal.
  • “Agile is not just taking your tie off.” No, really. Keep it on if you like. It makes no difference. A black polo top doesn’t make you more agile.

(Vaguely inspired by hearing that Dave Weinberger’s going to be talking about what blogging’s not.)

What I like most about Extreme Programming is that it makes the practices explicit, whether you agree with them or not. “Refactor Mercilessly”, “You Ain’t Gonna Need It”, “Test-Driven Design” – they might sound like mindless mantras to the uninitiated, but they actually reflect a lot more concrete, rich, advice than “Chill Out”, “Loosen Up” and “This agile thing’s a breeze … (something about whiteboards) … profit!”.