I’m working on a project that requires dynamic charts and graphs. I took another look at Google Charts today, and it didn’t take long to create an interface with MV BASIC. Now I can easily create bar charts, and I’ll soon extend this to support lots of other types like pie charts, line graphs, and candlestick charts. So now do I keep this to myself? Sell it? Open source it? *sigh* Here we go again.
Creating a simple bar chart doesn’t require much code. The Google Chart API is well documented and has a nice Getting Started introduction. Someone can easily hardcode a set of parameters that conform to the spec. Figuring out how to send those parameters to Google would be a trick for a lot of people. Figuring out what to do with the return data would be another trick. But after those three things are worked out, anyone can hand-code their own chart.
It takes a little more effort to create a framework that makes it easy for someone else to create new charts, and understand and maintain existing code. Some people consider cryptic code like PCL or f-correlatives to be a guarantee for job security, but I like to write code that I can pass on to others – especially clients. As an example, here is some of the code I’m now using to create a bar chart:
INCLUDE GCHART.INCLUDE GC.PARAM = C.INIT CALL GCHART GC.PARAM = C.TYPE GC.DETAIL = C.BAR:C.VERTICAL:C.GROUPED CALL GCHART GC.PARAM = C.CHART.SIZE GC.DETAIL = "" GC.DETAIL<C.P.WIDTH> = 500 GC.DETAIL<C.P.HEIGHT> = 400 CALL GCHART
Even without comments, anyone should be able to understand that. The mystery is:
– What are GC.PARAM and GC.DETAIL?
– What is GCHART?
– What are C.INIT, C.TYPE, etc?
To the first question, GC.PARAM identifies what part of the chart I’m working on. In this example we see I’m initializing a new chart, then setting the type as a bar chart, then setting the size of the chart. The pattern is : Set GC.PARAM, Set GC.DETAIL, Call GCHART … repeat as required.
To the second question, GCHART is just a routine that parses GC.DETAIL depending on the GC.PARAM, and assembles all of the parameters into a structured record which is later passed to Google.
To the last question, I created the GCHART.INCLUDE item with a bunch of EQUATE lines to define constants. I set the chart size using defined attributes for Width and Height, but I could easily have just hardcoded GC.DETAIL=”500×400″, and GCHART would still be able to give Google what it needs to get the chart size right. However, by using Equates I limit the chances of passing invalid data to Google. If I accidentally hardcode GC.DETAIL=”500y400″, Google will return an error. But if I set the Width and Height as I did above, my chance for making that mistake is diminished.
The above describes the nature of most of the products I’ve created for MV market, including NebulaXLite for creating Excel workbooks, NebulaManager for Outlook contacts and appointments, and NebulaMail for sending and receiving email. The details of the implementation are hidden (the details of exactly how Outlook, Excel, Email, and Google work) so that developers can focus on what they want to do, rather than on how it’s done internally.
With NebulaXLite, developers build arrays, and when they’re done with the whole thing they pass it to NEBULAXLITE.BUILD, which generates the Excel workbook. But with GCHART I’m passing instructions one at a time. That’s just the way I wrote it and another version in the future might offer the option to work either way.
Notice that when I’m setting GC.PARAM = C.TYPE, that GC.DETAIL gets set to C.BAR:C.VERTICAL:C.GROUPED. All that does is to create the string “bvg”, but while GC.DETAIL=”bvg” means nothing to the next poor developer looking at my code, the constants are readable, and someone can easily change the code with constants to C.BAR:C.HORIZONTAL:C.GROUPED. Now you should be able to understand what that means, where you’d have to think a moment what “bhg” means. Again, this is why I created the constants.
Some developers might prefer that code to look like this:
GC.DETAIL<C.P.TYPE> = C.BAR GC.DETAIL<C.P.ORIENTATION> = C.HORIZONTAL GC.DETAIL<C.P.LAYOUT> = C.GROUPED
That structure is similar to what I did with chart Width and Height. I can easily require anyone who specifies the chart size to concatenate WIDTH : “x” : HEIGHT, but that exposes how the underlying mechanisms work. A developer using a higher-level interface like this should only know about the data (about what (s)he wants to do) and not about the syntax of the underlying protocol. To allow for the construction above, assigning C.BAR and the other values to defined attributes, the GCHART.INCLUDE program needs to have those constants added, and the GCHART program needs to be enhanced to process those attributes. This would be a typical kind of enhancement that needs to be made to allow different developers to create what they might perceive as more elegant code. But who makes such an enhancement?
Well, for now, if I want to write code like the above I’ll need to make the changes. It’ll take about 5 minutes or less. If I sold this package like NebulaXLite then I would accept enhancement requests and make that change for a “next release”.
But if I open source this code then anyone can make that change and publish it for all of us to benefit.
Do I take the 5 minutes and make the change myself? Sure, for 5 minutes I’ll do that. For a change that takes an hour, I might wonder to myself if the change is worth it. I might wish that I had open sourced the code so that someone else could make some neat enhancements, like supporting a completely new graph type. If I keep this code to myself then I’ll just make changes as I need them. If I productize this then I’ll be obligated to provide updates on a timely basis, but I’ll at least be getting paid for it. If I open source the code then I won’t be getting paid, but I might get some free updates from the community. That’s part of what FOSS is about – developers contribute to others, and ideally they benefit from the contributions of others.
But the MV market isn’t very good at this FOSS thing. People in this market take open source software because it’s “free” as in “no cost”, not because they’re “free to enhance it for everyone else”. Interestingly, we’ve seen people in this community will download MVBASIC FOSS and not even comment on it, and the software will eventually fall into disuse because it’s not being maintained. Not only do people not contribute but they don’t even report issues or enhancement requests. So what motivates developers to create a FOSS project with MVBASIC? Well, nothing. I and others used to think that this was a worthwhile and noble effort for the good of the community, but absolutely no one seems to benefit from MV packages that go FOSS – and yet when I talk about new software like GCHART I inevitably get the question “are you going to open source that?” Uh, why?
So here I am, stuck with the beginnings of some very cool software, wishing that I could open source it and watch it blossom into something that we could all use, but knowing that the effort to publish the code will go unnoticed, unappreciated, and that nothing will come back to me afterward. So what motivates me to publish as FOSS? Well, nothing. So I’m either going to keep this to myself or I’m going to enhance it to a point where it’s of sufficient quality to sell. And then I’ll face the music from people who chastise me for selling software instead of giving it all away. Hey, ya gotta do what ya gotta do.
Man, it’s a shame that it always ends up like this.
See Part 2 of this blog/article.