This blog isn't maintained anymore. Check out my current project, an agile/scrum management tool.

Thursday, November 29, 2007

Open Source Software Monetizing schemes

Here's two methods of monetizing open source projects that I've kicked around in my head for a while that I haven't seen anyone do yet.

Ransom Based

Distribute a binary. Accept donations. When a certain threshold of donations is reached, release the software as open source.

This leaves a bad taste in my mouth because it doesn't feel right, but it might be a viable solution for certain types of development. I remember there used to be a couple websites that would let companies describe a project they want and would pay for someone to make an open source version. It's essentially the reverse of that since it lets the developer initiate the project.

Donation as a sale

Many projects out there accept donations. Corporations have a lot of money, but in the corporate world it's often really hard to get a donation approved. But buying stuff is a lot easier! What if open source projects sold a "gold" version of their software that was identical (in content and license) to the open source version. I'd imagine it would be a lot easier for an engineer working in a corporate environment to make a donation by pushing through a PO to purchase software than to figure out how to go through the corporate machine to send out a donation. In fact, I'm sure many organizations would welcome the ease of supporting open source projects that they use through a model like this.

Just a couple random thoughts to think about...


Tuesday, November 27, 2007

Spreadsheet Demo #2 - ComboBox

UPDATE: http://www.rogue-development.com/blog/2008/03/first-public-release-of-my-flex.html

Last night I wanted to see how my component would work with custom editors that weren't just text boxes.

Here's a quick demo of my spreadsheet component with a custom renderer descended from a combo box.  Notice a few things:
  • 1 click on a cell to open, not one click to activate the cell and another to open it.
  • You can keyboard navigate to it, hit the down-arrow, open the list of choices, use the arrows to select one, and then hit enter to select it, just like you should be able to.

Labels: ,

Sunday, November 25, 2007

Spreadsheet Component


I'm working on a spreadsheet like component for AgileAgenda that I might end up turning into a general-purpose flex component at some point.

It has a couple advantages over the Flex DataGrid class including:
  • Focused on data entry instead of data display.
  • Full keyboard navigation
    • Arrow or tab keys to move between cells
    • When editing a cell, arrows move cursor instead of cells
  • "Placeholder" rows.
    • Automatically created as they're needed.
    • Dimmed out rows that aren't in the dataprovider until they're edited.
    • Uses a IFactory to create your value objects on the fly so you get any field validation that your value object implements.
  • Partitions
    • You can partition your data for display any way you like, independent of how it's stored.
    • Each partition can have different default values for fields.
    • A row can be in 1 or more partitions.
    • Expandable/Collapsible
  • Autocompletion
    • Comes standard just by specifying a list of possible values.
  • Custom item renderers/editors
    • Enhanced functionality if your editor implements a special interface, but that isn't required.
Soon I'll be adding:
  • Full sorting of columns (without modifying the underlying data).
  • Multi-cell selection and editing capabilities
    • Copy/Paste multiple cells
    • Clear multiple cells at once
    • etc.
Here's a quick screen cast of what's working so far:

http://rogue-development.com/SpreadsheetDemo.swf

(Edit, changed URL of demo movie since my Jing quota is quickly approaching)

Labels:

Friday, November 23, 2007

ObjectHandles - 25,000 Downloads!?!

ObjectHandles, the library to allow user movement & resizing of components that I started 6 months or so ago has somehow gotten over 25,000 downloads!  I guess it was something that people really wanted.

I just started a new wiki page to post links to projects using this component.  If you are using it, stop by and leave a comment there and I'll put the link in the page.  I'm really interested to see ways people are using this.

Thursday, November 22, 2007

New ObjectHandles Build

I posted a new ObjectHandles build yesterday.  It fixes a couple bugs and integrates some patches people have sent me including:

1) Graphical handle support
2) Fixed aspect ratio support
3) Ability to detect transparency & clicks 

There will likely be another build in the next week to integrate another patch and fix a few a performance issue.

Labels: , ,

Wednesday, November 21, 2007

Flex 3 Anchoring

Adobe has changed the anchor UI in FlexBuilder 3 and I've hated it since the first time I saw it. But I wanted to give it some time to see if I grew to like it, maybe I just didn't like the change.

Turns out time didn't help, I still hate it.

Consider this one more rant about it. It takes too much mouse activity to make it happen. It's tedious and those frigging guide lines are always in the way. I'll be editing constraints in code for now on.

Monday, November 19, 2007

XML Facade instead of value objects?

I have a project I'm working on where it'd be great if older versions of the software preserved information in the XML file format that it didn't understand. For example, imagine if Version 1 (V1) of the software had this for a file format:

<data>
<value>1</value>
</data>

Now imagine if V2 of the file added an attribute

<data>
<value type="number">1</value>
</data>

It'd be great if you opened that second file with the V1 software and then saved it again, it would preserve the stuff it didn't understand. Unfortunately that's not how I usually write my value objects. Usually I do something like:


public class ValueObject
{
public var value:Number;
public static function fromXML( xml:XML ) : ValueObject
{
var v:ValueObject = new ValueObject();
v.value = xml.value;
}

public function toXML( ) : XML
{
var xml:XML = <data>;
xml.value = value;
return xml;
}
}


As you can see, anything in the file that it doesn't understand is lost. But what if we followed a facade pattern for our data objects and did something more like this:


public class ValueObject
{
protected var source:XML;

public static function fromXML( xml:XML ) : ValueObject
{
v.source = xml;
}

public function toXML() : XML
{
return source;
}

public function get value() : Number {return source.value;}
public function set value(val:Number) : void {source.value = val;}
}


They both have the exact same API, but the second one will preserve XML attributes (or even nodes) that it doesn't understand.

What about AMF based projects, especially when passing rich objects with a Red5 server? I know there's a pretty seamless mechanism in place if properties aren't known, but how do you get those unknown properties back to the server?

What other solutions or best-practices do other people follow for solving this issue?

Labels: , , ,

Sunday, November 18, 2007

Beta AIR apps & commercial releases? + Spreadsheet Component

This past weekend I decided to hold off the 1.0 commercial release of AgileAgenda until the AIR stuff is finalized. Seemed like a pretty easy decision to make since I'd hate to screw over customers with an expiring AIR beta or something radically changing and breaking some important feature. Plus it just felt wrong to release an app that runs on a beta runtime.

Any other commercial AIR apps out there? What are you guys planning? I'm curious if anyone decided the earlier release date was worth the risk.

And plus, this gives me more time to work on the application. I started work on a "spreadsheet" component to replace the datagrid in my task-editor. I really hate the datagrid and it's limitations so it'll be interesting to see if I can do better. I think I can since the datagrid was really hampered by two conflicting goals.  The desire to make it easy to use, and the desire to make it powerful. Some features I want to put in:

  • Ability to have partially entered records that don't get added to your underlying datasource until they're "valid".
  • Copy, Paste, and delete across rows, columns, etc.
  • A hierarchy of data along with collapsible headings. (Check out flexlib if you just need this feature)
  • More Intelligently create item renderers and pass them more information about what's going on.
  • Let item editors be bigger than the cell they live in.
  • Better keyboard navigation.

Didn't mean for this post to turn into a description of the new component, but I guess it did. Time to update the title :)

Saturday, November 17, 2007

Website Update

I just rolled out the latest update to AgileAgenda.com, I like it a lot better now it feels a bit more professional.

Tuesday, November 13, 2007

I love my job

Yesterday I found another reason on why I work in a really great place.

We have a product, our biggest product. Makes us tons of money. We moved into the "Only fix critical showstopper bugs" mode about a month ago as we near another release. We did that for many good reasons including resource availability, risk of fixes causing regressions, and a general desire to get more real-world feedback to decide what we think is broken vs. what customers think is broken.

Yesterday we found out there might be an additional build cycle to fix a problem with another team's component. We also found another bug in our stuff. The immediate response from everyone was "Well, if there is another build lets fix this bug."

And we sat and talked about what would it take to fix it, the risks involved. But then I asked a simple question.

"Why does it matter if there is another build or not to fix this?"

After a bit of discussion it turned out the answer was something like

"It's not important enough to cause a new build cycle."

So my next question was

"Doesn't that make this a non-critical non-showstopper bug?"

And the answer was "yes". A bit more discussion, and now we're not fixing the bug this time around. It's takes an amazing amount of discipline to choose not to fix a bug because you have a policy saying you won't. Especially when that policy is there for a good reason.

It's one of the reasons why we're not constantly running around in a panic like some of my friends at other software companies are.

Before we sound like a mechanical robot always following policy to the letter I'd like to point out that we do regularly deviate from policy, but it's always after a discussion and a "good reason" to do so. Most of the time I agree it's a good reason.

I didn't mean for this post to turn out this way, but I might as well mention it. We're hiring if you're in the Boston area.

We have 2 engineering positions open that are in that link above.

We also have a few "technical producer" positions open. It's a hard job to define but I guess we're really just looking for smart people that understand how software should work. Do you know when a radio button vs. a checkbox is appropriate and how to use them to create a great UI? Can you think through a set of data and decide what types of reports might be useful to users? In the job, you'd be designing software, writing specs, and have a general knowledge of what's supposed to happen. You'd work with QA to decide what's a bug worth fixing and you'd work with engineering to find cheaper ways of implementing features. It's not a programming job (but in one of the three positions it would be nice if you did know some), and it's not a design job (but being able to sketch a UI for a graphic designer to work up would be nice). And it's not really a management job either. If you're interested in that shoot me a resume and I'll try to find the official job description and forward your resume on to people who want them.

After that long job description this blog post really ended up being an ad, huh? Oh well.

Friday, November 09, 2007

Pagerank? Neat!

My websites have always scored a 0 on the Google pagerank-o-meter. Today I noticed they don't anymore.


The home page url is a 6/10
Agile Agenda scored a 7/10
The blog URL is a whopping 8/10

That's neat stuff.

Thursday, November 08, 2007

FB3 Beta expiration extended?



Yesterday my FB3 Beta 2 install said it expired in 13 days. Today it says 59. I wonder if it was extended somehow and if that means anything about the release date.

Wednesday, November 07, 2007

GMail upgrade

My GMail account got the version upgrade today. One feature I haven't seen reported anywhere else:





I sign up for mailing lists with alternate email addresses that get forwarded to my GMail account. Before, whenever sending mail to those lists I'd have to change my "to" email. Now, I can just reply and it works. Yay.

Monday, November 05, 2007

Want to work with me?

The company I work for is hiring. If you email me your resume/cover letter I'll be happy to forward it on.

We're just west of Boston and all-in-all, it's a pretty great place to work.


Senior Software Engineer Needed at Exciting Educational Software Company

Tom Snyder Productions, developer of innovative educational software products, is seeking an experienced software engineer to architect and code exciting new applications. The ideal candidate for this hands-on position has:

• Experience developing commercial software
• Experience designing and coding user interfaces using GUI
frameworks
• Excellent object-oriented design skills in Java
• Exposure to client-server application development
• Experience with or desire to learn ActionScript 3 and Flex 3
• Shrewd problem-solving skills
• Interest and ability in math

• Interest in developing with the latest desktop and Internet technologies, including Adobe Flex/Flash/AIR
• Desire to work as part of an efficient, agile software development
organization
• A great sense of humor, and interest in playful software
• Enthusiasm about education

This position offers the tremendous satisfaction of contributing
directly to the lives of young people by delivering extraordinary
learning products into their classrooms.

Tom Snyder Productions, a Scholastic company, is the developer and publisher of award-winning educational software products for K-12 classrooms. We offer a vibrant and friendly work atmosphere focused on making a difference in the lives of students and teachers.

This is a long-term contract that would last at least 1 year.
Compensation is based on experience.

Job Qualifications/Requirements
• Bachelors degree or equivalent work experience
• At least 2 years of experience in a commercial software development
environment

Typed Actionscript Arrays? Yay!

I saw it over here... http://aralbalkan.com/1072

Seems the next player might have typed arrays?

That was #10 on my "Top 10 Flash/Flex requests" Whooohooo! 9 more to go :)

Labels:

Sunday, November 04, 2007

Slow Flex Builder compile and refresh solution - Modules

For the past month I've been plagued with up to three minute compile times on Flex Builder 3 Beta 2. I've also been plagued with long several minute waits of "Refresing bin/".

Last week I solved the issue for one of my projects and prevented it from happening to another.

Apparently embedding graphics causes a performance hit in compiling, refreshing directories, and even just before launching. So if you have a hundred or so of these:

<mx:Button icon="@Embed(...)" />

You'll be in a world of pain. The easiest solution is to move those embed calls into your style sheet and then compile your style sheet as a module.

Here's how to make a style sheet module:

1) Create a new MXML module (file->new->flex->MXML module)
2) Add your stylesheet reference to that.


<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="0" height="0"
creationComplete="trace('iconsloaded')">
<mx:Style source="style.css" />
</mx:Module>

3) Next, remove the reference to your style sheet from your main application.
4) Now, in your main MXML or AS file add some code to load your module.

protected var styleLoader:ModuleLoader;
protected function init() : void
{
styleLoader = new ModuleLoader();
styleLoader.addEventListener(ModuleEvent.READY, onModuleLoad );
styleLoader.addEventListener(ModuleEvent.ERROR, onModuleError );
styleLoader.url = "IconsModule.swf";
styleLoader.loadModule();
}
protected function onModuleLoad( e:ModuleEvent ) : void
{
maximize();
var mainApp:MainApplication = new MainApplication();
mainApp.percentHeight = 100;
mainApp.percentWidth = 100;
addChild(mainApp);
}

protected function onModuleError(e : ModuleEvent ) : void
{
Alert.show("Could not load module IconsModule.swf","Error",Alert.OK );
}

You can see there that I intialize my main application component after the module has loaded. I didn't have to do this in a Flex app, but in my AIR app that component wouldn't get all of the new styles if created before the module was loaded.

Option 2

Sometimes, it wasn't practical for me to put the embedded graphic in a stylesheet. In those cases I:

1) Made an interface listing all the embedded graphics

public interface MyGraphicsModule
{
// Bindable tags are there purely to suppress warnings,
// these properties never change after startup.
[Bindable(event="moduleChanged")] function get addIcon() : Class;
...
}

2) Make a class that implements that interface and extends ModuleBase, also embed the graphics in there.

public class MyGraphics extends ModuleBase implements TimeLinerGraphicsModule
{
[Embed(source="/art/toolbars/add.png")]
protected var _addIcon:Class;
public function get addIcon() : Class { return _addIcon; }

...
}
NEVER import or otherwise use this class into your application. The goal is to keep it completely separate.

3) Create a module manager class

public class MyModules
{
[Bindable] public static var graphics:MyGraphicsModule;
}


4) Set MyGraphics to be a module that gets built in your Project->Properties->Flex Modules settings.

5) Load your module somewhere at startup

public function loadModules() : void
{
graphicsModuleLoader = new ModuleLoader();
graphicsModuleLoader.addEventListener(ModuleEvent.READY, onModuleLoaded );
graphicsModuleLoader.addEventListener(ModuleEvent.ERROR, onModuleLoadFailure );
graphicsModuleLoader.url = "MyGraphics.swf";
graphicsModuleLoader.loadModule();
}

protected function onModuleLoaded( event:ModuleEvent ) : void
{
if( event.target == graphicsModuleLoader )
{
var o:Object = event.module.factory.create();
MyModules.graphics = event.module.factory.create() as MyGraphicsModule;
}
}

6) Find the spot in your code that used that icon and replace it

So this:

[Embed(source="/art/icons/addIcon.png")]
public var addIcon:Class;


Would become this:

public var addIcon:Class = MyModules.graphics.addIcon;


This all seems like a pretty tedius job to do, but I ended up writing a perl script to scour the source tree, find all the references, and replace them for me. Unfortunately I did that script as part of my day-job and can't share it with everyone right now. I'll ask for permission on Monday.

The end result was we went from a 3.5 minute wait from saving a code change to executing the application to a 20 second wait. Not too shabby considering the size of the codebase we have.

Labels: ,