return to OCLUG Web Site
A Django site.
November 7, 2012

Michael P. Soulier
msoulier
But I Digress
» 21st Century C

I saw a sale from O'Reilly Publishing tonight on an new ebook for 21st Century C. I have a good history with O'Reilly and C programming, so it caught my attention.

When I was in University, Practical C Programming taught me much more than any of my professors, and Unix System Programming for System VR4 taught me a great deal more about programming C on Unix/Linux. After reading those books, I became actually comfortable in working in C for all of my assignments, and other students kept coming to me for help until I had somehow become a local C expert. Amazing what a good investment in reading material will do, not to mention actually reading said material. Another friend in University taught me that. He told me not to ever begrudge the cost of a book that helps you get better at what you do. I've applied that lesson ever since.

I relied on O'Reilly for my first introduction to C++, with C++, the Core Language, which finally explained to me where some of my memory leaks were coming from, by explaining copy constructors and assignment operators. I turned to another book to finish most of my C++ education, but O'Reilly got me started.

Since University, with the wealth of information on the Internet, I haven't bought many C books, but I did pick up Advanced Unix Programming, second edition, on the recommendation of a coworker, and he did not lead me astray, the book is excellent. Mind you, I still haven't finished reading it. I seem to buy books faster than I read them these days.

Maybe one day I'll take a little vacation just to read. Anyway...

Looking at the new O'Reilly book, it looks like it has many practical ideas for someone living with C from day to day, and should also provide a nice introduction to the new C11 standard, just released in December of last year. Hopefully it'll sharpen my skills like previous O'Reilly books have. I'll try to post a full review once I've finished it...err...if I finish it.

I will stop buying faster than I can read. I will stop buying faster than I can read. Maybe if I keep repeating that, it'll sink in.

August 6, 2012

Michael P. Soulier
msoulier
But I Digress
» Custom request headers in Python

Just to be fair, here’s the same example in Python, batteries included.

#!/usr/bin/python

import httplib

conn = httplib.HTTPConnection('digitaltorque.ca')
params = {}
headers = { 'X-Bender': 'Bite my shiny metal ass!' }

conn.request("GET", "/", params, headers)

response = conn.getresponse()

print response.read()

Not too painful.


» Custom request headers in Mojo

I was just playing with the latest version of Mojolicious, while writing an HTTP client, so I’m using `Mojo::UserAgent`. Pretty cool, although I still think the documentation could be so much better.

I wanted to insert a custom request header and came across this, so I thought I’d share. Apparently it’s done via the event system, very nodejs-like.

use Mojo::UserAgent;

my $ua = Mojo::UserAgent->new;

$ua->once(start => sub {
    my ($ua, $tx) = @_;
    $tx->req->headers->header('X-Bender' => 'Bite my shiny metal ass!');
    print 'Request: ', $tx->req->url->clone->to_abs, "\n";
});

my $tx = $ua->get('http://digitaltorque.ca');

print "Response body:", $tx->res->body, "\n";

In fact, it’s so nodejs-like that I’m thinking, who cares about nodejs? I already know Perl.


May 10, 2012

Michael P. Soulier
msoulier
But I Digress
» Post-transaction events in Django

So, at work I’m using Django quite a bit, and I ran into a problem where I need the database transaction to be committed, and then I need to trigger additional server-side code that will act on that data.

Putting all of this into the view function with a manually managed transaction sucks, far too much code. There’s transaction middleware, but by then your view function has returned. What to do?

Simple. I added my own middleware, and I return a new property that I tag into the HttpResponse object. Python is flexible enough to allow this hack.

MIDDLEWARE_CLASSES = (
    'teleworker.lib.middleware.MslEventMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.transaction.TransactionMiddleware',

So in my MslEventMiddleware, I look for a new property in the response, and if it’s present, I execute the requested command, which will happen after the TransactionMiddleware has called commit.

    def process_response(self, request, response):
        if hasattr(response, 'mslevent'):
           msl.event(response.mslevent)

Simple enough. Although a real post-processing API in Django would be helpful.


May 7, 2012

Michael P. Soulier
msoulier
But I Digress
» Eclipse is still mean to me

So in working on Android programming I’ve been working through O’Reilly’s book on the subject, or one of them at least, and I’m at the stage of including the jtwitter library to talk to twitter. So, I add it as a library in eclipse, and everything builds, and then when the app runs I get a spectacular backtrace with a NoClassDefFoundError exception on the very library that I just included, winterwell.jtwitter.Twitter. Umm, ok. Is it added or not?

Trying a variety of configuration changes, I’m unable to get it working, but I finally came across this post on stack overflow about moving the jar to the top of the classpath order. So under Build Path -> Order and Export, I move the jtwitter.jar to the top of the list.

Voila. It’s working now. Seems rather braindead to me, as should Java not simply search the entire classpath until it finds the the requested import? I don’t understand why this works, and that isn’t good, ’cause it’ll just happen again. If someone has an explanation I’d appreciate it.

Cheers.


May 3, 2012

Michael P. Soulier
msoulier
But I Digress
» Eclipse, you could be nicer to me

So I’m playing in Eclipse going through Android development HOWTOs. Yes, I know. Java. Thankfully there’s a scripting layer for Android, but I want to learn it all before I choose a toolset for a particular problem. Besides, Java ain’t all bad, just mostly.

Anywho, I fired up the HelloWorld tutorial, made my project, and very quickly found that Eclipse’s wonderful generated code that was going to save me all this work of typing Java didn’t compile. I got, “main cannot be resolved or is not a field”. Huh? The main it’s referring to is my main.xml file (can’t have too much XML eh Java?) describing the Android UI layout, under res/layouts/main.xml. Invoked through the ubiguitous Android R object. What do you mean it’s not there, you stupid machine??

So I do what any modern programmer does, after swearing at my screen repeatedly, I look up the error in google, and voila, I’m not alone. This post was particularly helpful. Apparently, it’s an Android SDK issue, which Eclipse invokes to create the project. Yo, Google! Get off your butts and fix it! Seems to me that you have time…


November 18, 2009

Michael P. Soulier
msoulier
But I Digress
» Java sucks

Well yes, we know this already from the way that it makes easy things hard, and hard things nearly impossible, but it’s rarely been captured with the eloquence that I find in these wonderful quotes on the topic.

And yet, as cockroaches are to humans this technology/language/marketing campaign continues unabated until having java on one’s resume is a requirement to find a job through some ignorant HR department that has no idea what is is. Like the job posting I saw a few years ago for a java programmer with 10-years experience when java was only 7 years old. Luck with that.

My favourite quote:

If Java had true garbage collection, most programs would delete themselves upon execution. — Robert Sewell

My boss asks me occasionally why I don’t use Java, and I tell him that I have many tools in my toolbox, some good and some bad that I bought on impulse due to good marketing or simply because they were new. Java is like my trendy flip-grip pliers from Crappy Tire that try to be both clippers and needle-nose pliers, but suck at both jobs. I don’t hate the tool, but I certainly don’t reach for it often, and I’m thinking of throwing it out.


June 30, 2009

Pythian
pythian
» Windows PowerShell for the SQL Server DBA

Most people think Windows administrators make a living with their right-hand—you know, right-clicking and left-clicking the user interface to get things done. While anybody can do that in Windows, the real value comes in when you no longer need to rely so much on the user interface but instead write scripts. Lower total cost of ownership is achieved when the administrative costs are kept low, and this is where Windows PowerShell comes in.

I’ve spent a fair amount of time writing VBScript scripts to administer Windows servers and workstations and automating repetitive tasks. One reason for me moving into Windows PowerShell is its roots in the Microsoft .NET Framework, as I have done a fair amount of .NET programming. But what is Windows PowerShell anyway?

Windows PowerShell is an extensible command-line shell and an associated scripting language built on top of the .NET Framework v2.0. It was released in 2006 and is currently available for Windows XP SP2/SP3, Windows Server 2003, Windows Vista, and is included in Windows Server 2008.

PowerShell will be included as a common engineering criteria (CEC) in future releases of Microsoft server products, making it a must-learn for Microsoft server administrators.

Administrators (DBAs included) have been using scripting to automate administrative tasks with scripting languages like DOS batch, VBScript, Perl, and a few third-party tools like KiXtart and WinScript. Windows PowerShell complements the administrators’ existing scripting toolkit to easily manage and administer Windows workstations and servers and other Microsoft server products as THEY are being built using the .NET Framework.

Although it is designed for operating systems, Windows PowerShell can be used to administer SQL Server 2005 instances and higher, as Server Management Objects—the object model used to manage SQL Server 2005—are built using the .NET Framework, thus exposing the object model in PowerShell. And since SMO is compatible with SQL Server 2000, you can administer SQL Server 2000 instances using Windows PowerShell. SQL Server 2008 even ships with its own PowerShell snap-in.

No wonder it makes sense to learn a thing or two about Windows PowerShell. Besides, I’ve seen Windows administrators being “forced” to do SQL Server DBA tasks even without knowing what T-SQL is. Windows PowerShell makes it a level playing field.

I will be posting a series of blog posts on getting started with Windows PowerShell, and how any Windows administrator can use it for their day-to-day tasks. In the process, I’ll also cover how to use Windows PowerShell for administering SQL Server instances.

April 9, 2009

Michael P. Soulier
msoulier
But I Digress
» Tftpy state machine overhaul

I just posted this news item to SourceForge.

I’ve decided that the state handling in tftpy is too difficult to maintain, and I’m ditching it. I’ve started that work in a private branch in Git.

First though, I’m going to merge all of the contributed patches into an experimental branch and push that to github. I’ll then rebase my state-machine branch on that and keep going.

It’s a big rewrite, so expect breakage in the short term. Contributed unit tests are welcome, I really need to flesh those out.

Cheers.

A merging I will go, a merging I will go…

April 7, 2009

Michael P. Soulier
msoulier
But I Digress
» Querying the db schema from SQLite

I’ve been trying to put together a migration strategy for SQLite that is not simply a bunch of versioned SQL fragments that are extremely difficult to backport.

The information is there but it’s not obvious. You can fetch the list of tables in an SQLite database with this little snippet.

SELECT name
    FROM sqlite_master
    WHERE type='table'
    AND NOT name='sqlite_sequence'
    ORDER BY name;

From there, you can simply loop on the table names and pull out all of the table columns and their types via

PRAGMA table_info($table_name)

I have some rudimentary code now in Perl that queries this and builds-up a multi-level hash of all of the tables, their columns and metadata. Pass that to each migration fragment and we don’t need a schema version anymore. Each migration fragment has enough information to conditionally do migration.

At least, I think it’ll work.

March 29, 2009

Michael P. Soulier
msoulier
But I Digress
» Where migration frameworks fail

At work I am using Django for a web-based management interface, using PostgreSQL as the database back-end.

Django does not yet come with a migration framework to evolve the database schema, so I wrote a really simple one, based on Rails migrations.

The system is simple. You put fragments of SQL code in separate text files at a predetermined location on disk, and prefix each one of them with a number, representing the version of the database schema. Your migration code also maintains a schema table in the database to keep track of the current versions, and whether the last migration attempt was successful.

So, on upgrade, if the schema version is 30 and the fragments on disk to up to 43, then you run 31-43, wrapping each in a transaction, and rolling-back at the first failure. So, if 41 fails, you’ll get as far as version 40, store an error, and you’re done.

Sounds ok, right? Well, if this is for a single database instance, sure. Unfortunately for this scheme, the product that I work on has roughly 6000 instances in the field in servers all over the world, with less than half running the most recent release. So, stream management becomes an issue. And stream management is something that I find that most of these modern frameworks overlook.

What if a bugfix that I just made on the HEAD has an associated schema change, and I want to backport that fix to the previous maintenance release? If the last schema version of the previous release is, say, 16, and I just added migration fragment 62, then we have a problem. And this is it.

Every migration fragment is dependent on the success of the previous one.

So, I can’t just backport fragment 62, I’d have to backport 17 - 62. Yikes.

The solution is actually simple, and it’s something that the SMEServer’s native databases do already. Each migration fragment is not raw SQL, it’s code, in this case Perl, but it could be anything. So, instead of blinding executing the migration fragments in order, you blinding execute the migration code fragments and let each and every one determine whether they need to do their particular job.

Need to make a varchar(512) a varchar(1024)? No problem, just check it’s size now, and if it’s 1024 then you don’t need to do anything. Now each fragment doesn’t depend on the one that came before it, and you can safely backport only what you wanted to backport.

So how do we know what the database, in this case a relational database like PostgreSQL, looks like now? As it turns out, the standard does have some support for that, and it’s in the information_schema.

This would fetch all of the column names from a table called “clients”:

select column_name from information_schema.columns
     where table_name = 'clients';

And this would determine the current length of the character field in that table called “name”:

select character_maximum_length
    from information_schema.columns
    where table_name = 'clients'
    and column_name = 'name';

So, an ideal migration framework would provide this information to the migration fragments, to keep their job simple. Migration isn’t done constantly so we’re not that concerned with performance. Keep the code simple and bug-free.

Anyone feel like writing it? I suspect I may have to.

December 8, 2008

Michael P. Soulier
msoulier
But I Digress
» Java dependency hell

So, while I’m not Java’s biggest fan, I went ahead and built the sun-jdk package on my Gentoo system so I could have java applet support in Firefox, and occasionally write a little code in it (rare, but it happens at times).

It built quickly enough, with only 3 dependencies. So, I follow that up with a check of what it will take to build Ant, Sun’s horrible XML-based answer to Make (if you are being encouraged to hand-write XML, you’re using the wrong solution).

And, and emerge -p dev-java/ant turns up this!

Calculating dependencies... done!
[ebuild  N    ] virtual/jdk-1.6.0  0 kB
[ebuild  N    ] dev-python/pyxml-0.8.4-r1  USE="-doc -examples" 718 kB
[ebuild  N    ] virtual/jre-1.6.0  0 kB
[ebuild  N    ] dev-java/javatoolkit-0.3.0-r2  17 kB
[ebuild  N    ] dev-java/antlr-2.7.7  USE="cxx python -debug -doc -examples -java -mono -script -source" 1,774 kB
[ebuild  N    ] dev-java/ant-core-1.7.0-r1  USE="-doc -source" 6,683 kB
[ebuild  N    ] dev-java/libreadline-java-0.8.0-r2  USE="-doc -source" 76 kB
[ebuild  N    ] dev-java/javacup-0.10k-r1  USE="-source" 187 kB
[ebuild  N    ] dev-java/jakarta-oro-2.0.8-r2  USE="-doc -examples -source" 338 kB
[ebuild  N    ] dev-java/ant-nodeps-1.7.0  0 kB
[ebuild  N    ] dev-java/xml-commons-external-1.3.04  USE="-doc -source" 645 kB
[ebuild  N    ] dev-java/xml-commons-resolver-1.2  USE="-doc -source" 257 kB
[ebuild  N    ] dev-java/bcel-5.2  USE="-doc -source" 256 kB
[ebuild  N    ] dev-java/sun-jaf-1.1.1  USE="-doc -source" 123 kB
[ebuild  N    ] dev-java/commons-logging-1.1.1  USE="-avalon-framework -avalon-logkit -doc -log4j -servletapi -source -test" 187 kB
[ebuild  N    ] dev-java/ant-swing-1.7.0  0 kB
[ebuild  N    ] dev-java/jzlib-1.0.7-r1  USE="-doc -source" 50 kB
[ebuild  N    ] dev-java/junit-3.8.2-r1  USE="-doc -source" 451 kB
[ebuild  N    ] dev-java/ant-antlr-1.7.0  0 kB
[ebuild  N    ] dev-java/log4j-1.2.15-r1  USE="-doc -javamail -jms -jmx -source" 2,051 kB
[ebuild  N    ] dev-java/jakarta-regexp-1.4-r1  USE="-doc -source" 135 kB
[ebuild  N    ] dev-java/xjavac-20041208-r5  2 kB
[ebuild  N    ] dev-java/jdepend-2.9-r4  USE="-doc -source" 296 kB
[ebuild  N    ] dev-java/ant-junit-1.7.0  0 kB
[ebuild  N    ] dev-java/xalan-serializer-2.7.1  USE="-doc -source" 6,138 kB
[ebuild  N    ] dev-java/commons-net-1.4.1-r1  USE="-doc -examples -source" 224 kB
[ebuild  N    ] dev-java/ant-apache-resolver-1.7.0  0 kB
[ebuild  N    ] dev-java/jsch-0.1.37-r1  USE="zlib -doc -examples -source" 263 kB
[ebuild  N    ] dev-java/ant-apache-bcel-1.7.0  0 kB
[ebuild  N    ] dev-java/sun-javamail-1.4.1  USE="-doc -source" 387 kB
[ebuild  N    ] dev-java/ant-apache-oro-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-apache-log4j-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-apache-regexp-1.7.0  0 kB
[ebuild  N    ] dev-java/jython-2.1-r11  USE="readline -doc -source" 1,272 kB
[ebuild  N    ] dev-java/ant-commons-logging-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-jdepend-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-commons-net-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-jsch-1.7.0-r1  0 kB
[ebuild  N    ] dev-java/ant-javamail-1.7.0  0 kB
[ebuild  N    ] dev-java/xerces-2.9.1  USE="-doc -examples -source" 1,672 kB
[ebuild  N    ] dev-java/xalan-2.7.1  USE="-doc -source" 0 kB
[ebuild  N    ] dev-java/bsf-2.4.0-r1  USE="python -doc -examples -javascript -source -tcl" 293 kB
[ebuild  N    ] dev-java/ant-trax-1.7.0  0 kB
[ebuild  N    ] dev-java/ant-apache-bsf-1.7.0-r1  0 kB
[ebuild  N    ] dev-java/ant-tasks-1.7.0-r4  USE="X antlr bcel bsf commonslogging commonsnet javamail jdepend jsch log4j oro regexp resolver -jai -jmf" 0 kB
[ebuild  N    ] dev-java/ant-1.7.0  0 kB

45 dependent packages! OMG…I’ll just grab the Ant tarball from upstream and be done with it, thanks. Better yet, I’ll just use Make.

Java - 1
Simplicity - 0

September 18, 2008

Michael P. Soulier
msoulier
But I Digress
» Surviving in ClearCase

I’ve gone over my complaints about Rational (IBM) ClearCase in the past, as one of the worst SCM systems I’ve ever used. I haven’t contributed much on how to use it, so lets start here.

I’ve been working in Git for a while now, and been needing to make it relatively simple to get my changes from Git back into ClearCase. I have a collection of shell functions for working in a ClearCase snapshot view, and here’s what I’m currently using.

alias ct='cleartool'
	
# Find hijacked files
function ct-find-hijacked-dirs
{
    for i in $(ct ls -s -r -nxname | grep -v \.git)
    do
        if [ -d $i ]; then
            if ct ls $i | grep -q '\[hijacked\]'
            then
                echo $i
            fi
        fi
    done
}
	
# Find hijacked directories, needed to detect renames
# adds and removals
function ct-find-hijacked-files
{
    for i in $(ct ls -s -r -nxname | grep -v \.git)
    do
        if [ -f $i ]; then
            if ct ls $i | grep -q '\[hijacked\]'
            then
                echo $i
            fi
        fi
    done
}
	
# Find untracked files, although this only works when all
# files are checked-in.
function ct-find-untracked
{
    ct ls -s -r -nxname -view | grep -v \.git
}
	
# Check-out hijacked files
function ct-co-hijacks
{
    ct co -usehijack $(ct-find-hijacked-files)
}
	
# Check in all checked-out files
function ct-ci-all
{
    ct ci $(ct lsco -s -r -me)
    leftovers=$(ct lsco -s -r -me)
    if [ -n "$leftovers" ]; then
        ct unco -rm $leftovers
    fi
}
	
# Deliver to the default stream
function ct-deliver-all
{
    ct deliver -complete -force
}
	
# List all checked-out files
function ct-lsco
{
    # Show me what I have checked-out.
    ct lsco -s -r -me
}

My snapshot view coexists with a Git repository. My sync-up process is essentially…

git pull
ct-co-hijacks
ct-ci-all
ct-find-untracked
# manually add new files, etc
ct-ci-all
ct-deliver-all

Now I just need to figure out how to automatically detect file removals, adds and renames and automate syncing that up.

July 3, 2008

Michael P. Soulier
msoulier
But I Digress
» Clearcase woes, and some needed rebellion

I’ve been looking for ways of making life in Clearcase easier. This isn’t easy considering just how much clearcase sucks.

I’ve found that the only way to make this environment palatable is to work in other, superior version control systems. I’ve been working with Mercurial and Clearcase for a while now, and now I’m playing with Git for comparison.

It’s very reassuring that I’m not alone, in trying to make this workflow function, or in wanting to break up with Clearcase either.

I’ll post any tips that I pick up in making this work, assuming that I can build on others’ experiences.

July 1, 2008

Michael P. Soulier
msoulier
But I Digress
» Playing in Git-land

I’ve been playing with distributed version control systems for a while now. First Mercurial, and now Git.

While I don’t find Git nearly as friendly and intuitive as Mercurial, I’m slowly starting to get into it. While a superior interface is often sorely overlooked, with the misguided believe that a more cryptic one must be somehow superior, I am finding that Git contains more potential.

While I am forced to do work on Windows, Git on CygWin works quite well, and there’s always the option of simply using Samba and running Git in a remote Linux box. At least merging works in Git on Windows out of the box, while in Mercurial they don’t even bother to fall back to simple conflict bars when no merge tool is available. Sad.

The basics of push, pull, merge, etc., are pretty much the same, but what I am finding Git fits my style better for is the ability to sync up my unfinished changes to the various places that I work. For some reason very little attention is given to this in version control systems. In Git I can work on a lightweight topic branch, and push that branch so I can pick it up as a remote tracking branch in other repositories where I work. I can keep that topic branch in sync until the work is done, and then merge it to master.

My main alternative in Mercurial for this is a versioned match queue, and pushing the patch queue around as a sub-repository of the main one. Thus far it seems like when you rebase, if your patches don’t apply, you’re expected to fix them manually without any kind of merge support.

I have constant questions, as much of Git is anything but intuitive, but I’m getting there. Interesting journey from CVS to Subversion to Mercurial and now to Git, not to mention the proprietary systems I’ve had to work with, being Nortel’s PLS and MCEPLS, and now Rational Clearcase (God save me from that one). Should be interesting as I learn more. Luckily there are some individuals with plenty of experience in it already to lean on.

May 7, 2008

Michael P. Soulier
msoulier
But I Digress
» C/C++ losing ground?

Simon MacDonald and /. both mentioned this article over at Dr. Dobbs on how C and C++ are on the decline, supposedly.

The study uses the “web presence” of a language to determine popularity, which I find somewhat questionable. I’m sure that the Java forums are full of questions, have you seen that shit?

I’m a big fan of Python, but when the right tool for the job is C, I use C. C++ can die for all I care, I find it horribly complex for what it offers, but C isn’t going anywhere any time soon. To justify this I offer the following points:

  1. C/C++ produce native code. I don’t see anything else on that list that does, and yes, this is still a big deal. Software is like a goldfish, it grows to fill its environment. If you want to run a single, bloated Java app then you likely won’t notice, but if you want to run 10 JVMs on a server, trust me, you will.
  2. C/C++ are powerful. Many say too powerful. I say hire better programmers and don’t switch to languages that stop creative people from doing powerful things.
  3. Garbage collection is overrated. Yes, I love it because it lets me be sloppy and go home on time. Is making sloppy programmers the norm really a good thing? Besides, what do the Java people do on embedded systems? They turn GC off. Uh huh. Write better code.
  4. Computers are getting smaller, not bigger. Powerful yes, but we always want them to do as much as possible, so the overhead of a Python interpreter, or J2ME, is not always welcome.
  5. C is still required for optimization. My last work in Java was mostly hacking JNI to legacy APIs. When I run into a bottleneck in Python that I can’t fix in Python, I tend to drop to C and extend Python with it. Use all the tools in your belt.
  6. How many operating systems are written in Java, C#, etc? On a contract to hack the Linux kernel for a new device, trust me, you’ll be working in C.
  7. For short-lived processes, firing up a Perl or Python interpreter is often a waste of resources. I still like building new tools by combining a lot of small, well-built pieces via a pipe. It’s the Unix way.

Now, don’t get me wrong, C and C++ have many points against them.

  1. Where’s the CPAN? My last big C project was on top of Gtk+ and Glib, and let me tell you, it really helps to have a framework for logging, string functions, ADTs, etc., at your fingertips instead of having to write your own. I, like most C programmers, have my own library that slowly grows over time. Shouldn’t we build such things into a C standard library? The C++ STL is a decent idea, but it wasn’t implemented all that well as far as I can tell.
  2. Deprecated, unsafe functions are still in the language. Why are gets(), strcpy() and the like still in the language? Ok, strcpy() is ok on string literals but string.h is full of unsafe functions that make it really easy for a newbie to write exploitable code.
  3. C++ really needs an overhaul. I find it makes easy things hard. Mind you so does Java.

So, use what works says I. I do find that a lot of Java people, for example, tend to think that if it’s not working for you then you’re not using enough of it. I work in, on average, three languages each day (programming, that is). Not a single one of them is good for every problem that I need to solve, and I don’t believe that they ever will be.

April 12, 2008

Michael P. Soulier
msoulier
But I Digress
» The quiet revolt against a bad language

I’ve been bashing Java almost as long as it’s been out, having been let down repeatedly by it, and Sun’s empty promises about the problems that it would solve. “Write once, run anywhere.” Yeah…right. “Java is a real language, those scripting languages are just toys.” Uh huh.

Meanwhile, the bulk of my programming problems are solved in C, Perl, Bourne-shell and Python. Java is pushed mostly by programmers who’ve absorbed “Design Patterns” to the point that they couldn’t program “Hello World” without 10 classes and a UML diagram.

I do so love hearing that Java is losing the battle for the modern Web.. I certainly hope so. The only place Java belongs, IMHO, is in an occasional desktop program that one wishes to deliver to a heterogeneous environment of desktops.

Mind you, I recently did just that with C and Gtk+ and a few #ifdef’s, and it wasn’t difficult. Granted, I had to build on Linux and Windows, so Java has me beat there. The ability to take an executable .jar file to both platforms without a rebuild is quite nice, and the developers of Python really need to give more thought to distribution issues.

The fact is that most of the time, Java should simply not be one’s first choice to solve any problem. Some would go as far as saying that Java is a crime against humanity, but I think that’s a tad extreme. Mind you, I love this quote:

Java survived teething only by dint of billions of dollars of promotion. It was taken up most enthusiastically by hacks living in fear of losing their jobs to other hacks more experienced on Microsoft environments. Every promise made in its infancy has proved a lie. Designed and implemented in such frantic haste that a semblance of quality was the first criterion jettisoned, it could not but grow into such a monstrosity as we face today. Today its uses in applications where it was, supposedly, intended — cellphones, browsers, rings — amount to little more than nasty, brutish parodies.

It’s simply not the right tool for the job, beyond the occasional niche case. It should be thrown on the language dumpster and used as an example of what happens if you take anything to extremes, including “recommended” design practices. Can I use it to get my work done? Sure. I could use Fortran or Cobol too. Why would I want to? Every time I come across a task and try to do it in Java, even with the help of seasoned Java programmers (oh, the humanity…), it ends up being 5-10 times the size of a simple Python implementation. I like to code, but I like to go home too.

The endless layers of hacks and duct tape that are thrown onto Java in an attempt to shore it up are simply pathetic. Struts, JSF, Hibernate, Groovy and pick a dozen other book titles from your local book store that aren’t worth the paper they’re printed on. Just move on and stop flogging a dead horse. Maybe then I can stop visiting websites with “jsp” in the URL which, coincidentally, are often down or slow to the point of uselessness.

There is no silver bullet. And even if there was, it wouldn’t be Java. Better time would be spent making a CPAN equivalent for C, or a native code compiler for Python. Convincing people is the hard part. The programming community is often like so much sheep, it’s difficult to stop them from following one-another and get them questioning their direction.

Update: 2008-04-14: Looks like I’m hardly alone in my opinions.