So how do you write Flex Builder Tracer Bullets knowing that Flex can be a RAD tool and Tracer Bullets are good to do? I have provided two lists, one technical and the other esoteric, that you can follow to hopefully build your Flex applications a little faster via Tracer Bullets. Here are the two lists:
Technicals
EsotericsUse States, Don't Use Transitions
A lot of screens have specific states. Some have none. The majority, do, though. It's quicker to make one LoginForm with three states than three different MXML views that make up a LoginForm. Quicker to edit, too. Flex Builder can show you those states visually, and automatically write the code for you to add and remove controls as well as changing their properties when the state changes. It's always easiest to start with "main_state", and go from there. If you don't, you may later have to copy and paste the MXML you've already written into AddChild tags individually, which are themselves in state tags. Total pain. Do it right the first time.
Transitions, the animated changes between states, add a lot and make the user's eye-focus putty in your hands. Don't do it yet, though. Wait until you've gotten direction on your appliation before you start directing the user's attention. Transitions are probably the most volatile code in your application, and are also the most subjective. Finally, they cause unexpected changes later when you start throwing data at components that causes their state to change (like custom item renderers, for example).
Define clear states for each View (component), and build them using Flex Builder. It's okay to hand type MXML as well.
Write Strongly Typed ValueObjects Based on the Client's Data Needs
Understand the data you have, as a client developer, early. Whether it's coming from your server team, the client's server team, or both, understand what you are going to be able to represent that data model in a strongly type set of classes. These do not need to match the server, and new ones can be created specifically to make GUI development easier, including properties. Getting these done allows you to be build Views (components) that actually have accurate GUI controls on them to represent the data. No VOs, and your just guessing. VOs give your GUI design direction, and give it purpose.
If there is contention in the VOs, you have a communication problem. Solve it, learn the nomenclature, get the lingo down. Collectively agree with all parties involved to have one name for everything. While some developers will say two, "We call it an asset ID, but the customers call it an item ID," you're just making it more confusing for you in meetings, e-mails, and IMs. Bad communication will sabotage any project, and clear data is the key.
If they are strongly typed, when you decided to refactor, you'll get compiler errors in Flex Builder that make it easy to quickly change names in places that your global find and replace didn't catch (or if you were just too paranoid to do so, by hand). This way, your application is resilient to change... and it's not even really an application yet.
Build Workflows, Then Build Use Cases
A task that the user needs to accomplish is solved by an effective workflow. A workflow is the way a user accomplishes that task by being guided or "led" via the user interface. These are the most important parts of an application and need to be nailed down first. They are also the first cement to dry when coding your application (meaning hard to change later without drastic consequences) so it's best to really think these out based on sales/client dialogues. More is better. If you have more than one idea to make an interface that allows a user to create a widget, go for it. If it's up to your information architect or interaction designer, let her/him know in no uncertain terms the clock is ticking.
Once you get a workflow down, "The user is shown a list of their savings plans. They can then interact with these savings plans," it's now time to build use cases around them. One is the user needing to upload a file, and another is the user needing to be able to filter visible data. Use cases are things the user needs to do. They usually collectively make up the task the user needs to accomplish. Sometimes, they can be task in and of themselves. The point here is to ensure you have a solid workflow first, then start working on satisfying your use cases.
Both should be put in builds and thrown at your client with abandon. It's okay to walk them through it in guided demos; this is brainstorming, not user testing. This is how your application will effectively work, so make sure your clients can do what they need to do and can see what they need to see.
Use Copious Amounts of Tagged Builds in Subversion (or Whatever Source Control You Use)
If you get a working build with specific functionality, make a tagged build in Subversion. If you are not using Subversion, mark the current build in your repository with a special label (in CVS), or some other verbose comment with an accepted convention so you can find that exact build of code later. No source control? ...just make a copy of the code.
This way, if you or the client wants to refer to an older example, you have the item on ice, and can thaw it in minutes, ready for any meeting.
Componetize Sections
This has less to do with OOP and more to do with MXML readability. Because FlexBuilder is nice in that the Design View will write all the code for you via dragging and dropping controls on your forms, it doesn't have that human touch. So, even if you don't format it by hand, you'll still end up with a ton of MXML tags spewed out over hundreds of lines if you build an entire application in one MXML file. The first pure MXML application I ever saw was a pure MXML RSS Reader posted on Flexcoders. While I respected MXML's power, I couldn't read it.
If you have a big form, put it in a component. That way, 30 lines of MXML becomes "". Omg, 1 line of meaningful code... I can read that at lightning speed! Furthermore, if you hold Control (Command on Mac), you can then click on "UserForm" as a hyperlink, and open the file in question. Supa-fast!
Use Canvas First, Panel Later
While Panel gives you a nice container for the mini-components of your application, they merely serve as pretty-looking trappings for your lack of requirements insecurity. Use Canvas, set horizontal and vertical scroll policies to off, and let it be raw. You need to see the gaping holes in your UI, not hide them in pretty chrome.
Make Builds Easy to See
The point of builds is to get client feedback, and get it early with real software. If the client can't see the software iteration, they'll question "this whole 'Agile' thing." Don't send EXEs over e-mail, nor SWFs. Find a reliable FTP site, upload it, and run it. This is easiest if you don't have any local file dependencies, the SWF makes no data calls (locally or externally), and doesn't require any weird arse things to make it run ("Oh... well, let me reset my host file to be localhost, and then reploy the war file...". What? Dude, just upload the SWF with the accompanying HTML file. If you can't do that, you're not writing a Tracer Bullet, but instead a real application build that wasn't meant to be agile.
If the sales person/client can't see the SWF, neither will your users. If you don't want to deal with Flash Player install issues, don't do Flex development. Once you get it out of the way, you can always depend on your salesperson/client being able to see your latest build from there.
Use Fake Data from Real ValueObjects
A great way to point out immediate problems, and make your application feels more real, is to throw fake data at it in the form of ValueObjects populated with data. Obviously, you may be way ahead of the server team (yours or the client), so it helps to have factory methods: functions that can generate a bunch of fake data for you quickly. You can then throw this at the GUI time and time again to test something. Pain in the neck to write, but you'll use them a tons afterwards.
Furthermore, this ties in really well with the "make builds easy to see." Instead of praying that your database call works while the client is viewing your SWF, or if the back-end guys will have their code done by the meeting, you instead don't have to worry about it; it's embedded in the SWF and will work even if the Internet connection suddenly dies (after they've downloaded the SWF).
For Cairngorm, a technique I learned from Darron Schall was using "Mock Commands". You make two Command classes: one for real data that may use a Delegate to make a call to the server, and one that just gets fake data from a Factory class and has a timer to simulate a delay. That way, you just change one line of code in your Controller class to switch to fake-data mode.
Put Event Handlers in Script Tag, Not in MXML
The thing that'll change the most as you hop around files modifying GUI stuff is your MXML. Since most MXML is for showing GUI controls, it'll be volatile from the get-go. Putting code there is just asking for it to get in the way, and maybe even get waxed. So, instead, have your Buttons for example call a function in your Script tag for their click handler instead of do things directly in the MXML. That way, you can even delete the MXML, replace it, and then easily wire it up again.
Find a Friend in Sales (or a Stakeholder at Your Client)
Sales can go either way. They can be a developer's worst enemy, or you're biggest fan base. I prefer the latter. I've been in too many situations where sales sold something that was impossible and I had to make the impossible possible. AKA, "Flash Developers at Design Agencies."
The first thing to do is find out who in sales (assuming just one individual) is interacting with the client, and basically catering the project to their needs. Start up a dialogue with this individual, assuming your project manager doesn't mind, and get to know the client. You may wish you hadn't, but do it anyway. Learn the needs that sales is trying to satisfy by using your code as a conduit. When they start asking for specific functionalities, you'll know why, and be more informed in suggesting ideas, changes, or options.
The ideas are cool because sales usually perceives engineering being "fun governors"; depending on the organization. The last thing they expect is more things for the developer to do coming from the developer. The changes are good because as an engineer, you know how hard something will be to make, how it may work differently in practice, or know the ramifications of a design path, whereas sales might not. Rather than saying no, you can make an informed suggestion about how to get the result sales is looking for. This may seem like something you can do in a meeting, but trust me, it's tons easier when you already have an established rapport with the individual, and almost give the suggestion in passing, almost like you and the sales guy have already got it all planned out.
Finally, options are key here. Being successful at software is the middle ground between doing everything sales wants, and coding just enough to get it solid and working. Enough flair to make the sale, enough OOP to ensure it doesn't blow up. Combined, you win. A lot of times, you as a developer may not know what that balance is. The easiest way I've found is to put the ball back in sales or management's court. If they ask for five things, you spec them out, give time estimations with risk assessments, and any additional optional ways to implement certain features in increments. Giving sales options is way better than ultimatums. It's important that your time estimations for your articulated options with possible incremental milestones are valid. You need to be sincere, honest, and thorough. If it was easy, they wouldn't call it "work".
Naturally becoming friends with the client is dangerous. It's all fun and games until business gets involved. That doesn't mean you still can't build up a rapport to better communicate with the client, and thus understand where they are coming from. I've seen a lot of managers in my time offer to shield me from meetings. If the meeting is with the client, I highly recommend you lower shields, and go. Even if you don't converse in a dialogue, you can still listen.
Write E-mails to Stakeholders (Sales/Client) Who Ask a Question That Can Be Answered
When
you are in the process of figuring things out, it's really easy to give
that laid back, relaxed feeling others in conversation. The
no-pretense, "What do you think?". Don't ask open ended, non-focused
questions like that to stake-holders. Be direct, and know the type of
feedback you want before hand. If you do, 1 of 2 things will happen,
both of which are good. Either the salesperson/client will answer your
question in written form so you can refer to it later and thus continue
working on your GUI, or they'll have no clue, in which case you can
propose some ideas and look straight pimpin' (really smart and capable).
Recognize an Opportunity and Take It
If
your sales/client has no clue what any form of Agile is, or what a
"build" is... find a way to educate them. That is, find an appropriate
time and place to introduce the concepts. Don't start ranting about
Agile Development on a sales call for example. Instead, if you have a
question about how a certain section works on a design comp the client
sent you, use that as an opportunity to send them 2 builds, and choose
the one they like, or perhaps choose a different one. If they respond
positively (or not negatively), boom, you win. You just set the
expectation you can send them working prototypes to play with. Suddenly
they'll be hip to the notion you're sending them working software to
play with that is representative of what they'll actually be using...
and that's a pretty accurate assumption on their part. Their shaping of
it also ensures you're never wrong because you're basically doing what
they tell you to do. Obviously, famous last words for a programmer.
Either way, if your the IA/ID or not, you can also use this opportunity
to suggest ideas, again giving yourself an opportunity at least appear
intelligent.
If there is a client phone call/meeting, and you have the opportunity to attend, do so. If it is appropriate, start a dialogue to challenge your assumptions about their comments to the recent builds you sent them. Engage with them (and/or sales) in the process.
Use a Phone, Not E-mail or IM
If
you're unsure about something, and you have access to sales, go talk to
them in person. Make sure you brushed & flossed first, obviously.
If they are unavailable, send them an email. If they are remote, call
them, and then only email if they aren't around and don't return phone
calls. In person dialogue is ideal, whereas phone voice dialogue is 2nd
best. Email and IM are not the best form of communication, and
communication is the most important thing in a software project. Use
the best kind you can to ensure success.
Caveats and Gotchas
There
are some caveats and gotchas. The more time your team is writing tracer
bullets, the less time they are moving forward with traditional visible
results. The Agile crew would argue that it is better to spend four
hours on two ideas, allowing the client to pick one they like as
opposed to spending one week on requirements and then two weeks on
development for an implementation the client won't like, which then
ends up being another two weeks to code to the new idea. Even two weeks
of bouncing ideas with near production code is better than two weeks of
"coding off a spec"... well, unless you're doing government work. It's
hard for some to see the value in writing code that has fake data, and
an ever changing interface, seeing the same things in different ways
without seeing in their eyes tangible progress on milestones. My retort
is they can't prove their milestones are accurate without the client
having some form of involvement in confirming those milestones were met
without allowing the client to play with a build that shows that
milestone in action.
Regardless, it's hard to argue with a Subversion log that says "everything under the View's folder has changed a lot the last week, but everything in the Cairngorm business, command, and events folder has not... what exactly HAVE you accomplished this week? Can you name one requested feature you've completed?". Valid question, and one that management & sales need to manage; IA/ID & developers can help, but ultimately they aren't accountable for resource management. Look at it this way: You'll either be re-coding this at beginning more quickly with less stress using a series of tracer bullets as opposed to slowly at the end with less malleable code under more stress. Use that fact to empower sales. Take the initiative.
If you don't have leadership approval, it won't work. If your manager looks at you funny when you send a "half finished application" the client, you're already in deep trouble.
If the client doesn't care, you'll really need to leverage your sales rapport. You'll need to educate the client how software works, and that is extremely hard... but fun. If you don't, they'll just expect it to be "done and finished by X date". That's not how things work in the real world and they need to realize no matter how much money they spend, they can't change that. It's in their best interest to get a good feeling with the software early because it's easier to change early, harder to change later. If you get those feelings early on, most changes later won't be so drastic as completely changing workflows.
Regarding MXML, I'm a big fan of writing my components in all ActionScript. That way, I can re-use them since I have lower level control and can make them really flexible. Again, Flex Builder won't render these unless you convert them to a SWC (via a Flex Library project for example), so save the uber-OOP for later. If you stick with pure MXML, the tool will work well, and you won't be fighting it to adopt your best practices. If you have a lot of members on your team, this is also something you can throw at other developers to handle, even junior ones. They can cut their teeth on making a reusable component while you continually define the app via multiple iterations.
A couple notes on branches and prototypes. First, I'm not a big fan of using branches for one Flex Dev to make some design iterations while the rest of the team "moves forward". The Flex Dev(s) doing the design iterations should be in the real code. If the rest of the team has qualms with this, you'll need to setup an easier way for them to test, whether by writing formal/informal unit testing for them on GUI & non-GUI code. For example, one of the benefits of Cairngorm is that it allows multiple developers to work in tandem. One strategy is to have multiple developers handling all Events, Commands, Factory, ValueObject, and Business Delegate code. This leave the Views in the hands of whatever developer(s) handling building the tracer bullets to show sales/the client. The rest of the team can either use the latest build in source control to throw data at and see what happens, and just comment out the actual Cairngorm Event dispatching when they check the code in, but I've found it's easier to just make informal test cases; MXML applications that test your whole Cairngorm use case setup. A la, you build a simple View with a GUI control data bound to the Model, dispatch an event, and see if it works.
Regarding prototypes, for larger projects I think these are more the than justifiable. Throw away code is quicker to write than tracer bullets, and it's always good to play with some code ideas before committing more rigorous practices to it before you know the idea will actually fly (strong-typing, encapsulation, etc.). There comes a point though where you should start leveraging the code you are writing in a good base, and really put the code to the test in early builds to see if she holds up.
Finally, being intimately familiar with Flex Builder helps. I think I'm pretty adept at it, and I'd say that significantly contributes to my ability to quickly modify code without making it spaghetti. My experiences in Director and Flash have contributed to my ability to fake a lot of interactions for the sake of communicating a point. Finally, using OOP, encapsulation, and strongly-typed code to get the tool to help you find errors are all ways to write flexible code. While the temptation is to not even use strong-typing, and use a procedural approach, you'll spend too much time trying different ideas because you can't share code easily. Remember, it's ok to do this stuff on paper or your favorite UML tool first. I just use paper, personally and plaster comps on walls in front of my desk. Now, that experience doesn't just happen over night. Regardless, I was responding to bi-weekly changes on software projects at my first job of which I didn't know OOP or how to write classes, nor did I know what design patterns were. I didn't even know how to return a value from a function (I just modified global values instead). Yet, I found a way, so you can too.
Conclusion