Monthly Archives: August 2009

Icebergs

As a developer, I know that awful feeling where you show a client/customer/constituent your work, and they ask you to make tweaks that they consider “easy changes” which for you are “complete architectural redesigns.” A large driver of this is the fact is that they don’t understand the amount of work that goes into building an application. They can’t really. To do so one has to fully understand the application architecture design, building, and coding process. In most cases to understand that you have to be a developer capable of it. If you are a developer capable of it, why are you hiring others? All this leads to the guy or gal in front of you asking you to change “just this little thing.”

People do it because people tend to think anything they don’t know how to do is easy. I think this is because our touch points with each other’s disciplines are so small and shallow. Our work is all icebergs. There is a little that can be seen, but underneath the surface it goes on and on.

What does this have to do with design?

The other day a typography site named Typedia.com launched. I follow a couple of the founders, and thought it was a cool idea. Then I happened to read a blog entry from the guy who designed the logo. (He’s John Langdon by the way, who did the ambigrams for the Dan Brown novel Angels and Demons.) In it he talks about the logo and the process of creating what is essentially a custom font for it.

Look at the logo. Did you have any idea that there were volumes and volumes of thought behind that logo, dating back to the invention of the printing press? I certainly didn’t.

Which leads me to think about the hundreds of fonts on my system (working for Adobe has its perks.) Each one of them contains some measure of this thought. Each of them is an iceberg too.

This leads me to think that every design comp I’ve ever seen is also an iceberg with hours of thought and volumes of reference and knowledge behind it. Makes me wonder about the push back I’ve given.

This does not lead me to say that all of these icebergs mean that I should not criticize other people’s work, or ask for changes. Volumes of content condensed into the wrong logo are still wrong, as John Langdon’s post reveals. It also does not make me naïve enough to think that every comp has had hours put into it, just that there are hours of expertise leading up to it.

It leads me to the thought that we need to be more mindful of the fact that what other people produce is not only what we see, but the accumulation of their expertise. We as developers need to see it when we look at the work of designers. We also need to see it when we look at the work of other developers. Once we do that we just need to go out and convince the rest of the world to look at our work that way. How we do that is a mystery to me, but I suppose it starts with doing it ourselves.

 

Co-working at IndyHall

Today I tried out co-working at Independents Hall. Co-working for those of you who might not know is basically people who don’t have traditional offices working in the same space. It’s for freelancers or independent contractors who tend to work out of their own homes or at their local coffee bar with WIFI. Instead of working alone, they can work with other independents and freelancers in a shared space. You get all of the benefits of having people working around you, the ability to talk to other people with similar drive, and a shared coffee maker.

Though I don’t quite fit that definition, I come kinda close. I travel a lot and when I’m not traveling I’m in my home office. I figured I was close enough.

It wasn’t quite what I was expecting. If you read their website, you get this feeling that people are bumping into each other, figuring out that they have a startup idea that will change the world, and working on it to the betterment of themselves and the world. Um, it’s just a bunch of guys and gals working in the same office, with no real dress code. People occasionally talk. Some people are working together.

What a frickin’ relief. I was afraid I’d get all covered in startup cooties and granola.

It was great. It was really affordable. I had a good conversation. I got a lot of work done. It’s three doors down from a smoke shop.

Assuming I’m allowed back- I was high maintenance with the office manager; which is the only logistical problem I had with the place. After months of getting up, leaving, and coming back to my laptop whenever I want to, I’ve gotten used to not having to call to get myself let back in. I assume that if you become member they give you some sort of code. (And the office manager was very gracious with high maintenance me. )

I recommend it to whoever is on the fence about it.

ColdFusion AIR Synchronization

First, let me just cop to the fact that this post draws a lot from Jayesh Viradiya’s post on this ColdFusion/AIR Offline support. I had to simplify his stuff to wrap my mind around it enough to talk about it. So hats off to Jayesh, he’s done some awesome work here.

I was doing a demo on ColdFusion and AIR integration at the keynote for CFUnited, and I figured I would go into a little more detail here.

First off, to call it “ColdFusion and AIR integration” is to do it a bit of a disservice. What our engineers have accomplished is nothing short of “ORM for AIR.” It handles:

  • Creating and maintaining the SQLite database
  • Saving objects to SQLite without SQL statements
  • Handling relationships:
    • one-to-one
    • one-to-many
    • many-to-one
    • many-to-many
  • Syncing those records back to ColdFusion

So I have a sample application that shows a basic demo of this, without the relationships. Jayesh’s demo has the relationships. I’ve attached the code here, so if you want to look at it, just download the whole thing. Otherwise, let me take you through it. One little note, this stuff was written for ColdFusion 9 Beta. There are some bugs. I’ll point them out where I can, and assure you that the bugs are being worked on.

So let’s start in the ColdFusion. First I define an ORM cfc:


component persistent="true"{
property name="personID" fieldtype="id";
property name="firstName";
property name="lastName";
property name="twitter";

public string function serial(){
return "#This.getFirstName()#|#This.getLastName()#|#This.getTwitter()#|#This.getpersonID()#";
}
}

Pretty straightforward; then I define a corresponding ActionScript class:


package airdemo
{
[Bindable]
[RemoteClass(alias="AIRDemo.person")]
[Entity]
public class Person
{
[Id]
public var personID:int;
public var firstName:String;
public var lastName:String;
public var twitter:String;
}
}

Note the RemoteClass mapping to the CFC on the back end. Now let’s go to the application. I have a simple data grid and form designed to show and edit the details of these person objects. I’ll skip that and go right to the part where I hook up AIR to the ColdFusion server:


private function init():void
{
// Provide Credentials for Server side Connection and CFC
syncmanager = new SyncManager();
syncmanager.cfPort = 80;
syncmanager.cfServer = "centaur.dev";
syncmanager.syncCFC = "AirDemo.personManager";

// THis handler will be called when any COnflict
// occurs while writing back changes on serverside
syncmanager.addEventListener(ConflictEvent.CONFLICT, conflictHandler);

//Kick off the application.
getRemote();

}

This connects this application to the ColdFusion server centaur.dev on port 80 and wires the syncmanager to AIRDemo.personmanager. More on that later. But it also kicks off getRemote which takes care of populating this application with data from the server. So getRemote() fires:


//GET records from BACKEND SERVER
private function getRemote():void{
var token:AsyncToken= syncmanager.fetch("fetch");
token.addResponder(new mx.rpc.Responder(fetchSuccess, fetchFault));
}

Syncmanager.fetch calls the fetch method of the ColdFusion CFC we set as syncmanager.syncCFC above. That method just retrieves the records using ColdFusion ORM.


remote Array function fetch(){
return EntityLoad('person');;
}

In most cases it is successful, in which case fetchSuccess calls createLocalDB:


//CREATE the actual SQLite DB
private function createLocalDB():void{
//Create a pointer to actual SQLite db file
dbFile = File.userDirectory.resolvePath("AirDemo.db");

var sessiontoken:SessionToken =syncmanager.openSession(dbFile,017916);
sessiontoken.addResponder(new mx.rpc.Responder(connectSuccess,connectFault));
}

In most cases that is successful and connectSuccess calls createLocalCacheFromRemote


//PUT records from BACKEND SERVER in SQLite DB
private function createLocalCacheFromRemote():void{
var savetoken:SessionToken = session.saveUpdateCache(pc);
savetoken.addResponder(new mx.rpc.Responder(saveCacheSuccess, savefault));
}

Those three ActionScript functions in concert with the ColdFusion one:

  • Got the data from the ColdFusion server
  • Created a local SQLite database for the data
  • Populated the local SQLite data with that data

Okay, so now I go through the application, update some data, and want to save it back to the SQLite database:


//SAVE to SQLite DB
private function saveLocal():void
{
//Generate person object from form.
var person:Person = convertFormToObject();

//session.saveUpdate saves record to SQLite Database
var savetoken:SessionToken = session.saveUpdate(person);
savetoken.addResponder(new mx.rpc.Responder(saveSuccess, savefault));
}

ConvertFormToObject does exactly what it sounds like, converting values from a form into a Person object, then session.saveUpdate() handles saving the record back to the SQLite store. No SQL required. Then we need to send it off to the ColdFusion server:


//SAVE to BACKEND SERVER
private function saveRemote():void
{
var committoken:SessionToken = session.commit();
committoken.addResponder(new mx.rpc.Responder(commitSuccess, commitFault));
}

That’s it. That transmits all of that changes made in this session to the ColdFusion server, where it is processed:


remote any function sync(required array operations,
required array clientobjects,
array originalobjects = ArrayNew(1)){

var i= 0;
var conflicts = ArrayNew(1);
var conflictcount = 1;

for (i=1; i <= ArrayLen(operations); i++ ){

var operation = operations[i];
var clientobject = clientobjects[i];
var originalobject = originalobjects[i];

if (operation eq "INSERT" ){
var obj = ORMGetSession().merge(clientobject);
EntitySave(obj);
}
else{

if (isinstanceOf(originalobject,"person")){
var serverobject = EntityLoadByPK("person",originalobject.getpersonID());
}
else{
throw "Invalid Object";
}

if (not isdefined('serverobject')){
var text="CONFLICT::SERVER OBJECT NOT FOUND, RECORD MAY BE DELETED ALREADY";
var conflict = New CFIDE.AIR.conflict();
conflict.clientobject = clientobject;
conflict.originalobject = originalobject;
conflict.operation = operation;
conflicts[conflictcount++] = conflict;
continue;
}

var isNotConflict = (originalobject.serial() eq serverobject.serial());
if (isNotConflict){
if (operation eq "UPDATE"){
obj = ORMGetSession().merge(clientobject);
EntitySave(obj);
}
else if (operation eq "DELETE"){
obj = ORMGetSession().merge(originalobject);
EntityDelete(obj);
}
}
else{
var text="is a conflict";
var conflict = New CFIDE.AIR.conflict();
conflict.clientobject = clientobject;
conflict.originalobject = originalobject;
conflict.operation = operation;
conflicts[conflictcount++] = conflict;
continue;
}
}
}
if (conflictcount gt 1){
return conflicts;
}
}
}

So this is a lot of code, but basically it performs the following steps:

  • Check to see if the record is new
    • If so insert it
  • Then check to see if the update is in conflict
    • If not, delete or update accordingly
    • If so, send a conflict back to the AIR client

Now back in the client you have to handle the conflict, in this version of the application, I just replace the client details with the server details:


//OVERWRITE from BACKEND SERVER
public function conflictOverwrite(conflicts:ArrayCollection):void{
var token:SessionToken = session.keepAllServerObjects(conflicts);
token.addResponder(new mx.rpc.Responder(conflictSuccess, conflictFault));
}

Again, one function, session.keepAllServerObjects, handles overwriting everything on the client.

So that is the gist of what I was going to show at CFUnited. The code is attached, (Down at the bottom there is a “download” link) feel free to give it a try and see what you can do with it.

Max 2009 Discount

We have educational/governmental/non-profit pricing for MAX this year. If you qualify as any of these groups, MAX will cost you $995. This is the best rate I’ve seen for MAX tickets to date, so jump on it.

To get the educational pricing, use the code EDU966, as noted on our Educators at MAX site.

To get non-profit or governmental pricing, email questions@max.adobe.com and they will assist you with a promotional code.

DZone Refcard on ColdFusion

DZone released my Refcard on ColdFusion 9 today.

As you may or may not know, DZone Refcardz is a collection of cheat sheets that are designed to give developers a quick jumpstart into a new topic. They’re pretty great – no fluff and lots of content squeezed into a little bit of space.

I’m particularly excited about this as the audience for the DZone is pretty expansive, and cuts over many technology interests, including Flash Platform developers, Java developers, .Net Developers and other web developers. As an evangelist, it’s important for me to show off ColdFusion to people who aren’t already fans. The Refcard and my interview with DZone over the release of the public beta of ColdFusion 9 are part of that ongoing effort.

I’m committed to expanding the ColdFusion community by bringing in .NET, Java, PHP and other web developers who are willing to give ColdFusion a new look. We’re not going to do that by only talking to the ColdFusion community, and this is what reaching out to them looks like. More things in this space are coming down the pike, but I wanted to let all of you know that we’re committed to growing the community, and taking steps to do so.

CFUnited 2009 New Session

Due to some last minute CFUnited speaker withdrawals (unfortunate ones at that) I have picked up another session. So my sessions are as follows:

Thursday

Friday

I’m excited about all of the topics, but I’d like to point out two of them to you.

For Working with MS Office, SharePoint, and Exchange I’m teaming up with Dipanwita Sarkar from the Indian team. It should be great to see the SharePoint features in more detail.

Dipanwita has been working hard on this and on her other session: ColdFusion Builder: Getting Started (Bring Your Laptop). She’d like everyone who’s going to that to try and have ColdFusion 9 Beta and ColdFusion Builder Beta installed ahead of time if you can. They’re going to have a special pre-session workshop to help with that.

The second session I’d like to highlight is new one that got added, Selling Professional Development Techniques at a Resistant Shop. I’ve added a few things to it over the past few months, so if you have seen it before, it’s still much the same content but updated. If you haven’t seen it before, it basically is designed to help you sell all the things you learn at CFUnited to your co-workers when you get back to the office.

I can’t wait to see all of you down at the resort. There will be cigars if anyone is up for them.

 

Scotch on the Road Part Deux

The mainland Europe leg of Scotch on the Road is a go. Adam Lehman, ColdFusion Product Manager, and I are splitting up the dates. We’ll be teaming up with Andy Allan and Kevin McCabe of Fuzzy Orange, Claude Englebert ColdFusion EMEA Specialist, and Serge Jespers Platform Evangelist from Adobe to bring some ColdFusion goodness to the continent.

  • October 19: Munich
  • October 21: Zurich
  • October 23: Milan
  • October 26: Amsterdam
  • October 27: Brussels
  • October 29: London

The best part is it’s free. Yep, no cost, one day sessions in various cities in Europe, completely free. Now you have no excuse to stay at work.

I can’t wait to team back up with Fuzzy Orange, Serge, and Claude for this. I’ll be taking the first week of events in Munich, Zurich, and Milan.

ColdFusion Trivia Friday

In honor of CFUnited next week, I’m running a little Friday giveaway contest.

I will be asking 1 ColdFusion trivia question every 30 minutes on Twitter (@tpryan) starting Friday August 7th from 12:00PM to 2:00PM EDT. Use the Twitter hash tag #CFTFri. This will total 5 questions, and therefore 5 chances at a prize. The first person who gets a particular question right, as determined by my twitter client, gets the question’s prize. Prizes are limited to one prize per person. So if you win one, you cannot win another.

Prizes will be:

  • 4 ColdFusion Rocks t shirts – 12:00, 12:30, 1:00, 1:30
  • 1 set ColdFusion 8 Scotch Glasses (4 glasses in set) – 2:00

After you win, we’ll get in touch with each other via direct message. Then I’ll get your shipping details (not limited to USA), and shirt size.

I’d like to give special thanks to a recent re-addition to the Evangelism team, Ted Patrick. This is a blatant rip off of his contest idea. (But he said I could.)

If for some reason, Twitter is not playing well tomorrow (as it appears to be today), I’ll reschedule for Monday.

Pulling Content out of Word with ColdFusion 9

I had a 1 + 1 = 2 moment the other day. I was fooling around with the ColdFusion’s ability to turn Word docs into PDFs. At first glance it’s pretty simple and straightforward:





Word to PDF is nice to have, but as features go, it’s a pretty small bullet point. Don’t get me wrong, you get fidelity to the original, including fonts, layouts, and images. But it’s still just converting a Word document to a PDF.

That is until you remember that you can pull content out of PDFs now in ColdFusion 9. So now you can do this:




source="#result#"
name="cfref"
/>

This will yield you the content of the original Word document. Now that’s cool.