Archive for November 2008

The End of POD Draws Near

For those of you unfamiliar with POD, it stands for Print On Demand. These are books printed with icky nasty toner. No matter how great the print quality is, the book still looks and feels cheap. Kind of like wheeling up to a Ferrari convention in a Yugo. It is true that laser printer technology has made amazing strides, but you can spot a toner printed book from quite a distance. You can also identify them blindfolded by simply dragging your fingertips down any given page. Feels kind of like a cross between Braille and 180 grit sandpaper.

POD falls into two categories.

1) a traditional printing house serving up toner printing for ARCs, Galleys, and out-of-print long tail books a publisher still wishes to keep in print. This is the ethical part of the business, and pretty much the only part of toner printing that makes any sense.

An ARC is an Advanced Reading Copy sent out to various professional reviewing services. Traditionally you will print 50-100 of these and they will have a special cover, if you are still entrenched in the business model which uses ARCs. Most people aren’t these days. Why? The pool of individuals requiring ARCs tend to be both unemployed and unemployable. If you have a reference or technical book, don’t bother submitting to a service which requires an ARC. If you do, your book will be handed off to someone holding a Phd. who has never worked an actual day in their chosen field of expertise. If it wasn’t for tenure, they wouldn’t have a job. In many cases they don’t. Anyone who has had to wade through a pool of recent graduates has had first hand experience with just how far out of touch college programs have become.

Galleys aren’t that much different from ARCs in this day and age. Some people still use them and some don’t. The major difference between an ARC and a galley is that a Galley is supposed to be what actually got sent off to the print shop. An ARC is assumed to still be a work in progress. I don’t know of anyone actually sending ARCs out to reviewers anymore. Galleys tend to get either a stamp or special cover indicating they are a galley. Everybody knows it is a cheap print job and they don’t ding you for it. Lead times for offset press can be measured in months, so a galley ensures there are some reviews ready to be posted with the book when it is released. In theory this helps your sales.

2) Vanity “Let us turn you into a published author” scam shops.

There is a large quantity of these companies on the market. Amazon.com even owns some of them. These shops offer “publishing packages” to the budding author/publisher. Generally they have come-ons like “be a published author for under $600″. The package includes one of their ISBN numbers (by definition they are the publisher, not you when it is their ISBN), some kind of on-line sales page, and an immediate listing on Amazon.com when your book is done. There is generally a minimum purchase requirement on the part of the author, so they have to pay the $600, then buy 48 books at list from the printing house which is actually the publisher.

In short, this is the absolute bottom of the industry. Vanity press titles don’t get listed in any major retail chain and all of that “marketing” you thought you were getting with the package won’t generate a single sale. The author generally doesn’t find this out until AFTER they’ve already “published” through this service and find the per unit print cost higher than the retail price most of their competitors list at on Amazon. Given they have to give a 65% discount to Amazon as part of the “package deal” their list price tends to be double that of their nearest competitor. This is the publishing industry equivalent of a dark alley filled with drug dealers and disease riddled hookers.

All of that is coming to an end.

The 3.0 version of OpenOffice is getting close to the Holy Grail, the ability to save directly to ePub format. The first step, being able to export to XHTML has already been delivered. Another team has been working on a PDF import functionality. Judging from the functionality chart and percentages of completion for those features, they are getting very close. Probably by version 4.0 (if not sooner) OpenOffice will be able to import PDF files from lessor Word Processors and save them directly to ePub format.

How is that bringing this to an end?

Sony is in the process of creating a publisher portal for self/small publishers. The portal is currently going to allow for Sony to do conversion services for those who simply don’t have the foresight to bail on the now dying Microsoft platform. Publishers who can provide an ePub format can move directly into being listed. The Sony eBookstore also feeds many partner sites. Instead of being raped by POD and Amazon, you can simply release your book in ePub format to generate revenue until you can do a quality printing with an ethical printer. Or, you can simply leave your work sitting out there generating revenue without any additional costs.
As of today, you have to convert your book into ePub format. Rather than messing with this, I have been sending my files out to IT Global Solutions for conversion and loading into Sony. Very soon Stanza will have its own eCommerce site up and running for the Apple iPhone market which can also read ePub format.

Yes, the days of the POD scam artists are drawing to a close.

When Will the Department of Labor and the Justice Department Get Involved?

Reading quite a few discussions today (many of them in an obviously Gartner funded thread on Tech Republic about the IT shortage), I began to wonder just when both the Department of Labor and the Justice Department will get involved. Somewhere, the DOL has its own “average base salary” database. I’ve seen links to it before, just didn’t go looking for it today. Instead, I went to Salary.com since it has a fairly good reputation for accurately gathering ranges in regions. (Who knows, they might even be repackaging the DOL information.)

Given today’s prior post, I searched for the title “Programmer Analyst” for the 63113 zipcode. I simply know the contract was somewhere in St. Louis and that was one of the many zipcodes listed for St. Louis. I cannot believe the surrounding zipcodes will have a massive fluctuation. How do I know this? I also looked up base salary ranges for a Chicago zipcode 60673 (again, one of many in the list).

Keep in mind these are base salaries for EMPLOYEES before benefits and bonuses are added in.

60673 somewhere in Chicago

Programmer I 50,397 to 65,151
Programmer II 59,859 to 75,286
Programmer III 73,726 to 91,314
Programmer V 98,300 to 118,161 (8 to 10 years of experience)

63113 somewhere in St. Louis

Programmer I 46,957 to 60,711
Programmer II 55,779 to 70,155
Programmer III 68,701 to 85,090
Programmer V 91,600 to 110,108 (8 to 10 years of experience)
95,504 to 115,744 if bonuses included

The rule with consulting is the rate which must be paid to obtain a qualified consultant is double the range of employee base salary for the same position. This has been the rule for many years. The consultant gets no bennies and there is a pimp taking a cut. So, we do some quick math using the bottom end of the salary range.

91,600 / 2000 = 45.8
115744/2000 = 57.872

If your employee was paid hourly they would make $45.80/hour. Doubling that means the bottom end of a billing rate to consulting firms would be $91.60/hour. Since the client was specifically looking for candidates with 7-10 years of experience, we are working in the correct salary range.

What the client is doing is posting a billing rate to the pimps involved which is less than their internal employee cost. Eventually they will use the lack of respondents as proof there is a shortage of IT workers, so they should be able to bring in H1-B and thus open the door wider for terrorists looking to gain easy access to this country. Those who think such statements are racist obviously don’t know about all of the people Homeland Security is sending home AFTER they’ve gotten here to work in IT. One company in that general vicinity was playing this game and bringing in H1-B workers. A few short weeks into one new-hire’s stint, HR found Homeland Security waiting in their office when they got in to work. The conversation was very short and very simple “He’s leaving today and you are paying for the transportation.” By the time they got done paying for everything they had roughly the cost of two U.S. born workers into this “money saving venture”.

That all brings us to the question of when is Homeland Security going to force the Department of Labor to crack down on this practice by engaging the Justice Department? The obviously have enough data to prove it is a gaping hole in National Security. The couldn’t have already forgotten the arrest of these people could they?

http://news.bbc.co.uk/2/hi/americas/4438593.stm

Vendor Management Systems = Price Fixing and Wire Fraud

Recently I had an interesting discussion with a pimp about a contract opening. They had posted the contract opening on Dice and tagged the entry as “market rate”, but when the called me, they were offering a billing rate well below half of market rate. Several other pimps had called about this same contract, all quoting a billing rate far below market, but this one tried the “chat to him a while and see if he changes his mind approach.”

During the discussion they stated the Vendor Management System didn’t allow them to present candidates outside of the quoted rate range. I informed them that is where the first crime happened. They were rather shocked to hear this, but not as shocked when I told them the second crime happened when they advertised the contract billing rate as “market”.

“What crime is that” they asked.

“Wire Fraud” I responded.

After a long silence they queried “How is that Wire Fraud?”

“I am not a lawyer, but I’ve chatted with some about this very topic. The position has been falsely advertised on the Internet. You put ‘market rate’ as the billing rate even though you know very well $42/hr you are offering is less than half of the going billing rate for qualified candidates.”

“The client is only willing to pay this much” they responded.

“I am only willing to pay 50 cents for a gallon of gasoline at the pump, is that the current ‘market rate’ for gasoline?”

“No.”

“There you go. By not allowing candidates to presented at the actual market rate, your client has engaged in price fixing. By participating in it, so have you and every other pimp advertising the opening as ‘market rate’. Had you actually put the maximum billing rate in the opening you would have been operating within the law. You would also not get a single qualified respondent.”

“How is that price fixing?”

“From what I’ve been told by people who actually work in the field of law, they engaged multiple companies in a single industry on a mission to cap a price. The companies willingly participated when they advertised the opening as ‘market rate’ and all agreed (by method of the Vendor Management System) to not submit any candidates above that billing rate. The company has taken the childhood action of sticking their fingers in their ears and humming really loud to avoid hearing a truth they don’t wish to hear. The method they chose of accomplishing that, while a feature of their particular Vendor Management System, isn’t legal.”

“Oh. So you won’t consider taking the contract?”

Your Very First Import to SourceForge

I recently created a project on SourceForge.net. The project is called xpnsqt. I don’t really expect anyone to work on it, nor do I care. I needed to write something to replace the expense tracking stuff I had developed in Lotus Approach years ago. Other than playing either “Starcraft” or “Lords of the Realm”, I don’t boot Windows. I don’t often have the time or desire to play games anymore, so Windows doesn’t see much usage anymore.

Rewriting the Lotus Approach stuff kept getting put off. I kept waiting for some OpenSource product which would let me do what Lotus Approach had done. Total development time for the original application with Lotus Approach was roughly 45 minutes. I had never used Lotus Approach prior to that. The application itself is quite simple. There are three database tables: categories, payees, and expenses. The first two tables are foreign keys for the expense table. They help ensure I record expenses consistently for the report I generate and hand to my tax person. The report is a simple control break report. Select all expenses flag as being tax deductions/business expenses, sort them by category then date, dump off with totals for each category and a grand total at the end.

Qt seems to be all the rage with C++ development. Having written two books on the Zinc Application Framework many years ago, I’m not new to cross platform development. The difference with Qt is you get a free version of the product with your Ubuntu (or probably any other Linux) installation. I purchased a couple of books on Qt and set about redeveloping this application using Qt and Postgresql.

“Foundations of Qt Development” ISBN-13 978-1-59059-831-3

This is a tome you don’t want to wade into unless you want to spend an inordinate amount of time discussing lists and other theories you should have learned long ago in college. I made it a whopping 65 pages into this 500+ page tome and pretty much parked it on that book shelf which is almost impossible to get to in my office. If I have trouble sleeping some night I might pull it out rather than taking drugs.

“C++ GUI Programming with Qt 4″ ISBN-13 978-0-13-235416-5

I made a good faith effort with this book. Like most seasoned developers, I learn by keying code in which was printed in the book, compiling it, debugging my typos, testing the run, then tweaking. This is the traditional learning path for every seasoned developer I have ever known. The first two chapters of this book allowed you to do just that. Then, it appears Prentice Hall’s design gestapo got into their act. The book made a dramatic switch to “snippets”. Yes, they provide a location to download the complete set of source code, but that is only useful if you are attempting to fix a problem and already know the product. It is not conducive to a learning experience. As a result, I was forced to use the book only for reference. The chapter on database access (yes, chapter) spends an inordinate amount of time showing you how to use a couple of SQL classes which simply aren’t ready for prime time. They don’t correctly handle an empty table condition. They didn’t at the time of writing either since the example program made a point of slamming data into the table before using those classes. In the end, I used little bits and spent a lot of time using the Yahoo search engine.

When it was all done, I had something serviceable. I’m not completely happy with the way the report was handled. You have to either spend a lot of time hacking your own HTML tags or you endure a broken print engine. I opted to endure a broken print engine.

Broken how you ask?

Old School. A standard 11 inch form has 66 lines at 6 lines per inch which was the standard print height. You kept track of your detail lines and made a point of not printing more than 55 of them before inserting a form feed and new page headings. When you printed, you dumped this file in raw ASCII to a printer. The printer (even today’s postcript printers) understand a stream in raw ASCII containing a form feed character.

QTextEdit class. No method of a raw ASCII dump. No matter how you set your printer object up, you cannot get there from here.

Result: I print one set of page headings and let form breaks happen wherever they happen without printing new headings. Why? Since the printing engine in the library is rendering things graphically, I cannot ASS-U-ME we will get 66 lines on the destination. I have no way of making the page break happen other than counting and spitting out a lot of blank lines. Those blank lines look really stupid when you are viewing the report in the QTextEdit class. The class does have built in PDF generation support, but ASS-U-MEs it is starting with the supported HTML subset. In other words, it isn’t smart enough to understand a form feed character either.

Sighhhhhhhhhhhhhhhhh

So. After entering all of my expenses thus far this year and otherwise exercising the application, I made the decision to create a SourceForge project out of it so that others may get some use from this code. Some young geek who actually likes adding code to spit out HTML tags might choose to fix the report. (Must not be a lot of those geeks because there are now several class libraries which are Qt extensions for reporting.)

Once I had been approved for a new project by SourceForge, they sent an email with instructions about doing some admin things. The link to the CVS page had links to CVS documentation. NOT ONE OF THESE LINKS ACTUALLY WORKED. I opened a trouble ticket with SourceForge and have been trading quite a few emails. Nothing actually solved the issue. I run 64-bit software, and judging from the responses I’m seeing, they are testing with 32-bit.

I’ve used quite a few version control systems in my day, but never CVS. Now I’m starting to understand why. After much Web searching I have concluded that either every person in the universe is using a dramatically different version of CVS than came with Ubuntu 8.10, or all the on-line doc is wrong. (Jury still out on SourceForge doc since it is unreachable.) Nearly ever piece of doc I found showed this example:

$ cd tc
$ cvs import -m “Created directory structure” yoyodyne/dir yoyo start

It’s just plain wrong. It is missing a parameter. I changed the username to drunken_coder in the following example, but this is what you can expect when you have an SSH client installed along with CVS on your 64-bit Ubuntu 8.10 system.

roland@roland-desktop:~/junk/xpnsqt$ cvs -z3 -d:ext:drunken_coder@xpnsqt.cvs.sourceforge.net:/cvsroot/xpnsqt import -m “Initial Version” xpnsqt LOGIKAL V_1_0
The authenticity of host ‘xpnsqt.cvs.sourceforge.net (216.34.181.110)’ can’t be established.
RSA key fingerprint is dc:a3:df:84:00:c6:65:b4:93:a6:2e:22:b1:d1:91:b8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘xpnsqt.cvs.sourceforge.net,216.34.181.110′ (RSA) to the list of known hosts.
roland_hughes@xpnsqt.cvs.sourceforge.net’s password:
N xpnsqt/ui_TaxYearDialog.h
N xpnsqt/ReportBrowserDialog.h

No conflicts created by this import

Notice the parameters:

-z3
because sourceforge said to use it.

-d:ext:drunken_coder@xpnsqt.cvs.sourceforge.net:/cvsroot/xpnsqt

cvs repository ext:username@repository:/root/path
the ext tells cvs to use ssh

import
command

-m “Initial Version”
log message

xpnsqt
module

LOGIKAL
vendor tag

V_1_0
release tag

The module parameter is needed and ends up creating another directory under the repository path you listed. Now my repository has /cvsroot/xpnsqt/xpnsqt. Had I been a little more educated at the time I would have stopped with cvsroot so I dumped everything in the top, or used InitialRelase so everything was isolated off. Admittedly, I’m used to much more robust version control software. With CMS, we dump everything into one project repository and create classes which contain generations. When you don’t have an OS which implements file versioning, I guess this is the best you can do.

If anybody else is starting a new OpenSource project on SourceForge and is befuddled on how to do the very first import, hope this helps. As with most things in the Linux/Unix development world, it is expert friendly.

Why I’m Ditching XM Radio

The recent merger of XM and Sirus has proven the more management inbreeds the more it becomes unfit to walk the earth. Prior to the merger XM had two channels which completely justified its existence: Fine Tuning & Audio Visions. These channels were unique in their nature and examples to be held up showing what the human race can aspire to become. Their loss can only be said to prove those against the proposed merger were correct.

Fine Tuning used to have the widest variety of non-mainstream radio music I’d ever found. In the same 45 minutes they could play Bach, Genesis, Jethro Tull, and several other artists nobody would associate together and somehow make it all work. There were shows which aired regularly such as Emerald Voyage featuring Irish folk and dance music, and a show featuring music of any genre written by original native Americans. These shows were fascinating. Had it not been for this station I would have never discovered a group called the Mediaeval Baebes, or an artist known as Nils Lofgren. Fine Tuning was a truly astounding station.

Audio Visions was that perfect background music for writing books or software. Most of the music had no lyrics. Simply beautiful sounds that evened out the stress of the day and allowed you to drift away when you needed to.

These were nearly the only stations I ever tuned in. They enriched the human species. Sadly, they are gone now. Soon my XM subscription will be gone as well.

Qt4 and Postgres quick example

Just a quick example of some very fundamental Postgres database access with Qt4. I was tracking down a problem all afternoon, so thought I would post this test. The only important thing to learn is that bindValue() really does only stuff the current value into a temporary string. This is NOT like an SQL pre-compiler which binds the variable for life, saving you a lot of work.

tax_2138=# select * from expenses;
tran_dt | category | tax_ded | payee | amount
———+———-+———+——-+——–
(0 rows)

#include
#include
#include

int main(int argc, char *argv[])
{
//int i_x;
QString dbName, localCategory, localPayee;
double localAmount;
QDate localTranDt;
bool localTax_ded;

QApplication app(argc, argv);

{
QString driverName = “QPSQL”;

//
// Set up information for driver and see if driver is available
//
QSqlDatabase db = QSqlDatabase::addDatabase(driverName, “xpns”);
db.setHostName(”localhost”);
QString dbName = “tax_2138″;
db.setDatabaseName( dbName);
db.setUserName(”"); // yes I deleted my username
db.setPassword(”" ); // yes I deleted my password

//
// Have they been good little children and created our database already?
//
if (!db.open()) {
qDebug() << "database wasn't opened";
return 0;
}

QSqlQuery query(db);
db.transaction();
query.exec("INSERT INTO expenses( tran_dt, category, tax_ded, payee, amount)"
"VALUES ( '21380506', 'Software', 'Y', 'CDW', 3456.72)");
qDebug() << "Rows affected from text only insert: " << query.numRowsAffected();
db.commit();
qApp->processEvents();
QSqlQuery preparedQuery(db);
preparedQuery.prepare( “INSERT INTO expenses( category, tax_ded, payee, amount, tran_dt) ”
“VALUES (:category, :tax_ded, :payee, :amount, :tran_dt)”);

db.transaction();
localTranDt = QDate( 2138, 10, 11);
localCategory = “Hardware”;
localPayee = “3Com”;
localAmount = 876.54;
localTax_ded = true;

preparedQuery.bindValue( “:tran_dt”, localTranDt);
preparedQuery.bindValue( “:category”, localCategory);
preparedQuery.bindValue( “:tax_ded”, localTax_ded);
preparedQuery.bindValue( “:payee”, localPayee);
preparedQuery.bindValue( “:amount”, localAmount);

qApp->processEvents();

preparedQuery.exec();
qApp->processEvents();
qDebug() << "Rows affected: " << preparedQuery.numRowsAffected()
<< " Error text: " << query.lastError().text();
db.commit();

db.transaction();

//
// Simply changing the variable values isn't enough.
// Qt doesn't work like SQL compilers which bind variables for
// the life of the program. There is no real bind here,
// simply things being forced into a command string. You have
// to both change the data and bind the value. I guess that is why
// it is "bindValue" not "bindVariable"
//
localTranDt = QDate( 2138, 6, 11);
localCategory = "Books";
localPayee = "Borders";
localAmount = 88.99;
localTax_ded = true;

preparedQuery.bindValue( ":tran_dt", localTranDt);
preparedQuery.bindValue( ":category", localCategory);
preparedQuery.bindValue( ":tax_ded", localTax_ded);
preparedQuery.bindValue( ":payee", localPayee);
preparedQuery.bindValue( ":amount", localAmount);

preparedQuery.exec();
qDebug() << "just wrote duplicate row" << preparedQuery.numRowsAffected();
qApp->processEvents();
db.commit();

}

return 0;

}

roland@roland-desktop:~/qt_stuff/db$ ./db
Rows affected from text only insert: 1
Rows affected: 1 Error text: ” ”
just wrote duplicate row 1
roland@roland-desktop:~/qt_stuff/db$

tax_2138=# select * from expenses;
tran_dt | category | tax_ded | payee | amount
————+—————————+———+—————————————————-+———
2138-05-06 | Software | t | CDW | 3456.72
2138-10-11 | Hardware | t | 3Com | 876.54
2138-06-11 | Books | t | Borders | 88.99
(3 rows)

Java Rots Your Brain

For the past few months now, I have been doing more Java than normal. This week, I started working with Qt and re-writing a system I use to track my expenses for tax purposes. The prior system was in Lotus Approach using DBF files and I wanted something which would work with 64-bit Ubuntu. I now only boot Windows when I have a strong desire to play either Lords of the Realm or Starcraft. It has been a long time since a client has demanded I run Windows and use a software VPN. I assume eventually there will be SISCO VPN software for 64-bit (or at least 32-bit) Ubuntu since that OS seems to be making quite a few inroads on corporate desktops.

Qt shouldn’t be difficult for me. After all, I used Zinc for a good number of years writing stuff on OS/2 which cross compiled for DOS, Windows, and Mac. I even published a couple books on the product. Perhaps it is just because I’m getting older. Perhaps it is because book publishers have forgotten the learning process. For most developers of my era, a new tool or language is learned by actually typing the listings in from the book. The books I’ve found on Qt have devolved into printing just the “relevant snippets” and providing a download link to get the full source. A download link is well and good, so is a CD in the back of the book. It helps those who just want to look at the thing or steal some code for a project. It doesn’t help those who want to learn the product.

Back in my college days, we were told to use one notebook for notes during class, and a second notebook to study from. We were supposed to take quick short notes in class, then copy them cleanly into an official notebook with additional material from our text and other information sources. Some high school classes I had actually graded our notebooks. The reason this was done is the repetition and multiple sensory focus re-enforced the learning process. You don’t learn by simply compiling examples and running them. It is very difficult to talk yourself into re-keying something that is already displayed in a text editor window. Takes a real force of will that most people don’t have.

So, how do we get from problems with Qt learning to Java rotting your brain? Read on.

Database access examples provided by most books are quite pathetic. Since they are focusing on just the needed IO calls/commands, all access information tends to be hard coded in the example. Things like username, database name, password, etc. all hard coded strings. Not the kind of code anyone would want in a production system (but sadly, the kind of code actually existing in a lot of shops.)

The first piece of code you have to develop on your own is a simple logon dialog. Depending upon the toolset you are using this can either be a dialog which prompts for and returns the information, or it can actually take the extra step of validating the connection information and creating the database object. I opted to connect and validate since that allowed me to create a shiny new database if the one I wanted was missing. Silly boy! You want something to function correctly. This is the age of Microsoft, where nothing works and nothing is expected to work!

Once I had that working, I created a second dialog to allow for entry and editing of the expense table while using the category and payee tables as foreign key references. When I added that dialog and tested the simple test of navigating to the screen and exiting it I was greeted with the following error:

QSqlDatabasePrivate::removeDatabase: connection ‘xpns’ is still in use, all queries will cease to work.

Spent around 4 hours searching around on-line and trying various things to eliminate this error. Found a lot of bad advice on how to mask the error and some people saying it was only a warning they could ignore. Well, it’s really neither. You’ve created a memory leak and at least this is letting you know about it.

Part of the problem is that QSqlDatabase objects are global to your process. No matter where they get created in your program, once created they are accessible by any function/method. I have mixed emotions about that, but it is what it is. The other part of the problem was my having worked with Java for a while then reading in the Qt 4 book about how all things derived from the QObject would be cleaned up by the Qt application when it closed. It’s true as far as it goes, but it doesn’t go far enough.

Granted, I should have created a container QWidget and added the login dialog to that, but, I also shouldn’t have been forced into that design since you can create dialogs wherever you want and they will get cleaned up…mostly. The “order” of cleanup leads to problems though. The other issue forcing my decision was the fact the form needed to know which tax year it was dealing with to be created appropriately.

I know, many of you Unix developers would simply put the second form in its own thread where it could run yet another instance of an application and all would be right with the world. I have a personal issue with launching a new thread from a parent thread and allowing the parent thread to die immediately after launching the child. This is EXACTLY what creates dangling threads on systems.

The problem doesn’t have anything to do with the QSqlDatabase class itself, other than it is reference counting since it is global. The problem has to do with the default parameter for a QDialog, most notably

XpnsLogonDialog( QWidget *parent = 0);

Ordinarily, this isn’t an issue. Creating an un-anchored dialog which connects to a database causes the problem. Were it anchored to a QWidget, the QWidget would die and take all its children before the other global things would be reclaimed.

Where I got into trouble was when the dialog needed parameters for its constructor other than a parent value. Those values needed to come from the logon dialog itself. Adding insult to injury was the fact I was looking at code “snippets” which were relying on having a parent QWidget to control life and death of the object holding the database reference. Life is really good some times.

else {

connectionStatus = true;
xpnsForm = new XpnsForm( -1, _tax_year);
xpnsForm->show();
}

The above snippet, executed when the logon information provided parameters which resulted in a valid database connection is where the wheels started to come off the cart. “new” put the allocation on the heap instead of the stack. Due to the way QObject gets cleaned up, the reference counter was still set. I tried everything, closing the database, calling removeDatabase, every suggestion, and still the reference counter caused the warning message. I was thinking this cleanup happened the same way Java garbage collection does. The cleanup would make N passes through the list collecting everything flagged for garbage collection and flagging new list entries as it freed things up. It doesn’t.

When all else fails, you use brute force.

XpnsLogonDialog *dialog = new XpnsLogonDialog();
dialog->show();
i_x = app.exec();
delete dialog;
db.close();

In the XpnsLogonDialog I was forced to create a destructor as well.

XpnsLogonDialog::~XpnsLogonDialog()
{
nuke_subforms();

}

void XpnsLogonDialog::nuke_subforms()
{
if ( xpnsForm != 0) {
delete xpnsForm;
xpnsForm = 0;
}
}

While it is true I didn’t need to break it out into its own function, doing that allowed me to test one other thing.

XpnsLogonDialog *dialog = new XpnsLogonDialog();
dialog->show();
i_x = app.exec();
//delete dialog;
dialog->nuke_subforms();
db.close();

Both methods free up the resources and clear the reference counter.

Spend much time working with Java, and you will stumble when coming back to C++. The same is also true if you spend a lot of time with C++ and try to jump back to Java. Admittedly, this problem surfaced because of someone trying to be nice and rolling their own garbage collection into an application framework. I suspect it solves more problems than it causes. I remember a lot of people having memory issues with their Zinc applications because there wasn’t newbie friendly documentation, just some example programs people copied from, whether they applied to their project or not.

One other major issue I have with the published examples have to do with the following code. This code is mine and I have fixed the issue.

//
// Actual database setup begins here. Keep in mind we have already
// established a connection to the database at this point so fieldIndex()
// should work correctly.
//
tableModel = new QSqlRelationalTableModel(this, QSqlDatabase::database(”xpns”));
tableModel->setTable(”expenses”);
tableModel->setRelation(tableModel->fieldIndex(”category”),
QSqlRelation(”categories”, “category”, “category”));
tableModel->setRelation(tableModel->fieldIndex(”payee”),
QSqlRelation(”payees”, “payee”, “payee”));
tableModel->setSort(tableModel->fieldIndex(”tran_dt”), Qt::AscendingOrder);
tableModel->select();

In the published examples, the create an enum for the field number and pass in compiled values to these and other database calls. That is an extremely bad practice, especially since the library already has the tools you need. Above, you will see I called fieldIndex() to obtain the column number from the currently connected database table.

Can anyone tell me why using a compiled enum is a bad practice?

That’s right! The database layout could change over time and you don’t want to be married to it. A five column example table has little chance of that, but what about a production table? What if you are only using five fields out of a production table that has 20 and the DBAs have to drop a column occurring before the columns you use? Sometimes you don’t even know about a change. The DBAs aren’t usually send out change request email that most developers ignore. Sometimes for performance reasons, they need to change the structure of a database. They do an unload and a reload, only the new table they reload into has the fields in a different order. You find out at 3 a.m. on Monday morning when your application won’t start and production is held up.

Wow! A rant AND useful information.

Numbered Headings in OpenOffice

Don’t get me wrong, most of the time, I’m very happy with OpenOffice. The thing which infuriates me about it is the lack of control being exercised over the developers. It appears to be designed by committees which communicate haphazardly rather than with some Queen Bitch riding herd over them and directing their efforts.

The move towards XML Style Sheets was not a high point for word processing in general. Something which should have been handled behind the scenes simply keeps rearing its head in the middle of the user interface. Today, I had to re-learn something I have done in every “The Minimum You Need to Know” book: How to get numbers into my headings. This is one shining place where the XML back end needlessly slipped forward into the user interface. First let me explain what I’m talking about.

Chapter 9
Working With Stupid People

9.1 They Don’t Know They Are Stupid

The Number’s I’m talking about are the chapter number in the chapter heading and, more importantly, the 9.1 in the secondary heading. What you want to have happen is the chapter number increments with each new chapter and the subheadings keep count.

Everybody beats their head against the exact same wall. You hit the F11 key to bring up the style menu and try desperately to modify both Heading 1 and Heading 2. That is the logical place for such a feature to exist from a user interface perspective. Well, you are not even close when you look there. Why does everybody make this same mistake? Because you only need to do it once for the document and it just rolls merrily along after that. In the case of a book, it could well be a year before you need to know this again.

Hidden under the Tools menu is a menu item called “Outline Numbering”. You must click on this, then select “Heading 1″ for level 1, insert “Chapter ” in the _before_ field. (Don’t forget the space.) You must also choose 1,2,3 as the numbering format and tell it to start with 1. Next you click on the “2″ entry to choose the style for the second level. Here one must choose “Heading 2″; “1,2,3″, and most importantly, set the sublevel value to 2 or more. If you don’t change this value, you don’t get the nice little “9.1″, you get “1″.

I understand why the developer put it there, but they were just plain wrong for doing it.

Perhaps some day OpenOffice will be able to generate ePub file formats for the Sony readers and iPhones out there. Then, and only then, will the word processor focus shift to XML based storage begin to pay back a tiny fraction of the frustration it has inflicted upon the world. OpenOffice isn’t alone in this XML move, but currently it is the only one I see which is letting the XML back end slip through to the front end.

Removing an Old PostgreSQL From Ubuntu

‘ve finally bitten the bullet and am porting an expense tracking system I use for taxes from Lotus Approach to a Qt program which runs under Ubuntu. I decided to use PostgreSQL for my database instead of XBASE file formats because it is easier to trap dependencies (expense category and payee) than with XBASE type files. Yes, it is far more convenient to keep everything for one tax year in one directory as I used to do with XBASE files, but not as reliable.

Because of several upgrades and installs, I had both PostgreSQL 8.2 and 8.3 installed. The standard package manager would not remove 8.2 because it was automatically started when the system booted. Rather than read through a lot of startup documentation and find the script to remove 8.2 startup, I found a command which would do everything for me.

sudo apt-get –purge remove postgresql-8.2
This command is smart enough to shut down the database server, then uninstall the product. Yes, I probably could have gotten the package manager to uninstall it once I shut it down, but when it comes to database administration, the less I have to dig, the better. Keep in mind that this database will rarely have more than 1000 records in it. It could have easily been dealt with using RMS files on OpenVMS, but I have a desire to learn a little more Qt programming before tackling a patch/fix to Konsole so it actually supports the keypad when in VT emulation mode.

SDLC Doc and Penis Enlargement

Over the past two years I have encountered companies which spent huge amounts of money purchasing SDLC templates and even larger amounts of money customizing those templates for their own location. Once they have their customized templates, they spend piles of money sending people suddenly titled “Business Analyst” to training on how to fill out the document templates for each project.

Why are they doing this? The root of this evil is Sarbanes-Oxley, but the vendors of SOX solutions have taken their marketing queue from penis enlargement commercials. “Get a big boost of confidence knowing your IT projects can no longer fail.” I have even been to sites that were stunned to find IT projects cratering. Managers were circling the wagons trying to figure out what part of the SDLC process the failed project skipped.

SDLC has a lot in common with “male enhancement” products. They both require you to believe and see what you wish to see. Where they differ is that investigators will have actual signatures on file when a project fails and someone tries to hide the cost in the books. SDLC documentation doesn’t ensure a project’s success, but it does identify who will go to prison when the failure is covered up.

Am I against SDLC doc? I am against many of the process steps imposed by commercially vended versions. Those vendors designed the SDLC so MBA’s could have input. They created a “Work Initiation” step which was more than a single line on a “to-do” list and less than a detailed analysis. The actual detailed analysis gets spread across three-four different documents, presumably to be filled out by three to four different people. Isn’t that just what you want on any project? Four different people all trying to steer the boat without any of them manning the sails. In actuality, this is exactly how the SDLC process is implemented at pretty much every client site I’ve been to that is SOX compliant. Guess what? If you aren’t publicly traded you don’t have to be SOX compliant.

To start with, no SDLC process can guaranty a project outcome. If any hint of that was in the sale pitch, you need to press criminal charges against the vendor. As currently implemented at most companies, an SDLC process serves only two purposes:

1)Turn tiny bug fix projects into massive things requiring sign off from many different people
2)Provide a predefined list of names to the criminal justice system.

You see, each and every SDLC process makes the grand assumption that “someone” working at your company actually knows what is going on. That assumption is the ultimate fraud. The process allows everyone who “thinks” they are in charge to feed their own ego by requiring them to sign off on various stages of the process. The process provides absolutely no defense from clueless ego feeders.

An even bigger threat for each and every SDLC process out there is that each person on the project will know only a little piece of the system you are working on. Each step in the SDLC process will pull the project in a different direction as each new player is encountered and your final system delivery won’t look anything like what was requested in the Work Initiation.

The most common train wreck every SDLC process creates is one which stems from piss poor management and scope narrowing. You have a system which has been in place for 20-30 years. It was originally purchased, then heavily customized. The only documentation which exists for it is the original system documentation, prior to modification. Other departments have taken over pieces of the system, rolling them into a new application by a new name. Some portions of the system are still using fixed width flat or indexed files for data storage. Other departments have written systems which makes use of the data at this stage, but they didn’t bother telling you. When you finally install your change in production, applications which haven’t been touched in over a decade suddenly fail and nobody has any idea how to recover them. All of your testing went perfectly, because you only tested for the couple of interfaces you knew about. There was no full scale production sized development system to run a complete production simulation, so you had to test only what you knew about.

This entire series of train wrecks gets even funnier when you toss in software development which is performed by illegal aliens who have no frame of reference when it comes to your business. They just code what they are told and don’t put up a fight like a seasoned professional would.

I don’t believe anyone reading this is willing to take before and after pictures using a ruler, and announce the “study” of a male enhancement product prior to some perceived “big boost of confidence”, which is why those products all promise they are shipped in a plain brown package without identifying markings. Did the SDLC product you purchased make the same promise?

|