About two months ago, I was asked to begin writing widgets for a product that didn't exist even as a set of requirements. I declined to do this task, but couldn't really explain why. Now the same project is nearing completion and I'm finally able to articulate my misgivings about writing code in anticipation of the actual use cases, and with not planning out the front-end before coding it in general.
As developers, I think we've got some cultural issues that often preclude planning things very well. For one, we often tend to become so enamored of our own code/approach that we refuse to admit when it doesn't address the goals of the application it's used in. I'm super guilty of that, myself. For another, when it's crunch time we have a tendency to get all heroic, pulling all-nighters and promising things we know we shouldn't be promising. Combine these proclivities and you get the potential for creating a codebase out of weird one-off solutions that have been hacked together overnight to form an "architecture" that's the code debt equivalent of those 0% interest for one year credit cards that balloon up to 33% the first time you miss a payment. And you promise, naturally, that you'll refactor all that as soon as things quiet down, but let's face it: if things quiet down it'll be because you moved on to some other project, and even when someone does finally find the time to refactor it they're just going to tear the mess out and start from scratch.
That's the project I'm on right now, the project that began with a request for widgets. There's been no front-end planning in the scope of the application as a whole, aside from a consensus about where JS and CSS files should live. The same tasks are performed differently on different pages. Custom plugins are used in places they weren't designed for. But those aren't even such serious issues. The plugins can be made more (or less) generic, that's not a terribly difficult change to make. What's going to be problematic is going back after the fact and defining an actual architecture where currently we just have lots of code.
I'm no expert on this shit. But it is something I've done several times out of necessity, in the interest of doing good work and preserving my sanity. If I were going to get in my time machine and head back to where this project began (taking all the user stories with me, even at the risk of creating a catastrophic paradox) here's what I'd do:Figure out the requirements
If you're on a project you're doing for money (i.e., not a personal labor of love), presumably you have a project owner or some other business person who will tell you what the product needs to do. But there's a difference between those requirements and the requirements you'll code to. I believe front-end developers are people who have to be willing to dip their toes into a variety of fields to be effective. We have to be able to consider the best technical solution, but that'll come later in the process. When the planning stage begins, we need to be able to ask the right questions about things like branding, design, and copy, things that - when you look at our role literally - ought not concern us. Whitney Hess wrote a really good article on this recently, listing off all the things developers, not just IAs or UX Designers, should figure out before even thinking about writing code.
Why do we need to know all that crap? Why can't we just wait for someone whose actual job it is to figure it out to do so? For the same reason we don't put our code in a glass case as soon as we write it and never change it again over the course of the project: every spec, wireframe, and mockup you receive is subject to change. If it's a couple words in the copy, NBD. But if the change completely alters, for instance, the intent of the site's landing page and what information it contains, your code is going to be completely fucked and newly useless. Unless you make a nuisance of yourself starting the second you arrive at the kickoff meeting and ask lots and lots of questions about things that are none of your business. If you know the business goals of each piece of your application, you can better predict what the requirements for the final product will end up being, and you can write code based on assumptions that are more likely to be correct.Define the ground rules for users
This isn't as simple as just saying, "We'll support IE7 and up." In addition to which browsers the users favor, you have to know:
- What is their level of internet savvy
- Do they have Flash/Silverlight/some other damned thing installed
- Are they accessing the site from mobile devices and, if so, which ones
Your counterparts on the backend are probably having their own discussion about architecture. If you don't want to be in the position of having to work around decisions they make that affect you, talk to them early while all this shit is still hypothetical. If they can integrate your pattern into theirs (and vice versa), things will probably go a lot smoother. I've talked here before about how I think it's ideal when the only thing frontend people and backend people need to discuss is what properties should be in a JSON object and what form elements should be named when they get POSTed. If you can get to that point, you save a ton of grief. It's great to be able to switch between the front and back end, but if you have specialists on both sides, it's better to just have everyone stick to their territory. Yeah, I said it, grab some territory. Grab it early. I don't care if that sounds like I'm advocating not being a team player. If your area of concern is the entire fucking application, you're going to be a lot less efficient and your "team" is going to end up in last place, if you finish at all.Pimp your ride
Probably you are gonna need some bling. You're going to need widgets like a calendar to ease the selection of dates and a rich text editor so your users can have access to extremely important features like bulleted lists. You're going to need swooshy little animations whenever something updates and tooltips that look like little thought-bubbles. Find all of these things. Search through every mockup and run a mental background check on every IA and Visual Designer working on your project to try and remember their propensities. Once you've defined them, research each and look at all your options. Rank them, list the pros and cons, and group them by framework. Don't forget to look at the CSS and the markup they generate. There exist plugins that look totally hot on their demo pages, but are rapidly revealed to be complete pieces of shit once you try to reskin them. And then you can't change the background color of the RTE without rewriting the whole damned thing and the utility of the plugin nosedives and your client tries to sue you.Choose a framework
Having clearly defined your needs, you're in a position to choose the toolkit that will best meet them (or to be a masochistic purist and choose no toolkit at all). In this idealized timeline, this is the penultimate step, but of course it may not always be possible. Sometimes you're stuck with one framework because it's what your company has standardized on and you're using it in a bunch of related applications and - though not ideally suited - it's good enough. There is an argument for sticking with what's in place because it's familiar. But let's say you can choose. If you've got a good sense of the project's requirements and how those will translate to framework-dependent things like server communication and plugins, this should be a no-brainer. Refer to the totes awesome research you've labored over and commit.Do all those things you're supposed to do
You know. Write unit tests. Write documentation. Lazy-load your scripts instead of just dumping them all down at the bottom of the page and telling yourself they don't really count if they're there. Kick off the infrastructure before you start creating objects and wiring things up to page elements. For me, this is a totally theoretical step. I have yet to do this on the frontend, and I know that is a really bad thing. The last time I wrote a unit test, I was a state employee. The last API I documented was for a JSF widget library, and this was when JSF was the new hotness. The problem is that I don't think about it early enough. Like refactoring, I tell myself I'll do this when things quiet down. And things never quiet down. They start quiet and get progressively noisier. If, on my current project and on many prior to it, I'd started with this type of "housekeeping," I think I would have actually had time to do it. Instead I got bogged down adding more features, fixing bugs (bugs unit tests would have helped discover), and finally explaining the code to whoever I handed it over to (which would have gone much more quickly if I'd documented it outside of random where-I-thought-of-it inline comments). I am totally sick of doing things that way. Next project I work on, immediately after downloading whatever toolkit I'm using, I will take care of this stuff.
So there's my plan. Now I just need the time machine, and I'm golden.
Addendum: It feels weird to talk about this stuff without mentioning Rebecca Murphey's recent posts on large applications and rolling your own. It's not directly related, but it's something I've been thinking about a lot lately, as I'm sure many other people have. Something I couldn't find a way to spell out clearly above was that, if I were going back to square one with those posts in mind and it were all up to me, I might have made different choices as far as a toolkit. Then again I might not have - this is not the world's most complex app here, it's mostly just a lot of show/hide and XHRs. Doesn't mean it shouldn't be unit tested and documented, though, and having a clear way of handling data from the server and XHRs from the get-go would definitely have made a difference in the amount of time we've spent debating different approaches. I do think debates like that are worth having, but sometimes it's also very valuable to be able to point to a toolkit and say, "This is the [Framework X] WAY." Anyway, my point is that this is not an exhortation to come up with the whole thing on your own, merely to get all the pieces laid out and thought about beforehand.