Discussing the Rugby World Cup over Friday beers, we began comparing different football codes—rugger, league, gridiron and so forth. When we came to the subject of body contact, my friend David Roze pontificated:
“Soccer is the disco of the football world.”
True. True.
The FSF created the GNU Public License to support their agenda of free software. In particular, the GPL incorporates mechanisms intended to ensure that free software is not incorprated into non-free software.
This has led to a certain industry captain taking the public position that it is not possible to “commercialize” a product incorporating GPL source.
Though IANAL1, I’d like to disagree with the industry captain. There are legal, if underhand, ways to make huge piles of $$$ from GPL software.
Take, for example, boutique retail banks. These are the kind of banks that have just 25 employees and write billion dollar mortgages for family trusts. Suppose you run a company producing front-office software for these banks, and that you have 5% of the market. Your clients pay well if you can offer them a competitive advantage.
You decide to add a Virtual Reality interface to the next version of your product. After carefully evaluating all the options, your technical architect settles on the GPLed C’Nedra as the VR engine, and your company goes into development, incorporating as much of the open source code as is helpful to the project.
Because your new product is derived from GPLed source, you must comply with the terms of the GPL. The trick to remaining profitable is in how you comply. Here is how I would address the license terms:
Section 2a requires that all modified source have a comment noting the change and its date. Your programmers probably do this already with the CVS $Log$ keyword, or similar.
Section 2b disallows charging money for the software. Instead, charge for installation, customisation, support, and ‘consulting.’
Section 2b also requires that your whole program be licensed to your customer under the GPL. Take a deep breath and go do it.
Section 2c requires that, if your displays a copyright notice on startup, it also gives details of the license. Weasel out of this by not displaying any copyright notice or startup message.
Section 3 requires that you distribute the source with the program. It offers a number of ways to do this, but 3a is the most promising. Copy all the source onto an unlabelled CD-R and hand it to your customer’s CEO. Warn the CEO of the danger to his company’s competitive advantage should another bank get hold of the CD-R. Recommend to him/her that they burn the CD-R and shred the ashes.2
Of course there are some details that I’ve left out, but no show-stoppers. Provided that your customer’s CEO doesn’t give away the source code, you now have a money earning, GPLed, and—for all intents and purposes—proprietary product.
Just a thought.
1 I Am Not A Lawyer. I am not legally or morally qualified to give legal advice. For that matter, I am not legally or morally qualified to give business advice. Don’t blame me if you try it and it doesn’t work.
2 It’s kind of neat that section 1 requires you to distribute a copy of the GPL with the source; your customer will be burning and shredding the GPL along with their source.
I had a peculiar problem this morning. log4j logging output was being turned off in a call to a third party library1. Not very much fun, particularly when exceptions start going unlogged.
Here are two code snippets that were useful for debugging the problem. This code resets the log4j configuration from the contents of the log4j.properties file:
static void resetLog4j() {
LogManager.resetConfiguration();
ClassLoader cl = this.getClass().getClassLoader();
URL log4jprops = cl.getResource(
"log4j.properties");
if (log4jprops != null) {
(new PropertyConfigurator())
.configure(log4jprops);
}
}
The log4j config can be dumped to standard out like this:
private void printLog4jConfig() {
System.out.println("#log4j Config");
PrintWriter pw = new PrintWriter(System.out);
PropertyPrinter pp = new PropertyPrinter(pw);
pp.print(pw);
System.out.println("#End of Config");
}
1 Google turned up a solution to the same problem in a previous version of the product, but nothing for the current version. I couldn’t find any other mention in the Knowledge Base or Support forums. I submitted a bug report, but meanwhile I have a workaround.
Microsoft have a product that provides a Unix-like environment, including command-shell and standard unix utilities (like Cygwin) and also an NFS client/server and a swag of tools for administrators working in a hetrogenous environment.
Given that it provides a whole bunch of standard Unix services to Windows users and to Windows applications, would you call it:
A. Unix Services for Windows, or
B. Windows Services for Unix?
Really, think about it for a second.
Believe it or not, MS went for option B.
I cannot imagine what argument they might try to make that option B is better than option A. Yes, the product does provide some Windows services to Unix, but it is more about providing Unix services to the Windows operating System, to Windows administrators and to Windows applications.
Undoubtedly there were solid, market-driven reasons for their choice but that doesn’t make their mis-representation any less.
Earlier this month, Ian Bicking blogged on the inadequacies of the standard unittest module. Reading through the discussion and comments thread is enlightening. Ian’s complaints are:
While I can see Ian’s points, I don’t feel his pain; the unittest module is perfectly adequate for my unit testing needs. I think the big difference is in our approaches to unit testing.1
When working on a system, I try to run all the unit tests every five or ten minutes. All I really need to know is whether the tests pass or fail. When they fail I know the bug must have been introduced in the code I was just working on.
The unittest module supports this quite well. I can a TestCase class for each major piece of functionality to be tested, with multiple testXXX() methods, each containing maybe five or ten individual tests. While not recommended by the unittest documentation, I find it handy to use the Python assert keyword rather than the TestCase testing methods.
Doing it this way:
A. Boiler-plate accounts for only a small percentage of the test code—maybe 10 or 15%, which is mostly the def and class statements.
B. The unittest.main() function supports running all the tests on a TestCase class, or an individual testXXX() method on a class, something you lose if you define your own TestCase constructor.
C. No logging of intermediate test results is necessary. The traceback is usually enough to diagnose the failure, otherwise it is time to insert a few print statements or break out the debugger.2
D. Nor is it necessary to see what the failures would have been had test continued on. Usually, I have done such little coding between test runs, that I have had time to introduce only one bug. If not, I’ll find out when I run the tests again.
This method relies upon is the ability to run the tests quickly. For larger systems, I need to split the tests into separate suites. All the tests are still run, but I run the suites pertaining to the current code more frequently.
All that said, one of Python’s strengths is the active, eclectic community it supports. It was great to see references to so many other unit test libraries and extensions to the unittest module on the comments to Ian’s blog entry. Among them were:
—————
1 I’m certainly not claiming that my unit testing method is better than Ian’s, just different.
2 I drop ”import pdb ; pdb.set_trace()” into suspect code to start a debug session.
In an article on xml.com, the Kendall Grant Clark notes that:
… the LAMP (Linux, Apache, MySQL, [Perl, Python, PHP]) crowd has not yet bought into the animating ideas of the Semantic Web.
While true, this is a little like observing that the United States has not yet bought into the animating idea of declaring Esperanto the national language.
On the other hand, I do see the odd discussion of the semantic web amongst the Javablogs crowd.
Got an email from a friend who is thinking of starting a blog. He has some reservations about it, and also asked about Movable Type. Here is my reply:
Blogs are good for some things – diaries, opinions, short articles. What they are particularly bad at is letting you develop a piece of writing over a period of time. That said, I am sure you will enjoy blogging, and I’m equally sure I’ll enjoy reading it.
Moveable Type is OK. From what I understand, it represents the state of the art for pure server-side blogware. ‘tis lightweight and easy to set up in a wide range of environments.
Installation was simple once I wrapped my head around how MT works: it stores all the information in the database, but when you publish, it generates flat html files into your www directory. phpwebhosting have all the tools you need (actually, just perl) to make it work.
The only problem I have ever had with it is corruption in the BerkelyDB database. I lost 80% of my blogs comments. I have since moved to the MySQL backend and have had no further issues.
Andy Sy mounts an argument for C over Java, C++ and C#.
I find myself agreeing at some points and disagreeing at others. It’s telling a telling point in Java’s favour, though, that his main arguments are against Java. An interesting read.
I just released the source code to Cardboard Schedule, a small project planning app I put together a few years ago. Distinctive features of Cardboard Schedule are:
Cardboard Schedule sold enough copies to pay for a PC and then some, but in the end, hours with my family were more important than hours with my computer, and Cardboard Schedule development stopped. The last license was sold more than a year ago1.
All up, building and selling Cardboard Schedule was a great experience. I got to delve into dark corners of Swing—image manipulation, printing and drag-and-drop—none of which was simple under JDK1.1. The experience I gained from deploying a single application over multiple JVMs and operating systems has been useful on almost every other Java project I’ve worked on since. I also learnt bucket-loads about shareware marketing, building and running hosted web sites and intellectual property law.
The reason for open sourcing Cardboard Schedule at this point is that I found an organisation that both wants to use the product and has the resources to look after the source. Maybe others can benefit from bits and pieces of code too.
Stay tuned. I’ll be writing another couple of articles on Cardboard Schedule.
1 Actually I didn’t “sell” that last license, I bartered it for a 50USD donation to ICCF, the organisation supported by Vim.
I’m in the middle of picking an Open Source License for some code that I once released commercially, but now wish to release more openly. The current favourites are the MIT License and the Historical Permission Notice and Disclaimer, because they are simple, relatively liberal and include the all important legalese paragraph that says “don’t sue me”.
Are there other, similar licenses I should be looking at?
Radio National’s Science Show recently broadcast a short interview on the subject of synaesthesia, the phenomenon of subjective sensation of a sense other than the one being stimulated. For instance, a form of synaesthesia is seeing patterns of coloured dots while touching particular kinds of surface. It is distinct from imagining or visualising.
The interview transcript is well worth a read.
While discussing the radio progam with a relative, she told me that she has a mild synaesthesia. Music with emotional content affects her perception of colour. For instance, in the Pink Elephants scene of Disney’s Dumbo, she sees the elephants as blue. Likewise, she is not sure of the colours through much of Fantasia.
The synaesthesia doesn’t affect the rest of her vision perception,1 so driving with the CD player going full blast is quite safe. The only problems I can think of are (a) she may not be able to tell the police the colour of the getaway car in a bank robbery, (b) finding her car in a carpark with background muzak may be difficult. five or ten people and nobody had it would be helpful. I’ll post another note
To me, the most interesting thing about the whole episode was that she thought everybody’s colour perception was affected by music. It hadn’t occured to her that there might be anything special about her perception. It causes me to question the strength of the grip we each have on the world around us. In particular, it makes me wonder what my quirks may be.
Anyway, I encourage you to ask your relatives and friends about experiences like this and let me know what you find—even a quick note to the effect that you asked five or ten people and nobody had it would be helpful. I’ll post another note in a week or two.
1 As far as she knows.
Keith PC finally declared his PC dead on Monday. So when we arrived at work yesterday morning we weren’t surprised to find that the hardware faeries had taken the defective box.
In some ways it was a rather eerie sight: the monitor, keyboard, mouse and LAN cables were all still in place, but there was just a hole where the actual PC should have been. “Let that be a lesson to any other PCs that might misbehave,” I said.
Mid-morning, somebody’s monitor went bang! and stopped working, so they took Keith’s. The desk was beginning to look pretty bare.
After lunch I resurrected an old PC, and found I needed a keyboard and mouse. As Keith left for the day, all that was left of his PC was a lone LAN cable, its tail buried in the wall socket and its head flopping on the desk.
A half hour later, I discovered the old PC I was traced a network problem to a bad LAN cable. So I took Keith’s, of course.
Simon Brunning recommends Andale Mono as a programming font. I’ve been using it in Eclipse for a few days now, and I really quite like it.
The origins and usage of Andale Mono has an interesting legal history, but you can currently download it from SourceForge.
A neat feature of Java is that it checks local variables are definitely assigned before they are first used. Because of this, it is not always necessary to initialise local variables in their declaration.
For instance, take this Java code snippet, which declares and initialises a variable named forward:
ActionForward forward = new ActionForward();
if (i > 5) {
calculateSummaryData();
forward = mapping.findForward(“big”);
} else {
calculateDetailedData();
forward = mapping.findForward(“small”);
}
return forward;
The initialisation of the forward variable in the first line is redundant; the assigned ActionForward object will never be used. The snippet could be rewritten as:
ActionForward forward; // no initialisation
if (i > 5) {
calculateSummaryData();
forward = mapping.findForward(“big”);
} else {
calculateDetailedData();
forward = mapping.findForward(“small”);
}
return forward;
This second form has several advantages:
ActionForward instance that will be discarded.When I first started coding Java (in 1997) all Java programmers seemed to know and use definite assignment. Over the past few years, however, I have seen more and more code that initialises variables unnecessarily. I wonder why this is. Any suggestions?
I’m using Win NT 4.0 at work at the moment on a fairly modern PC. It stinks:
Remember this next time someone tries to tell you that Windows XP is no better than NT 4.0.
Got back from a country holiday today. No Internet for one week and I’m OK. Mostly OK. Pretty sure I’m OK.
The blog collected three comments while I was away. Two were blogspam. One advertised pillz, the other a sad mixture of viagra and porn. They lasted as long as it takes to click Moveable Type’s delete button.
The third comment was on an old entry of mine, Crime Scene Cleanup Directory. Turns out cardboard.nu is Google’s #3 result for ”crime scene cleanup directory”!
This morning I woke up from a dream about the Oracle TO_DATE function. The dream had all of Oracle function names, in UPPERCASE, listed on a pdf manual page, with a brief explanation alongside each. I was examining the TO_DATE function in particular. In reality, there is no such manual page—the real manual only has long explanations.
It was a relief, that despite this week’s run-in with the DB/2 TO_DATE function, it was definitely the Oracle TO_DATE function I was dreaming about.
Overall, this was a strange experience for me. I usually have dreams about people and places rather than things. I can’t remember ever dreaming so vividly about an object.
On the plus side, I am taking leave this week. I was feeling a little guilty about the timing—we have a delivery starting Tuesday—but this little episode is proof that I need the holiday.
Joe has a story and a photograph of street sign that talks back.
Reminds me of the battles the authorities have with speeding motorists on the F6 freeway. Thirteen or fourteen years ago, they put up a huge, bright sign that displayed each car’s speed as it zipped past. Of course, many took that as an invitation to make the numbers go as big as possible. My friends regularly got a score of 180km/hr. I’m sure others topped 220.
That sign came down fairly quickly.
Well, technology has marched on and recently a new interactive sign has appeared. And the RTA have learnt their lesson. It only activates when it detects a speeding car and instead of showing the offender’s speed, it shows their number plate.
Much more effective.
Leafing through the DB/2 SQL Reference, I found a function called to_date( string-expression, format-string ), which converts strings to dates. Just what I needed, I thought, for converting string in arbitrary formats to dates.
Nope.
This what the manual says about the format-string parameter:
format-string A character constant that contains a template for how the string expression is to be interpreted as a timestamp value. The length of the format string must not be greater than 254… The content of format-string can be specified in mixed case.
Valid format strings are:
‘YYYY-MM-DD HH24:MI:SS’
And that’s it. There is ONE valid format string. Passing any other value for that parameter earns you this error message:
SQL0171N The data type, length or value of argument “2” of routine “SYSIBM.TO_DATE” is incorrect. SQLSTATE=42815
Very funny, IBM.
Had a huge day today converting our Hibernate application from DB/2 to Oracle 9i. The move seemed to highlight every single little shortcut we took through the whole development so far.
There were numerous little gotchas. Keith took the first one. Hibernate was using a single SELECT statement to read 146 columns spread across ten tables, half of which were outer joined. The generated SQL was 5923 bytes long. On DB/2, it was a performance problem; on Oracle it caused the JDBC driver to curl up its toes and die.
The most frustrating problem of the day was dates. It turns out that DB/2 and Oracle have very different ideas about how dates should be represented in literal SQL strings. We used literal dates quite heavily from our test cases. Turns out there is a representation of a timestamp that is valid in both Oracle and DB/2 (to_date(‘1962–08-11 12:00:00’, ‘YYYY-MM-DD HH24:MI:SS’)), but for straight dates there was no single string that worked in both SQLs. Prepared statements are fine—it’s just literal dates in SQL.
Hibernate has certainly lived up to its reputation—the generated SQL runs as well on Oracle as it does on DB/2. The only Hibernate problems we ran into were due to misconfigurations or misunderstandings, all easily corrected with a little help from Daniel.
Eclipse / WSAD deserve a mention here too. I would still be coding without Ctrl+Space, Ctrl+Shift+F and, especially, Ctrl+Shift+O.