Imagine a group of runners who have set out to run a marathon. They train for months to get ready, and come the big day they gather at the starting line wearing their Nike's, tank-tops, and running shorts. They're hydrated and ready to go.
The starting gun fires and off they run. Some are determined to run the fastest, others want to pace themselves and run efficiently, while others are going to pull themselves through on shear willpower. The problem is that no one knows where the finish line is. In fact, no one thought far enough ahead to make an actual finish line. The guy in charge of the route figured that everyone would simply stop once they had run "a marathon", because everyone would be able to tell when that had happened.
Some people turned back at around 5 miles, right when word reached them that there was no exact finishing line. Others turned back after about 10 miles when the road split and no one knew which way they were supposed to go. At around 20 miles hardly anyone could see each other or knew where the race was, and they became despondent and gave up. At 30 miles people were too tired to continue, and just didn't care. Some people, determined not to give up, continued to run until they saw the sign for Wichita, Kansas. How long have we been running, anyway?
Starting to write the code for a program, without first completing its design, is like running a marathon without a finish line. How will you know which roads to avoid? How will you know when you're finished? How will everyone know when to get together, fill their glasses, and toast your success?
It's easy to make mistakes when planning, though. So how will we know what to plan?
A program, at its core, is just input and output. If a program can accept input from the user and then output the correct results, then the program is working properly. So to plan our program, what we need to determine is the input and output.
"But what about our Jutsus! What about our class structure, and storyline!" Yes, those things are important, but not at the moment. The sorts of things that we need to plan are "The user will enter a combination of key strokes to execute a jutsu", or "A user will be able to select his class", or "When the player finishes entering his character's name, the opening movie will begin to play and introduce the story". These statements tell us exactly how the user will interact with our program, and they give us concrete systems that need to be programmed. If we were to write a list of such statements, then all we'd need to do to finish our game would be to go down the list checking off items until they were all gone. Then our game would be finished, Cheers!
All we need to know now is what to put on that list. The answer: Everything. Everything that a user can do needs to be on that list, in every combination. Here's an example illustrating why:
Let's say our list had these two entries: 1) players can double click another player to start a turn based battle; 2) players may not leave battle until one or the other is dead or runs away. Now consider that a malicious user joins your game, double clicks one of your players, waits until it's his turn in battle, and then logs out. Now your regular player is stuck in battle unable to do anything. We forgot that when the program is in the state where two players are battling, each player still has the ability to input a window closing command. So we need to write another line: 3) if a player becomes disconnected while in battle, he has one minute to reconnect, after which the other player wins. Once we take into consideration all input available to the player at every state in the program, then our programming job will be much easier, and we won't be sabotaging ourselves in the future.
This list of actions that the player can take is what's known as a Functional Specification, or Func Spec for short. Func Specs come in many different forms, and most of them don't look anything like the one I'm going to show you. Think of this as an introduction for the BYOND developer. (Here's more in-depth article on Functional Specs).
When planning this article, I started writing a spec for a simple program with which I could illustrate the concept. My first attempt was the Snow Monkey Simulator (which illustrated a different concept). The concept that I finally came up with was a 'Game Chat' environment. The current spec, which may someday become an actual BYOND program, is version 12 (I think) and can be found here.
Notice how this spec has several categories. At the top is the name of the project, and a brief description of its purpose and Core Functionality. This is the statement of why the project exists in the first place. Everything else flows from and supports this functionality.
Next is the main body of the spec (simply titled "Specification"). Notice how most of the statements start by mentioning that this is something initiated by the user. The specification describes what the user can do, and how our program will respond. (I will admit the first several entries are not very good. In my quest to document EVERYTHING, I forgot to write in understandable English. Future versions may remedy this.)
After the main body, you'll notice three other sections. Ever got a great idea for a cool feature? Ever put that feature into your game, only to see your original project bloated by hundreds of non-essential features, while your saving system still doesn't work? Programmers will never give up on a feature, so we need to put them somewhere where we know they'll be safe. The ideas under consideration, for future versions, and even the section on forbidden ideas, will do just that.
The ideas under consideration are features I feel would support the core functionality, but either are not needed or not yet concrete. Some of these features, like the filters, will definitely be added to the spec; all they're waiting on is a statement of exactly how the user will interact with them.
Ideas for future versions are really good ideas that would support the core functionality, but are not essential. These are put on hold until future versions, so we can get a 1.0 release out the door.
Finally, there are the ideas which WILL NOT be put into the product. These are ideas which are really cool, and we don't want to forget, but detract from the core gameplay, or would sink the project. This category is also for ideas other people think are cool and will try and lobby to be added to the spec, yet you think are detrimental to the project.
These three sections are a must have.
To wrap up, let me say this: You need a functional spec, because it is your game. Before any code has been written, before any art has been drawn, before any sound has been recorded, you need to take the nebulous ideas floating around in your head and translate them into concrete rules. Once you have this document you have a much better chance of completing your game.
As an added bonus, you also have a much better chance of getting people to help you! Imagine if you could go to the forums, and instead of saying "I need an experienced coder and iconner and mapper", you could post a link to your document and say "This is what I need done". A programmer will be a lot more willing to work with you if they know, up front, exactly what needs to be done and how much time it should take.
So next time you're tempted to open Dream Maker, even if you're going to work on a project you've already started, take the time, instead, to sit down and start a functional spec. The half hour you spend writing in a human language will save you months of writing computer code.
Copyright © 2015 BYOND. All rights reserved.