Tcoz Tech Wire

Discoursing on trends and technologies interesting to Tim Consolazio, sole proprietor of Tcoz Tech Services, specializing in Flash/Flex/Air, iPhone, Facebook, Twitter, and related technologies.

"Technology from an indie software developer's perspective".

Thursday, September 17, 2009

Predictable Irrationality: Project Planning by Reverse Engineering a Concrete End Result

This is one of my greatest challenges as a developer. Everybody thinks they know this already. Almost nobody seems to actually practice it. For the most part, this example doesn't use actual technology project examples, but that's deliberate, because oddly, people don't think real life thinking applies to technology project plans.

Anyway, here we go...a client has an idea for a project; they want this fantabulous application that does this, this and this. They qualify you, and hire you. There you are, ready to look over requirements and wireframes, iterate through them, allocate your resources, get some preliminary milestones approved, and create a draft project plan.

The client hands you a few comps; artist renderings of the end result. "That's what I want".

You're a contractor, so of course, you say "erm...have you considered...". Some internal employee that believes he/she has already foreseen the future is annoyed, but concedes, so they rework the comps. You look it over and say, "hmm...but how about errors and alerts...what about some form of tips or help...what will happen if the user does this..." The designer starts to whine, the client gets tired of hearing you say, "have you considered...", and assigns some internal employee to start pushing you to start dev immediately, believing that because they have shown you a snapshot of the end result, that the plan is ready to go.

I want to throw a chair across the room and shout, "EVEN IF YOU SUCCEED, YOU ARE GOING TO FAIL!".

IMHO, it's why most people are accustomed to failure. They don't work towards visions rationally. They get caught up in working around obstacles and situations that prevent them from following the original plan to the concrete end result they want, so they never get there, and abandon the vision; failure ensues. I see people go through this all the time.

Again, you're probably saying, "This is stupid, it's obvious. You have to be flexible, roll with the punches, redirect as necessary". But like a guy I used to work with at American Express used to say, "in practice, common sense ain't so common."

Here's an example; you want to get to California. Somebody sends you a picture of the state and says, create a budget, figure out the wear and tear on the car, and get to work. Oh and btw, it'd be nice to get some pictures along the way.

You say, "well...", the client says, "there's the state, for god's sake you have a picture of it. My internal guy already planned the route, here it is. Get to work."

Well, ok. The route he gave me is N miles, which means Q wear and tear. Ok's your plan. This is what I'm going to deliver, based on your route. Nice and neat. The client grumbles; it seems more expensive than "his guy" led him to believe, but he accepts the plan. "See? It doesn't have to be so complicated."

Seventy five miles out, there's a detour. It takes you 20 miles out of the way down some other highway. Hey, you're flexible; you redirect as fight around the detour, take some other roads, and get back to your original plan. You speed up a little to make up the time. Not so bad; a little acceptable risk, but we're ok.

Two hundred miles later, you get a blowout. You're stuck on the road, and have to wait 90 minutes for the AAA guy. You get patched up, but now you're behind schedule. So YOU SPEEEEEEEDDD to make up the time. You may get lucky and make it; you are counting on it. You may get a speeding ticket; you decide to "incur the cost", because you believe it's your fault. You may get into an accident because you are proceeding recklessly. You know it's risky, even stupid; you're risking complete failure, even unrelated personal obligation, but somehow, you feel the whip is justified, because you have to get the plan "back on track".

What about the pictures the client wanted? You take them at 110 mph. The requirement is met, but poorly.

From a project perspective, this is analogous to having your developers work day and night, beyond the point of diminishing returns, because something went wrong. You push them until they just don't care anymore and are ready to quit...or do so. You hire another resource as fast as you can, incur the cost, and crack the whip the second he walks through the door.

All in all, your plan is in the shitter. You are now proceeding by the seat of your pants. Everybody is tense. You've told the client, "just a hiccup, we'll get it back on track." You feel somehow it's your job to "protect" or "insulate" the client from these details. You haven't slept in two days and the scar tissue on the developer's backs makes them numb to the whip. They stop responding, so you push harder.

At this point, getting to the Golden Gate Bridge is a tossup, even unlikely. The budget was blown five states ago. You're way behind schedule for arrival. The client is angry. You're mindset is "too far to turn back now".

If you're lucky, miraculously, you find yourself going over the bridge. It all seems worth it; you shrug and say, "the unexpected occurred, so I failed to deliver the plan, but I did get to CA. I'm hardcore!".

Now the client wants you to come back. Believing he learned what you tried to tell him, but still not really listening, he provides two routes this time, and allocates a little money for repairs and some more time to get back based on how long it took you to get to CA with the originally blown plan. Off you go. Again.

Nothing has really changed.

How would I do it?

"Ok, so, California. When would you like to arrive? Let's propose a route, taking into account it may change drastically based on traffic, detours, etc. Ok, here's my route, and the one you proposed. Here's the good and bad. Either way, if nothing goes wrong, it should take this much time, and this much wear and tear. I can't predict the future though, so let's try to get to this milestone 200 miles away. At that time, I'll call you and report on my progress, and along the way, I'll let you know if I think we're going to encounter any issues, and we'll discuss how to deal with them."

Some scenarios as you try to get to that milestone:

- You make it on, or ahead, of time. No change in plans. Good news.
- You make it, but learn of some condition that will enhance, or complicate, the next milestone. You propose a redirect.
- You make it, but are a little behind schedule. You say that, at this point, unless one of the two above conditions occurs, you will be a day late. See below.
- You make it, or did not make it (accident, etc.), and are so drastically behind schedule that you know the only way to "get back on track" is to be reckless, which incurs risk. You propose abandoning driving and getting to the nearest airport. Regarding the pictures, well, the point was to get to CA. We can figure out the pictures later if you want them; maybe I can get them from Flickr. MAYBE YOU JUST DON'T NEED THEM TO GET TO CA.

Read those scenarios again. If you're a gambler that couldn't afford to lose, would you put your money on good news, or bad?

You're now managing the client's expectations every step of the way; you're communicating effectively. You get a sense of completion at the milestone, you never incurred unnecessary risk or abused resources, and you got the client what he needed; you achieved his vision by abandoning the concrete end result. If he tells you to speed recklessly, you say no. Miraculously, he accepts this. Surprisingly, you work to a new milestone, and the client seems satisfied.

It seems so logical, so easy. But I'm telling you for a fact that almost nobody works this way because people are afraid to tell their clients that they are setting themselves up for failure.

So do yourself, and your client a favor. Be a pro. Don't tell the team to run a pattern you know will probably fail. Work with your client to get them to look at Milestone One as opposed to the concrete end result. Ensure that redirects achieve the core of the vision; recognize what is important, and what isn't, to achieving the vision.

If you want to get to CA, get there safely and rationally. It doesn't matter if you take the bridge...unless the bridge is actually where you want to go. Even then, if you planned to go over it from one direction, but ended up coming the other way, does it matter?

If it does...well, go over it and turn around.

As always, thanks for visiting.

Labels: ,

Wednesday, September 9, 2009

Put an image (or whatever) next to any character in a TextField that wraps and is multiline.

Somebody on the Adobe AZFPUG (Arizona Flex Programmer's User Group) asked today, "I have a TextField that is multiline, and has numerous wrapped lines. I want to be able to put an image RIGHT NEXT to the last character. How?"

Most of the responses were along the lines of "get the x loc of the textfield, and get the width, then get the y loc, and the height, then put the image".

That'll always put it to the lower left of the TextField. It won't put it next to the last (or any) character within the TextField.

I've dealt with this before, and was surprised to see that this person was really having a hard time finding a solution. So I gave her one: Here it is.

If you're not familiar with getCharBoundary ( indexOfChar ), look it up. It can save your life. It returns a rectangle that bounds any character you specify in a text field. A rectangle has an x, y, width, height. So you get the rectangle, do the math as below, and your display object.

private function doIt ( ) : void
// can be anything, movieclip, combobox, image, whatever
var img : Image = new Image ( );
img.source = "timprofile.jpg";

addChild ( img );

_txt = new TextField ( );
_txt.x = 100;
_txt.y = 100;
_txt.multiline = true;
_txt.wordWrap = true;
_txt.width = 200;
_txt.height = 200;
_txt.text = "Hello how are you I am fine ok that's very nice thank you ok let's wrap some text I hope this wraps let's wrap it up nice ok";

rawChildren.addChild ( _txt );

var r : Rectangle = _txt.getCharBoundaries ( _txt.text.length - 1 );

img.x = _txt.x + r.x + r.width;
img.y = _txt.y + r.y;


As always, thanks for visiting.