“Priced Right” Developers Will Put You Out of Business

Northern Tool shopping cart
Norther Tool shopping cart

It seems the world is devolving into Keller MBAs and fake-reality television stars. Bottom feeding Keller MBAs have infiltrated every company it seems. They have the following main mantras

  1. Any job which can be done by two people can be done by one at half the cost.
  2. Do more with less.
  3. “Priced right” is the only qualification that matters.

Even if they have a diploma from a different school, if they utter even one of these mantras out loud, they got the exact same worthless education one gets from Keller. Sadly, Keller MBAs seem to have even infiltrated Norther Tool.

The Spherical Cow

Spherical Cow image
Spherical Cow

I’ve written two books on Java.

A free one which is part of the XbaseJ project. (If any of you see it being sold on lulu.com or any other worthless POD site, please contact me ASAP! Twice someone put that title up there for sale and I had to fight with lulu.com to get it taken down.)

A not free one written so Java programmers could learn a bit about JNI and people who only knew Java could experience working on a real operating system like VMS.

Java is what you use when you either have no other choice or are bottom feeding on price. Corporations choose Java because they are bottom feeding. Individuals choose Java because they either don’t know any better are aren’t getting paid for the work.

I recently had this conversation with a Sperhical Cow in the comp.os.vms Usenet newsgroup. I have worked at places where people bragged about only paying off-shore Java developers $10/day. (That’s right, day.) I have also written Java when I was going to be donating code to a community. In the case of the free book I was donating the code to various farm and trucking organizations so their members could track and manage fuel surcharges.

It was supposed to be a temporary solution until surcharges went away in another year (they are still here). It also had to run on just about everything, old MAC computers (old enough to actually be a MAC so multiple processor changes ago), Windows 98, ME, XP, not to mention OS/2.

There was no way in Hell I was providing support for free. I knew the market this was going into.

Those dang computer things.

What’s a backup?

Right click, what’s that?

Everything sold retail in the past decade came bundled with some form of “Office” suite. Lotus SmartSuite, WordPerfect Office, Microsoft Office, etc. All of them had built in tools to use/fix XBASE files. Yes, I could have written something really cool using some Java specific database which “might” have worked on all those platforms, but a DBF file using one of the common XBASE formats ensured support would be one email asking which office suite they had then they could be sent a canned email (or pointed to a link if it became a problem) about how to use that suite to fix the file.

So, DBF library which didn’t have to be either purchased or licensed (not getting paid to do this, remember?). Probably need to develop with a quite old version of Java to ensure broadest target platform acceptance. That lead me to the XBASEJ library. It only had a few “expert friendly” example programs for a “tutorial.” I took notes digging my way through and fixing a few bugs in the library. When my application was done I turned those notes into a book.

The Insight

The spherical cow believed I should have used a recent pure Java relational database “because they are easier on the developer.” College professors should never be let out of a University.

The Java on OpenVMS book was written in 2006 and the XbaseJ book in 2010. Part of the incentive for releasing the XbaseJ book to the project was to contribute more to the OpenSource world. The larger part was a hopeless attempt to bring more young developers to VMS even though it was and still is in a death spiral. I think you can all see just how ludicrous it is to talk about using a Java only relational database which happens to be working good in 2019 in a 2010 app where the database either wasn’t a gleam in the eye or was buggy as Hell.

Initial sales of the Java on VMS book tended to calendar lag XbaseJ downloads.

xbasej download stats
http://www.logikalsolutions.com/wordpress/wp-content/uploads/2020/02/xbasej-download-history.png

I never bothered to dig into what the conversion rate was because there are so many places people pull the stuff down from. Despite the PDF being a free part of XbaseJ

1.9K views on Scribd
722 reads of xbasej book on free-ebooks
Some of the spherical cow’s academic cohorts even built classes around it yes, classes plural.
987 views on this slideshare site

getfreeebooks isn’t polite enough to post download rate nor does it tell me who “John” the poster was.

Another site hosting the book without showing reads/downloads

neither does OpenLibrary.org

217 on Wattpad

ScribD used to be a good indicator, but not anymore.
Logic book 50 page preview has 20 views on ScribD but over 2K downloads on Free-Ebooks

122 views of 51 page Java on VMS preview

32K views of 42 page preview “John Smith – Last Known Survivor of the Microsoft Wars

It appears ScribD periodically resets counters. There was a time when “Infinite Exposure” had north of 14K. Maybe the reset happened when ScribD changed hands? Maybe ScribD never changed hands and that is just a story circulating among authors?

So, when all of these kids find themselves needing information on JNI they can scour the Internet for “free” information which is many times wrong or they can look to a book by an author they are familiar with. I used to even point them to Death Row Cluster for a free account. That’s gone now. Maybe some find this page?

Maybe they just read the book trying to figure out what they can steal for the current project?

Some of the people buying it are people writing Java on some other platform and really liked “John Smith – Last Known Survivor of the Microsoft Wars” and want to find out a bit about this OpenVMS system talked about in it.
https://johnsmith-book.com/

Btw. Thanks again to whoever sent the image of their Tabpole (ALPHABOOK 1) which is the computer on the cover. If you find yourself in the states, I do owe you a drunk. My making it to the U.K. seems to get farther away every year.

The Reality

The reality is you don’t choose Java to build a robust high performance system. You choose Java when you are trying to toss something extremely low cost out the door. Companies choose Java when they are looking to pay developers $10/day.

“Priced right” is the only qualification that matters.

Just how many tens of millions of dollars have your “priced right” developers cost the business? Ah, the world will never know because you always leave that line off the spreadsheet.

Well, we know one sale they cost Northern Tool. Probably thousands of others as well.

Norther Tool Java error image
Java error coming back from PayPal

I can’t believe that was a one-off. What I can believe is a worthless AGILE development environment (there are none worthwhile) hurled a hand polished turd into production before leaving for the weekend.

I mean nobody who uses tools for personal projects ever works on said personal project on a Saturday. They would never find a bolt rusted in place in too tight of a space for grinder or torch necessitating use of a hammer bit prior to the much more painful step of right angle drilling the thing out.

Probably really was “just my order” that didn’t come back from PayPal correctly, right?

Qt – Printing – Taxes – Pt. 4

center headingBefore I get into more coding on this topic, I need to cover some remedial information. The first is how we center a heading. Even when we had printer spacing charts we would write the text on scratch paper then put a slash every two characters, counting spaces as characters then we would count the slashes. When working with narrow form we would subtract the number of slashes from 40, with wide form it was 66. That gives us the position of the very first character. Once again, COBOL made this simple.

cobol header definition

 

Things tend to get less obvious if you are using C++ and trying to use the approved Qt methods of building a string.

report header cpp

That’s why the early xpnsqt version built the report heading this way.

report heading original

It’s a bit more human friendly. In the days of C and even early days of C++ developers would just use sprintf() with a format string. Admittedly, it got ugly. More of us switched to the example above because even a junior still in school developer could fix a spacing problem. QString does provide apsrint but we are told not to use it.

sprintf warning

There is a new new new approved method as well.

new new new way

Honestly COBOL is starting to look like a higher level language for reports, probably why COBOL will outlive Java and every scripting language in vogue today.

Many Qt developers try to get around such things by writing html files. At first blush it doesn’t seem too horrible. Headings don’t get too complicated.

html page heading

You will note the use of tables to control positioning. The knee-jerk sizing width 100% really bites you if someone clicks the full screen button though.

html full screen

I don’t know about you but “Total” kind of disappears for me. It’s also very difficult to follow the line across the screen.

The real killer is dealing with all of the tables because that is your only real method of creating column alignment.

html detail

That funny looking piece of code from 419 to 423 creates the blank row between category total and grand total lines. In theory a single string of “<tr></tr>\n” should have worked, but not in all browsers. Keep that in mind. It may look perfect in your application, but if you don’t delete the file someone is going to try looking at it in their default browser if it has a .html extension. You need to keep in mind another thing before clutching html as “the solution.” Much of it is going away with html 5.

html differences

 

You can follow the link to read up on everything disappearing from <td> when the browser supports only html 5. I included this snippet because the code made heavy use of align to make the report line up. Still, forcing the font to Monospace 9 point allows creation of a passable report for this purpose.

report image

You will note the page breaks occur as expected. Yes, there is a touch extra space at the top of the second and subsequent pages. It can be fixed and it is good enough for this example.

We need to look at just how bad things can get before I end this post. Click this link to be taken to the Edgar database for Oxford Square Capital Corp. (OXSQ). I gave you the company name in case the Edgar database moves or something. You will see a page looking much like this.

Edgar filing

Click on the 10-Q html document and scroll down to the beginning of page 2, “CONSOLIDATED SCHEDULE OF INVESTMENTS.” It should look something like this.

10-q

 

Click your back button then click on the complete submission text file. Search for “consolidated.” You should find something like this.

consolidated html

Nice huh? If you go back to the top and search for “T04” you can the later point in the file where they wedged in the data.

Our discussion for today is over. In case I don’t get back to this before New Year’s Eve, have a happy happy!

 

Which programming language offers the best job market?

I got sucked into a discussion on Reddit with this very question. No, I don’t hang out on Reddit. I wouldn’t even go there but a couple of technical writing crawlers periodically drop an email with links to things there. So, let’s get a few things out of the way up front:

  1. There is no “best language to learn” when the question is asked in a vacuum.
  2. There are many different job markets and industries which use the same programming languages, but they don’t advertise on Indeed or Dice or the general mainstream job boards.
  3. Most advertised = lowest wage.

Before you think about learning a language and beginning a career as a programmer you really need to take a course on programming logic. Many schools either don’t offer it or they completely ruin their students by teaching PASCAL in the class. The students end up learning PASCAL instead of programming logic. I understand. Kids today don’t want to flowchart and pseudo code but that is where you have to start if you are going to be any good. I wrote a book on logic years ago. Once you spend a full semester or year solving larger and larger real world problems by just drawing out the logic, you can pick up any 3GL in a few days. Honestly. You already know how to solve the problem and only need to figure out the syntax of the current language. You can jump from COBOL to BASIC to FORTRAN to C to DIBOL with relative ease because the logic and stepwise refinement are the same no matter the syntax.

Yes, logic books are thin, but you cannot skim them. You really need to sit with a small group of people drawing and writing the solutions for the exercises because a small group of people will generate different viewpoints and should ultimately provide a better solution.

“A programming job” is also a bad phrase people toss about without putting much thought into it. Ask instead “What type of life do I want?”

Do you want programming to provide you with most evenings and weekends off?

Well, you aren’t going to have that at a startup or most Web companies. That will only come from a major corporation which happens to use programs to do their real work. From there poke around to find major corporations claiming to offer that type of life for their developers. If they have Intern programs (most of the big ones do) you can inquire from the Intern contact what types of languages and skills they look for in programmers and proceed accordingly. Best if you find at least 3 which have some overlapping skill requirements. While they may have some trendy Web skills needs, most of it will be COBOL and C++ because they will have large ERP and WMS packages from vendors like Oracle and SAP. You won’t be “programming in a language” as much as “learning a package written in a language.”

Be warned that most of these companies will try to start you off somewhere between $30-60K. They have been bringing in tons of H1-B workers and paying them nothing. They will also try to place an arbitrary earnings cap on you well south of $100K unless you get a worthless MBA. Time off for friends and family has to be purchased with earnings potential.

Do you want to work 7 days per week 14-20 hours per day for years on end in some vain hope at becoming rich?

You are looking for a startup. There are several Web sites out there which focus on listing jobs exclusively with startups. I forget their names as I avoid them. Initial pay will be low because they will dangle free soda, lunches and stock options in front of you. Keep in mind the stock is worthless if the company does not go public and most startups fail. You won’t find the skills they want searching Indeed or Dice or any of the major job boards. You have to do a Web search for “startup jobs” and wind your way through a few sites. When you are 20-something startups can be cool. There is always the dream of being the next “it” thing. When you hit 30-something it’s time to take a serious look around. If you are still driving the same car you had in college or cannot afford a reliable car and insurance, you need to move into the real world. You no longer have any youth left to misspend.

Are you a closet hardware geek who really loves playing with your Raspberry Pi or Beagle Board?

Those products are great cheap learning devices for people wishing to write device drivers and assemble BSPs (Board Support Packages). For them you will be learning C, Bash shell scripting and a touch of Python. Some firmware is still written in Assembly language but not drivers. This field has too major forks, bare metal coders and driver coders. Bare metal coders have no OS. They are writing things like UBOOT and what we used to call BIOS but now is called UEFI. If you are not working with assembly you will be working with an incredibly stripped down version of C.

Do you think it would be cool to be part of a team which develops medical devices? I wrote roughly half of the user interface code for this device. That code was C++ and Qt and we ran on a highly customized Embedded Linux. You will also need to read up and learn about remote debugging. Most major Linux distros have a version of the Qt development tools in their repos. You can start by learning C++ and Qt on your desktop/laptop then learn about cross compiling for a Raspberry Pi or Beagle Board.

Despite all of the Web programming Google is famous for, they have a lot of low level OS coders. They are currently abandoning Andriod and working on Fuchsia.

Cannonical is also in the process of abandoning Linux for their own flavor of Fuschia. Don’t worry. What was Ubuntu will be rebranded Windows and shipped by Microsoft. It’s already started. When you open up a bash shell on Windows 10 it is running a flavor of Ubuntu.

Most universities can only teach you the fundamentals of software development and some of the languages needed by the largest corporations. A good many don’t even teach COBOL anymore yet it is still the language with the largest production code base on the planet and will be, pretty much forever. The Silicon Valley crowd create and discard a new “language” every few weeks. You cannot go to school to learn what they want to hire now and you cannot take more than 2 days to learn it because it will be an obsolete skill in 3 weeks.

Know this. When you search on Indeed or Dice or some other general IT job site, the languages you see the most are also the lowest paying. There has been a tidal wave of H1-B workers arriving in America. Most are Java or .Net. Despite the much talked about $60,000 threshold during the election, the bulk are paid around 1/3 of that. Yes, you can “always be employed” but, you will start off around $30K/year and 10 years later when your salary approaches $80K that will be as much as you ever earn. If you are okay with never being able to own a home in a nice neighborhood, then go for it.

Yes, you have all seen the salary surveys showing Google and others hiring programmers for around $150K right out of school, but you cannot live on that out there. Google has had to start providing housing. Other Silicon Valley firms are also buying/building living quarters for employees because you cannot get your own place anywhere near the campus for what they pay.

Speaking as someone who has written multiple books on Java, I can honestly say Java is a dying language. It never lived up to its promise and architecturally it can never be made secure. In a world where identity theft and massive data breaches pepper the daily/weekly news, that’s a big issue. No, I’m not going into a lengthy discussion about it with people who cannot yet program. You can go searching for how Java was praised in the early days because of the way it uses URLs to locate classes a program needs anywhere on the Internet. Then sit and think about that phrase.

Yes, some companies are trapped with Java and refuse to bite the bullet. They will continue using Java until they go out of business. This trapped number isn’t anywhere near the size you wish to believe. This trend started in 2010.

Now we have to talk about the definition of “best.”

If your definition of “best” is there will always be a job and you don’t care much about money, IBM Mainframe COBOL with CICS and JCL. Yes, most of the gigs will only pay $40/hr but payroll and accounting systems running COBOL will continue to run long after humans cease to exist. You can also learn Java and make even less competing with $15/day off-shore labor.

If your definition of “best” is the highest billing rate ever, then you are looking for niche tools and markets. C++ Qt on Embedded Linux or Drupal. Boring and difficult device driver coding in C for various embedded targets. BSP (Board Support Package) work. Whatever tool some startup with massive venture capital is pushing into the market this week.

Whatever is hot as a Web programming language today will be forgotten next week. That’s the way the Web is. Scripted languages come and go. Two years ago Ruby on Rails consultants were billing out at over $200/hr and most are unemployable now. Scripted languages have no staying power in the market because there is no commitment to them. You don’t develop a high volume core business system in a scripted language because the processor cost of the interpretation is simply too high.

Think about it. ADP is one of the biggest payroll processors in America. Do you really think they could chew through that many payroll records each month using Java or some other scripted language? Keep in mind all of the precision problems with floating point types. Packed Decimal and BCD (Binary Coded Decimal) aren’t just legacy data types to save storage space. They also existed to solve precision problems which crop up with payroll, mortgage and other financial calculations. When you use IEEE floating point types:

1.0 - 1.0 != 0.0

Most of the time. You can search the Internet for all kinds of war stories when trying to do integer math with floating point data types. This is a problem made worse by JavaScript and other newer scripting languages which have a single numeric data type, double precision floating point. You will find more than one young programmer posting pleas for help because 3 – 2 did not equal 1.

How Far We’ve Come – Pt. 2

We need to establish a time frame before I start showing any code. Yes, you can go visit Source Forge to pull down what is there if you are well and truly desperate to view it. This portion is more about the journey than the code.

xpnsqt

The xpnsqt program was originally written around the time IBM sunset OS/2 which, according to this article, spanned the time frame between March 12, 2003 and December 31, 2004. Foundations of Qt Development came out in 2007 and C++ GUI Programming with Qt 4 came out in 2006. Both of them discussed QSqlDatabase. Ordinarily I would just hit the help key in QtCreator for QSqlDatabase. It would then take me to a help page which would say something like “feature/class was added in version blah.ha. Funny thing happened when I tried that today.

qtCreator image

Couldn’t find it on that page. Searched on-line in the 4.8 documentation and didn’t find any mention of when QSqlDatabase class was added. I don’t remember it being in Qt3 but I didn’t do that much with Qt3 because the message boards said Qt4 was going to be a night and day difference.

Point and Laugh

At any rate, now that most of you have some idea just how long ago this was and the fact it was my first “real” Qt program, it is time to let everyone point and laugh.

main.cpp

/****************************************************************************
 * Originally created by Roland Hughes at Logikal Solutions.
 * Project is being released under GPL2 license.
 *
 * At some point in the future either Logikal Solutions or Roland Hughes
 * may elect to publish a book with this original source code in it.  If
 * the book is written it will be part of "The Minimum You Need to Know"
 * book series.
 ****************************************************************************/
#include 
#include 
#include 
#include 

#include "XpnsLogonDialog.h"

int main(int argc, char *argv[])
{
    int i_x;
    QString qtDbName;
    QTime theTime = QTime::currentTime();

    QApplication app(argc, argv);

    {
        QString driverName = "QPSQL";

        //
        //  Set up information for driver and see if driver is available
        //
        qtDbName = "xpns" + theTime.toString("hhmmsszzz");
        QSqlDatabase db = QSqlDatabase::addDatabase(driverName, qtDbName);
        if (!QSqlDatabase::isDriverAvailable( driverName)) {
            QMessageBox::critical( 0, "Missing PostgreSQL Driver",
                                   "The Qt driver for PostgreSQL "
                                   + driverName
                                   + " is not installed.  You must install it before running this program",
                                   QMessageBox::Ok);
            db = QSqlDatabase();        //  reset to avoid warning
            return 0;
        }

        XpnsLogonDialog *xpnsLogonDialog = new XpnsLogonDialog( 0, qtDbName);
        xpnsLogonDialog->show();
        i_x = app.exec();

        qDebug() << "About to delete dialog";
        delete xpnsLogonDialog;
        qDebug() << "Dialog deleted, now clearing database";

        db = QSqlDatabase::database();  // clear connection to avoid error
    }  // end scope of logon dialog

    QSqlDatabase::removeDatabase(qtDbName);

    return i_x;
}

Looking at some of the comments in here brought back memories which were a long way from good. I’m sure many of you are freaked seeing the {} block enclosing the bulk of the program and the call to removeDatabase() outside of the block. When I saw the whole “clear connection to avoid error” comment it kind of all came back to me.

One thing I really hate about writing stuff like this for my blog, besides never getting paid for it,  is not being able to highlight code. There is probably some HTML markup tags which would let me set the background color, but the WordPress editor should make it a whole lot easier. Due to the way blog themes change the display of preformatted text I cannot even be sure line numbers will display.

The Logon Dialog

While I’m certainly not going to post all of the code in this series, we need to look at a couple more source files (kind of the worst) before we go too far in the discussion.

XpnsLogonDialog.h

/****************************************************************************
 * Originally created by Roland Hughes at Logikal Solutions.
 * Project is being released under GPL2 license.
 *
 * At some point in the future either Logikal Solutions or Roland Hughes
 * may elect to publish a book with this original source code in it.  If
 * the book is written it will be part of "The Minimum You Need to Know"
 * book series.
 ****************************************************************************/
#ifndef XPNSLOGONDIALOG_H
#define XPNSLOGONDIALOG_H

#include 
#include "ui_XpnsLogonDialog.h"
#include "Xpnsform.h"

class XpnsLogonDialog : public QDialog, public Ui::XpnsLogonDialog
{
    Q_OBJECT

public:
    XpnsLogonDialog( QWidget *parent, const QString &qtDbName);

    bool getConnectionStatus() { return m_connectionStatus;}
    int getTaxYear() { return m_tax_year;}
    bool useCalendarYear() { return m_calendarYear;}
    QString getActualDbName() {return m_actualDbName;}

private slots:
    void attempt_postgresql_logon();
    void on_userNameLineEdit_textChanged();

private:
    bool m_connectionStatus;
    void create_database( bool dbCreated);
    void ask_copy();
    void prompt_prior_year();
    void copy_prior_year( int year);
    bool  test_exists( int year);
    int m_tax_year;
    QString m_qtDbName;
    QString m_actualDbName;
    bool m_calendarYear;
    Xpnsform *xpnsForm;
};

#endif

Multiple Inheritance

Take a good look at that class definition. How many of you remember every class based on Qt and a UI file having to perform multiple inheritance? Come on, be honest! That all changed when the infamous “they” tried to make Qt usable by Java developers so they could finally abandon Swing. I and most others railed against that, but we lost. No, I won’t empty my colon on it again. You can buy a copy of this book if you want to read that rant. Let’s just say Java banned multiple inheritance and then had to bring it back with “interfaces.” They also banned the goto statement but the labeled break statement and a few other such things. The really bad parts in C and C++ existed for reasons. You can’t successfully remove the bad parts until you remove the reason for them.

Yes, if I don’t run out of time with this series I will rewrite the application from scratch using the more current approach to all things Qt. I believe you need to know where we came from because at some point you are going to encounter heritage code someone wants you to change without rewriting. If you don’t believe that you are either too young or haven’t been coding long enough. Every 1-2 years I get phone calls for a contract at a medical device company where they are looking for Qt 3 only. They have some device they want to make one small change in. If you rewrite they have to go through a very lengthy FDA approval process if the consultant just tweaks they can go through a much shorter and cheaper approval process. A rewrite means it is a “new device” while a change means it is an “updated/changed device.” No those aren’t the correct terms. I don’t remember the correct terms, but those work for the general audience.

Design due to QSqlDatabase “feature”

The convoluted design came about due to a “feature” with that version of Qt and Postgresql. In order to run like a mainframe/midrange application a database login dialog needed to pop up. Since I was going to release this as OpenSource I needed to have the information splash dialog pop up first so people too lazy to read a README.TXT would actually know something. First time users would be somewhat screwed. There was no way around having to manually enter categories. I didn’t want to ship with a predetermined set of categories. N year users would have it great because the login dialog would create the database for the tax year and offer to copy category information forward.

Our first “feature” reared its head during the first cut where I called the dialog exec() method. Even though QSqlDatabase was supposed to globally keep track of connections, when the dialog which created the database went away, so did the connection. In order to keep an entry you had to keep one reference alive. This left me with some really unenviable design choices.

  1. Pass a pointer to the db variable into the constructor of the dialog
  2. Pass string references for username and password and database year duplicating the connection code
  3. Derive from QApplication splitting all of the login functionality into methods within that class which would be executed when the event loop started.
  4. Doing something similar with a QObject class.

Our second and third “feature” reared its head when I didn’t have {} around the life of the db variable.  If one didn’t clear the database connection a runtime error would spit up in the terminal/debug window about object destroyed with active connection or something like that. Simply clearing the connection wasn’t enough, or at least it wasn’t instant enough. Calling removeDatabase() immediately after the clear with the db variable still in scope would cause more errors to be thrown about removing a database with an active connection.

Growing Pains Leave Warts

Yes, they were growing pains. Yes, most of these oddities have long since been cleaned up. Yes, this code still compiles and runs, I use it every time tax season approaches. Yes, you are going to encounter decade plus old code because it serves its purpose and rewriting isn’t free.

Many years ago I worked on a trading floor system for a stock exchange. The original “temporary” system was written in BASIC on a PDP 11 computer. Years later it was “temporarily” ported to the VAX hardware, then the Alpha, all the while the “permanent” trading floor system was being designed and a platform being chosen. This temporary system got pretty much rewritten when the U.S. stock market switched from trading in fractions to dollars and cents. That stock exchange got rid of its trading floor a few years ago. I’m told that “temporary” system went away with the trading floor but I would not be surprised to learn the automated portions of that system are what is running the exchange today.

Short Term “solutions” = Long Term Problems

Keep in mind that Y2K happened because “short term” solutions which made sense in the 1970s and early 1980s which were supposed to be replaced once storage and software became cheap enough were still in use near the year 2000. Read this page to learn what other Y2K like events are in your future.

Cast no stone at decade plus old code. We can always insult the ability of the developer but sometimes it is the ability of others which forced an ugly choice.

<Previous-part Next-Part>

Related posts:

Where Did My QDebug Output Go?

MOC Parse Error at “std”

KDE Neon – Distcc and Qt

CopperSpice Experiments

QtCreator – No qmlScene installed

So You Can’t Get Your Models to Work with QML?

QT Database book

Subtle But Deadly Java Date Bug

All of the college professors who have never worked in the real world oooh and aaahhh over Java. I’ve never been a big fan of the language, in part because it is one of the most inefficient languages on the planet, but mostly, because any tool in the marketplace with that much hype surrounding it generally turns out to be a shiny new turd. (How many of you are old enough to remember PowerBuilder? How about all of those different “Case Tool” products which were going to completely eliminate programmers?)

I was forced to use Java on a recent project and came face to face with a known bug which has been allowed to exist for a very long time. Please examine the following:

badDateBug.java

 

  1. import java.io.*;
  2. import java.util.Date;
  3. import java.util.Calendar;
  4. import java.text.*;
  5. public class badDateBugs {
  6. public static void main(String args[]){
  7. DateFormat screenFmt = new SimpleDateFormat( “yyyy/MM/dd”);
  8. DateFormat badScreenFmt = new SimpleDateFormat( “yyyy/mm/dd”);
  9. String original_date_str = “2008/09/01”;
  10. System.out.println( “Original date ” + original_date_str);
  11. System.out.println( “Result when good date format string used”);
  12. Calendar d1 = Calendar.getInstance();
  13. try {
  14. d1.setTime( screenFmt.parse( original_date_str));
  15. d1.add( Calendar.DATE, -7); // last week
  16. System.out.println( “One week prior was ” + screenFmt.format( d1.getTime()));
  17. } catch( ParseException p) {
  18. System.out.println( “Error parsing date1”);
  19. }
  20. Calendar d2 = Calendar.getInstance();
  21. System.out.println( “\n\nResult when bad date format string used”);
  22. try {
  23. d1.setTime( badScreenFmt.parse( original_date_str));
  24. d1.add( Calendar.DATE, -7); // last week
  25. System.out.println( “One week prior was ” + screenFmt.format( d1.getTime()));
  26. } catch( ParseException p) {
  27. System.out.println( “Error parsing date2”);
  28. }
  29. } // end main method
  30. } // end class badDateBugs

 

You probably don’t even notice the subtle typo which causes this problem. Listing lines 11 and 12 contain it. All you have to do is enter “mm” instead of “MM” and this bug rears its ugly head.


roland@logikaldesktop:~/java_date_example$ java badDateBugs
Original date 2008/09/01
Result when good date format string used
One week prior was 2008/08/25

Result when bad date format string used
One week prior was 2007/12/25
roland@logikaldesktop:~/java_date_example$

 

You will notice that none of the much vaulted “ exceptions” were thrown. The parse engine simply went on its way, and Java was happy to give you the wrong answer without any indication of a problem. Nice, very nice.