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".

Tuesday, March 9, 2010

This blog has moved


This blog is now located at http://tcoztechwire.blogspot.com/.
You will be automatically redirected in 30 seconds, or you may click here.

For feed subscribers, please update your feed subscriptions to
http://tcoztechwire.blogspot.com/feeds/posts/default.

Friday, March 5, 2010

My Comments on Steve Job's attacks on Flash technology: C'mon Steve, it's about money and control.

Recently, Steve Jobs has escalated his war on Flash technology. You can read about it here:

http://gawker.com/5474900/what-steve-jobs-said-during-his-wall-street-journal-ipad-demo

There’s so much contrary info available to me about Steve Jobs’ war on Flash that I can’t find his position credible. It’s amazing that anybody would take it seriously.

I’ve been a Flash dev for a long time. Flash hasn’t crashed my computer in years. Browser now and then, yes, computer, never. And I run three macs, and do all my development on them. Steve is telling a half truth here; if he was being accurate, he would say that POORLY WRITTEN flash apps take down BROWSERS. That is the fact.

This is no less true of a poorly written iPhone app. Go to the forums, bad iPhone apps take down iPhones all the time; memory allocation, lockups, you name it.

Steve Jobs is being dishonest about his motivation for his attack, and it’s obvious to anybody that knows how iPhone content distribution works; this is entirely about control, and money, that’s it. If you allow Flash on the iPad/iPhone, people will be able to write games, audio/video experiences, and deliver them to the iPad, without the deathgrip approval process Apple has over applications (you must submit your app to Apple, and get approval, before distributing to the iPhone via iTunes; Apple gets a distribution fee, AND you have to pay every year to be a registered developer to be allowed to submit apps at all) . Apple won’t make the money on the app distribution, and won’t have to force you to go through the app approval process.

That’s the real issue. I am confident that an army of Flash/Flex devs, and Adobe, as well as any legit third-party evaluation process, would state that there is no technical reason that an iPad can’t support Flash.

It is also interesting that, for video solutions, he points to h.264 video (quicktime), which is a patented and privately licensed technology. And guess who owns it. Sure, cheap now...but when people start depending on it, watch Apple change that for "enterprise content distribution" or some such.

Finally, Steve says Flash is on the way out; that statement, more than any other, I just can't fathom. Flash is in no way dying at all, in fact, as a developer using it for years, I have never seen so much Flash/Flex work. I turn down good work all the time because I’m far too busy. 3d advancements and other useful technologies are allowing Flash to go where it has never gone before.

Apple was heavily vested in Flash technology for years; shortly before the release of the iPhone, they ripped it all off their website; I happened to notice this, and was suspicious of the motivation. A few months later, they announced the app store, and the model for development and distribution; then it became clear to me why you would never see Flash on the iPhone.

Apple can’t control content delivered via Flash.

Folks, people say Microsoft is the evil empire, but one thing for sure, they never tried to control the content you see and use on your devices to the extent Apple is currently enforcing. They should call the device the iCensor.

Me, I’m not getting an iPad. If I buy a device of this nature, I want the entire web experience, not some dumbed-down version Apple is foisting off to enforce control and print more mountains of money. A phone, alright…Flash does take CPU cycles and may not be ideal for a phone (though I don’t have enough info to know this for a fact), and dumbed-down versions of Flash for mobile don’t appeal to me. But there is no excuse for the iPad, unless that device is technically just a big iTouch, in which case, imho, it’s a waste of money. I'll buy a device that doesn't tell me "we don't like it so you can't have it".

Watch out Apple, you're creating a real mud-slinging marketing opportunity for Microsoft here. Windows 7 is on the rise and people are fast forgetting Vista.

Tuesday, February 2, 2010

Flash Builder BUG: Services failing, SWF trying to load crossdomain.xml from localhost:37813?

Oh man this one cost me some time.

I have a swf loading data from some services at IP yadayada. It's working fine, both from the FB IDE, and when I copy the bits to the remote server, pull up a browser, and hit the remote IP.

Then I try it from another machine, same browser, same FP version, same IP address. I see this gobbledy gook:

Warning: Failed to load policy file from http://localhost:37813/crossdomain.xml
*** Security Sandbox Violation ***
Connection to http://localhost:37813/?q=services/amfphp?hostport=[ipommitted]&https=N&id=-1 halted - not permitted from [myswf]

WTF, why, why, why is that request trying to load the crossdomain file from localhost:37813, screwing up everything on all but my dev machine? Yes, I know dev machines aren't the acid test, but I'm not running the project from the IDE, or even the browser the IDE uses, I'm pulling up an "off to the side" browser and hitting the remote address, exactly as I am on any other computer.

I went through all the security settings, found posts directing me time and again to the new meta policy and socket policy documents and white papers: I've read them all, several times in the past, I'm good with Flash security, I KNEW I was doing all this correctly.

So, I abandoned Flash security, assuming I had everything correct. Where else had I seen URLS redirected to localhost:port?

HTTP Sniffers, like Fiddler. They intercept HTTP traffic, channel it to a local port, trace the data, and forward the request along.

Was I running one? No...oh wait, yes.

THE NETWORK MONITOR IN FLASH BUILDER.

IT COMPILES THE REDIRECT INFO INTO YOUR SWF.

So, if you compile your swf with the network monitor active, which you may not realize is the case, you have just told your swf to redirect all traffic to localhost:37813. So you'll deploy it, and guess what? Because no other machine is running the FB network monitor, the calls will fail. GAH.

Turn network monitor off. Recompile your swf. Redeploy. Voila.

GAH. What a pain. Anyway, if you have this problem, hopefully this saves you from the frustrated grumbling and cursing I spent a few hours going through.

As always, thanks for visiting.

Thursday, December 17, 2009

Flash Builder: Spark Skinning Issue to look out for (hopefully they'll fix this)

If you're in the ActionScript world and haven't cracked open the beta of Flash Builder (the latest version of Flex Builder, just rebranded), it's time to hit the Adobe site and pull it down. There's a lot to like about it.


It ain't perfect yet though. Here's a brief post about a couple of things I've discovered that might throw you when you get started.


Spark Skinning

The new Spark components (get ready for the new s: namespace) seem to work great, and have a lot less overhead than the old mx flex ones. For instance, "groups", like s:HGroup and s:VGroup, can be used instead of "boxes", like HBox and VBox. They work the same way, but don't contain logic for scrollbars and such. This somewhat mediates the old Flex issue of nested containers impacting performance. Although you should still always be careful nesting containers, its good to know that, at least to a point, you can be a little more creative about their use without overtly damaging your app's perf. You can also do more with CSS than in the past as far as skinning, fonts, and so forth. Great stuff.


However, it's still in beta, and I stumbled across what appears to be more of an API/OOP design flaw than a bug, but nevertheless still feels like something is broken, so here it is:


When using a Spark List component, you may want to reskin the Scrollbar (let's face it, the default scrollbars are UGLY). To skin the scrollbar, you would implement a new skin class for the part of the scrollbar that you want to alter, then simply apply it to that element of the scrollbar. The easiest way to to this would be to just copy the content of the default skin class, put it in a new class, modify it to suit your needs, then apply it in place of the default one. Note that the Spark documentation says this is the way to go; you shouldn't override or extend skin classes.


However, the default scrollbar skin for the increment and decrement arrows contains an "Arrow" MXML piece. Remember, this is the SKIN class, not the implementation class. Even if I omit the skin class entirely, I would expect the app to still compile and run; a null check would avoid any errors, though you may not see a skin for the scrollbar, or a default system skin would be used; something other than the app completely breaking without any compile-time errors.


You can find the Spark skin classes in [FB Install folder]/sdks/[version]/frameworks/projects/sparkskins/src/mx/skins/spark, which is great; using them as a starting point for skinning you Spark components makes this actually very easy.


Anyway, in those default Arrow classes (the ones I'm interested in are ScrollBarUpButtonSkin, and ScrollBarDownButtonSkin), you'll see this MXML fragment:



<!-- arrow -->
<s:Path horizontalCenter="0" verticalCenter="-1" id="arrow"
data="M 3.5 0.0 L 7.0 7.0 L 0.0 7.0 L 3.5 0.0">
<s:fill>
<s:RadialGradient rotation="90" focalPointRatio="1">
<s:GradientEntry id="arrowFill1" color="0" alpha="0.65" />
<s:GradientEntry id="arrowFill2" color="0" alpha="0.8" />
</s:RadialGradient>
</s:fill>
</s:Path>


Now, I don't want that, because I'm drawing some very custom shape in place of this default arrow. So, I omit that MXML fragment, and replace it with a Graphic object, in which I use the new drawing MXML stuff to create a new arrow.



<s:Graphic width="25" height="20">
<s:Path data="M 0 0
L 25 0
L 25 10
L 12.5 20
L 0 10
L 0 0" >

<s:stroke>
<s:SolidColorStroke color="0x29a094"/>
</s:stroke>

<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="1"/>
<s:GradientEntry color="0x7ac8c5" alpha="1"/>
</s:LinearGradient>
</s:fill>

</s:Path>
</s:Graphic>


After making the new class with the Graphic element instead of the old "arrow" drawing path one, I applied it to my Spark List component and compiled; new errors. I ran the program though, and it crashed right away. The error was that the "arrow" property could not be found, and there was no default value, etc. So, out of curiosity (and the desire to get the app running), I just added a public var, "arrow" : Object, and again compiled without errors. Running it though caused another error, and then another, because "arrowFill1" and "arrowFill2" were not found, no default value, etc.


So, I had to add these three public vars to my custom class to get the app to run.



// don't remove these, they are placeholders for the wonky "arrow" mxml that isn't needed here.
public var arrow : Object = { };
public var arrowFill1 : uint = 0;
public var arrowFill2 : uint = 0;


After that it worked.


To me, this is broken; as long as the skin class is properly made, it shouldn't need to contain ANYTHING in order to run properly, as long as any necessary interfaces are implemented (a well built API should be interface based). Implementation of functional objects should not be a concern of the skin class. But it is; you have to put in those dummy properties to get this to work.


I circulated this find, and the consensus seemed to be that yes, this should be fixed; there's no reason a required visual object should be in a skin class, circumventing compile time errors and crashing the entire app when it tries to instantiate a skin for a scrollbar. Evidently, more hacking away found that this is the case in a number of Spark skins.


Insurmountable? Nah, just add the public properties to satisfy the Spark parent component demand for whatever it's looking for. But it's wonky and, as far as the consensus of the people I referred the error to, should be addressed by Adobe before the product is released, for the sake of elegance if nothing else.


As always, thanks for visiting.

Labels: , , , , , ,

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 sir...here'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 needed...you 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 voila...place 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.

Tuesday, August 11, 2009

(To Unix guy) Yes, it does...Windows Has Symlinks.

This is one really started to irk me lately, so here we go.

Qualifier: I am not a Windows fanboi at all. My primary machines are Macs, with a Windows box for Windows-only games and testing, and a remote one for development (I have two, one Centos, the other Windows Server). However, I am not a Mac fanboi either. The primary reason I own Macs is that in my field, most people work on Macs. Mac is also ruling the roost of UI-think these days, and I'm a UI developer. If and when the wheel turns, depending on the wants and needs of my clients, I will too. The ability to reinvent yourself is what keeps you viable and current; just ask David Bowie or Will I Am.

That said, to all the Unix guys who wave symlinks in the face of the Windows developer:

WINDOWS HAS SYMLINKS. YES IT DOES. THEY ARE CALLED NTFS JUNCTIONS.

I post this because recently, a friend who runs a business got shafted by some PHP developer, who got in over his head, screwed up his site, and suddenly "wasn't available". He got the entire site zipped up and sent it to me. It didn't work when I just dumped it into XAMPP on a Windows dev box I have running; the pages were requesting directories that didn't exist in the file structure I was sent.

I contacted him, and he responded, "what are you running it on", I said, "oh, a Windows box". He said, "you can't do that, the site uses symlinks".

While I understand the "why" of why he did this (easily point at other directories to try other versions), I don't really think it's in the interests of the client (and therefore, isn't a good idea). You can just rename directories to try alternate versions of a codebase. It also defeats the purpose of the whole "can run on anything" mantra; as far as this developer knew, he had tied a basic PHP site to Unix-based OSs, with the thought that, "you shouldn't run Windows". My friend (the business owner) had no knowledge of this decision whatsoever, as far as he knew, PHP ran anywhere, mySQL ran anywhere, the site was portable.

So here's a pro note: don't tie your websites to a particular platform unless you have to, and inform your client if you do, that "you will not be able to move this to Windows", or ".Net is, in practical terms, Windows technology. Your site will not be directly portable, if at all, to Unix/Linux".

Anyway, I responded, "that doesn't matter, Windows has symlinks".

He responded, and I have heard this from people at a particular startup I did some work for not long ago, who considered themselves superior to anybody that touched a Windows machine, "Windows doesn't have symlinks".

And like I said then:

YES IT DOES. THEY ARE CALLED NTFS JUNCTIONS.

So, either get the Windows Server Resource Kit to get the "linkd" tool, or just get the small, free Junction tool that's been around for a few years. If you have either of them though, it's a breeze.

With Junction (which is what I use), it's as easy as:

- Create an empty directory (your "symlink").
- junction c:\path\simlinkname c:\path\actualdirectory.

That's it. There's also commands to inspect directories for symlinks, delete them, and so on.

Note that, as far as I know, symlinks to directories on remote shares are not supported by Windows. This may not be true on the newer server versions, I dunno.

Here's a list to Junction (which I use now instead of moving around the whole Windows Server Resource Kit, which you can look up if you're so inclined):

http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx

Happy Windows symlinking!

Labels: , , ,