Thursday, May 31, 2007

Seeking Alpha Pits Apple against Microsoft's Surface Computing

While my head is still spinning a bit from being impressed with a Microsoft product demo, Carl Howe at Seeking Alpha prefers to play Apple fanboy. Now, as I said, I've played OS/2 fanboy in my life so I know how the cult can work, but it's better to judge technology on its merits than waste effort pushing an emotional preference.

In his article How Apple Will Trump Microsoft, Howe first argues that consumer excitement about the iPhone is due to multi-touch. I hate to burst his bubble, but the excitement is about merging two devices into one, the phone and iPod.

Multi-touch is actually the huge question mark around the iPhone. Let me explain. I have a bit of a DIY home entertainment system consisting of Linux machines running MythTV. Because infrared remotes are a bit of a pain, I wrote a little Java Servlet to process commands from a browser, connect to MythTV or Xine, and execute the commands. My "remote" is a Sharp Zaurus. You know what I discovered after I wrote this interface? Using an interface where you can't learn the buttons by touch is really inconvenient.

How many of us look at our tv remotes to change channels? Now imagine if your remote could reorganize its buttons for each different function you used? Obviously, we'd get a lot more functionlity, but would it be at the cost of usability? In my experience, the answer is yes. Multi-touch is the iPhone's achilles heel. Its strengths are Apple design, iPod/phone convergence, and a decent Internet interface.

To end the article, Mr. Howe asks the question, "Apple isn't doing anything with multi-touch for computers, is it?" His answer? "Wait a few weeks." This is the kind of thing I would expect from Microsoft, not Apple. Of course, it's not from Apple. It's from some random, Apple stock owner writing for a blog.

Labels:

Wednesday, May 30, 2007

Microsoft's Home Run

I'm not sure how vocal I've been about it on this blog, but I'm a long-time Microsoft detractor. For years, I was an OS/2 user and even enjoyed playing around in comp.os.os2.advocacy from time to time. In fact, to this day, I prefer OS/2 as a client platform to OS X (my day-to-day work platform), Linux (pick a desktop, they're all pathetic), and Windows. It was maybe 4 years ago that they finally pried OS/2 away from me.

Anyway, back to the point. Microsoft...bad, bad, evil, derivative, unoriginal...sorry, wrong post.

Microsoft has come out with a product that you have to see to believe. Digg links us to Gizmodo for this morning's Today Show demonstration. If you don't watch the demo, you'll be saying they have touch-screen interfaces at every restaurant chain in America. At least, that's what I was saying. After watching the video, all I can think about is buying stock. It's as if Bill Gates watched Minority Report and told his R&D department to get as close as they could.

Head over to Microsoft's Surface site to check it out. The site doesn't work worth a flip in Firefox, but oh well. Them's the breaks with Microsoft. I lost my moral authority to gripe about product tie-ins when I joined the Apple camp.

Labels:

Thursday, August 24, 2006

My Moment of Xen

As I write this, my old dual Pentium III rackmount server sits under my desk whirling away at a domU configuration in Xen. If you're unfamiliar with Xen, it is software that allows you to run multiple operating systems on top of Linux or NetBSD using a technique called paravirtualization. If you're at all familiar with virtualization technology, you likely know about the big names, Virtual PC and VMWare. If you're an open source guru, think Bochs and Qemu respectively.

In Virtual PC, an entire Pentium PC is emulated in software. Originally written to run on MacIntosh systems, the entire Pentium instruction set had to be emulated because there was no underlying Intel compatible processor on the system. Though I don't know for sure, I assume the Windows version accelerates some operations much like VMWare.

Though less complete and less capable of running alternate operating systems, VMWare makes up for it in speed. VMWare works a little like a Just in Time compiler in a Java Runtime passing raw machine code directly to the host processor when possible. In a race, VMWare wins, but it's still not the same as running on the host hardware. Nevertheless, my old Pentium 400 running VMWare on Linux could run Windows 2000 almost as fast as Virtual PC running on my Quad-G5 Mac.

Paravirtualization is different. In Xen, everything runs on the bare metal save a few security constraints placed on the guests. The only real emulation is in the devices presented to the domU instances (virtual machines). This gives Xen speed, but it also requires modifications to the virtual machine operating system limiting the available choices. It should be noted, however, that Xen 3.0 includes the ability to virtualize any OS using AMD and Intel virtualization extensions in newer processors, but few have those processors right now.

Admittedly, VMWare provides a compelling alternative to Xen because, to put it bluntly, Xen is complicated and its documentation sucks. VMWare merely runs on top of an operating system and provides very simple means to run a virtual machine from a single file with good performance. Configuration couldn't be much simpler in VMWare. Xen, however, requries a custom kernel in both the host and the guest. The installers provided by XenSource work fairly well, but there's still a steep learning curve when you throw in some variations like an LVM boot device or alternative file systems. Eventually, you almost have to roll your own Xen kernel to get around the limitations of the binary distributions.

So, VMWare looked nice yesterday. However, years ago I jumped off the closed-source, commercial bandwagon when some of my primary tools were orphaned by their creators. Consequently, I always look for an option with source available. Xen is available under the GPL which meets my needs so I kept plugging away.

The mailing lists for Xen are invaluable. Almost any problem I ran into was found in the archives of the mailing list. The user community there seems helpful even to clueless newbs based on what I've seen in the archives. If you stick to fairly standard configurations, you won't run into much trouble, but when you do, head to the mailing list archives and run a search.

Today, I have 4 machines at the colocation facility of which 1 needs to be torn down and rebuilt, another is overloaded, and yet another is in such a poorly cooled case that it needs to be transferred to another system. Xen should give me the ability to move services onto my old Pentium III (which is actually one of our faster machines...stop laughing...I said stop laughing...you can quit now), reconfigure the vacant machines, and slowly move to a purely virtualized solution.

It's not unusual for us to have one PostgreSQL database wreak havoc on our entire hosting system due to a spike in traffic. With Xen, we can put each such database on its own virtual machine so we can move the databases around to maximize resource use. I know for a fact that the majority of our CPU usage is on two machines. We can now change that.

Additionally, Xen will give us some fault tolerance. It wasn't a month ago that I had a processor fan fail leading to thermal shutdowns by the hardware. Last year, I was chasing dying power supply fans in several machines and had to perform several hardware upgrades requiring more downtime. With Xen, we move the virtual machines to another system, fix the system in question, and move them back.

I know a lot of IT departments are already doing this with VMWare or Xen or other alternatives, and honestly, I've known about virtualization alternatives for a while, but I never consider applying them to my own systems.

Labels: ,

Tuesday, June 27, 2006

Pstack Equivalent with GDB

I'm not sure why I've never stumbled onto this before, but you can use the following command in GDB to get output equivalent to pstack:

thread apply all bt

Now I'm going to go kick myself for only just learning of this today.

Labels:

Tuesday, May 02, 2006

Open Source Learning Curves

Tim Fennell, author of The Stripes Framework, makes some excellent observations on Open Source Software learning curves in this post on his Blog:


Flat Learning Curves: Powerful


As with anything, Tim's observations hold true in some cases and not in others. More often than not, Tim's observations hold true when a company develops OS software and sells support. In this case, market forces drive the company not to develop good documentation or user-friendly features. In fact, some companies even sell the documentation which may still be insufficient simply because selling support is the only way they make money.

I could name names, but I won't. Most Java developers know the culprits.

Labels:

Better Webapp Development?

Looking at something completely unrelated, I stumbled onto this video presentation by a NASA JPL developer:

Better Webapp Development

As you'll find when you watch the video, the creator intends to push JPL developers away from using J2EE for web application development. To make his case, he compares J2EE to Ruby on Rails, Plone/Zope, TurboGears, and Django. His approach is to create both a "Hello World" application as well as a trivial time tracking application in all of the frameworks including 2 for J2EE:


  1. Servlet + JSP + Hibernate + MySQL

  2. EJB/JBoss



At the outset, his motivation should be clear from the test parameters. First, he's looking at 3 different Python frameworks which should give us a clue he leans toward Python. Secondly, his two Java setups involve some of the worst tools available. Rarely do Java developers now use raw servlets, Hibernate provides some of the ugliest "xml situps" (as he likes to call them) in any platform, and EJB is...well...EJB. Most importantly, he uses application development tools on each of the other platforms but sticks to Emacs and Maven on Java.

So, let's talk about what he could have done differently to present a more accurate test. To do this, I will completely ignore the EJB solution as I agree that EJB is ugly. Apparently, it has its place and performs well in that place, but I will never use the current incarnation (still waiting to see EJB3).

Instead of Servlets, the video should have looked at development using a web application framework. In my case, I would have chosen Stripes as it drops the XML limbo and provides much simpler form development. Stripes would likely knock 50-100 lines of code off of his XML, knocked substantial Java off, and made validation simple with a couple extra lines.

Next, let's look at JSP. While I like JSP with some JSTL, I understand the argument that it doesn't play well with Dreamweaver and other web design tools. But guess what...maybe it does play well. It just so happens that Dreamweaver has plugins for JSP, Velocity, and who knows what other J2EE view technology. The fact remains that you have to put dynamic data into the HTML stream at some point. And to do that, you have to have parseable tags.

As to Hibernate, I'm sure if you've read my blog, you know what I'll say. Hibernate is a mess. However, it does provide a nice database abstraction and relational mapping layer if you can live with its quirks. To save about 20-30 lines of XML, the author could have moved to Hibernate v3 with Annotations. Of course, he may have been generating POJOs from mapping files so who knows if that would save him anything. In my experience, it does save headaches, though.

Now, stepping outside of his choices, what if the author had used IdeaJ and all of its tools? Are there perhaps other tools available that would have automatically generated the application with little to no code and few, if any, errors? While I'm a text editor and command line kind of programmer, given the age and popularity of Java, I'm sure the answer is yes.

At this point, I'm sure the narrator would claim this wasn't a fair test because IdeaJ isn't part of Java. To that, I would say that IdeaJ is a tool, not unlike the tools used to generate applications in Ruby on Rails, Plone/Zope, etc. In fact, the test was unfair to Java *because* the author chose tools badly. If RAD was his goal, then he picked the wrong tools.

The other improper guidance given by the author deals with the "headaches" of each solution as he calls them. While I can't comment on Ruby on Rails, TurboGears, or Django, I do have some experience with Plone/Zope. If the author thinks an average developer can get in and write a time tracking application in a matter of minutes, he's sorely mistaken. Zope is complex. Plone may simplify it somewhat, but those dropdown clicks that he so quickly glosses over with some 50 items in the list take some learning. The minute the application goes from experimentation to production, Zope becomes time-consuming in that you need to understand it fully, and it's a big program with thousands of options.

That leaves me wondering if he glossed over complexity in our other 3 competitors as well...

The other missing aspect of this test is any measurement of performance, reliability, and/or scalability. What use is saving 2 hours in development if the user can't actually run the application? I don't have any experience with these other frameworks in any of these metrics, but it's impossible to make an educated decision without looking into those measurements.

Fun and productivity are not the only important measurements of development tools as this video would lead you to believe.

Labels:

Thursday, April 27, 2006

Reliable Backup

Currently, I use a combination of cron, tar, ftp, and some of my own custom scripts to run backup jobs between my company's two offices. Sadly, the data in one office has become so big that it's rarely succesfully transferred to the other office. Consequently, we end up relying on the local backup machine instead of both local and remote backups.

Today on Slashdot, I saw an article about Cleversafe. Cleversafe seeks to build a grid of backup computers in any number of locations and slice-n-dice the data all over the place. What's great, though, is that you can rebuild the data from slightly more than half of the machines on the grid. It would also distribute the load of the data transfers between several different systems.

So, in essence, we could use home DSL-connected systems, workstations at the office, servers at the colo facility, and who knows what else to store backups. Not only would this fix my remote backup woes, but it would also offer a viable option for local mailbox backup.

As of now, I haven't had a chance to test the software, but it looks like it comes to the Open Source market via a commercial company. Hopefully that means it's fairly well tested. Regardless, it still needs Windows and Mac OS X support to make it a universal alternative. As it is now, I could run it on my FreeBSD RAID system which acts as a backup to a NAS and distribute the backup across several systems.

Definitely worth a look and a try...

Labels:

Monday, April 03, 2006

Hibernate Named Parameters in SQL, No Escape

This past weekend, I was working on a SQL query that I was executing using Hibernate. Part of the query required two casts to one field. In PostgreSQL, you can write the cast as:

cast( cast( field as text ) as int )

Or, you can use a shorter notation:

field::text::int

If you've worked with Hibernate, you likely know that instead of using question marks as placeholders for parameters in SQL and HQL queries, you can use named parameters. These named parameters are of the form ":parametername".

By now, you know what probably I ran into. When I used the short-hand notation for type casts in PostgreSQL, Hibernate interpreted it as a named parameter. Instead of "field::text::int", I ended up with the database seeing "field?".

After reviewing the code in question, I could find no way for the colons to be escaped and not interpreted as a named parameter. Maybe I'm reading the code wrong. Regardless, features like these need to have escape sequences. Now my already complex SQL query is uglier than it had to be due to the nested cast calls.

Labels:

Friday, February 10, 2006

Java Ignoring TTL in DNS?

We have an application in production that is running on a recent 1.5 JDK on Linux that recently ran into a problem with DNS. A 3rd party solution provider redesigned their network resulting in an IP address change for a server we were using in the application. Their TTL (Time To Live) for the record was 24 hours so I fully expected the change to take place without incident and put no further thought to it. Now, over a week later, I find out that our application is still connecting to the old IP address.

So, is Java ignoring TTLs in their DNS caching implementation? The underlying OS had the right information so it has to have something to do with Java. Whatever it is, I just had to take the system offline for 5 minutes to get new DNS information.

Labels:

Monday, January 30, 2006

Working with Other Software Developers

Over the years, I've employed four software developers and contracted with a couple. In all of these cases, it never ceases to amaze me how they fail to follow instructions.

Take my current situation as an example. My company has contracted with a developer with a resume that should intimidate any potential co-worker. Yet, when I give him some of the simplest instructions such as:


  • Use Spring's Annotated Transactions for DAOs

  • Move 3rd party libraries to the lib directory

  • The project must build at the command line and not just in an IDE



He routinely fails to follow them.

In the first example, not only did he not use Spring Annotated Transactions, he didn't even use Spring's wrappers for Hibernate DAOs.

In the second example, he sent me an e-mail proposing creating a lib directory in the project for the 3rd party libraries. Huh?

In the third example, it has become obvious he just doesn't want to leave the IDE.

So, my question is this. Is he:


  1. Feigning ignorance to do the project the way he wants knowing there is little time to go back and change some of these things?

  2. Stupid?

  3. Unable to grasp the level of complexity required in a mid-sized web application?



Based on my experience, I'd say (b) is the most likely culprit with (a) thrown in for a little variety. I know some would object to me calling him stupid, but consider this...if he doesn't follow the instructions of the person who writes his check, what is he????

Labels:

Friday, January 27, 2006

Highpoint RocketRAID 1820A Review

In a recent quest to add a 1+ terabyte media server to my home network, I stumbled onto the Highpoint RocketRAID 1820A. This RAID interface supports up to 8 SATA drives with support for RAID levels 0, 1, 5, 10, and JBOD at only $208.00 through NewEgg.com.

If you have ever hunted for a RAID 5 card, finding something that does true hardware RAID for a reasonable price is next to impossible. Even if you do find it, the chance of drivers being available for anything other than Windows is near 0. Nevertheless, Highpoint delivers hardware RAID 5 with drivers for Linux, FreeBSD, and even Mac OS X. It also supports Windows if you prefer.

Labels:

Tuesday, January 24, 2006

Will I Use Hibernate Again?

Short Answer: Probably Not

Over the past 2 years, I've been reading about the wonders of Hibernate and how much simpler it makes CRUD operations. For two recent projects, I decided to take the plunge and use Hibernate. The purpose of this post is to explain some of the reasons I am not likely to consider Hibernate in the future.

Now, to be fair, I did not use raw Hibernate. I used Hibernate wrapped up by Spring, but if you're familiar with both, you probably know how much simpler and prettier Hibernate is if wrapped by Spring. So, I consider my experience with Hibernate more positive than it would have been without Spring. Feel free to tell me why I'm wrong.

Anyway, as you get into developing an application with Hibernate after having spent years on JDBC, ODBC, and the like, you achieve an initial euphoria over how simple it is to perform CRUD operations on the database. In my case, I wrote POJOs, mapping files, and SQL scripts and quickly had a simple schema up and running with full insert, update, delete, and select functionality.

Of course, Hibernate can make life even simpler by letting you create POJO's and SQL scripts from the mapping files. You can also create mapping files and SQL scripts from POJOs using annotations. Needless to say, there are a lot of tools that can make Hibernate even nicer than what I used.

So, you're probably wondering what is my problem. Good question...

First, let's talk about Lazy Loading. Over the years, I've written who knows how many lazy loading methods within a class to improve performance in situations where a given set of data might not be needed. It is a sound principle of database application development as long as it is fully documented. One aspect central to all lazy loading systems I've ever written, though, was the ability to connect to the database and get data regardless of the context.

What does Hibernate do? It throws your friendly neighborhood LazyLoadException anytime its session disappears. Due to the architecture of my system, it ended up being easier to turn off lazy loading everywhere than to have to hold Hibernate's hand everytime it needed a session.

Of course, turning off lazy loading introduced Hibernate's second major weakness...performance. If you have a database schema of any size/complexity, loading data can become quite cumbersome. Of course, Hibernate offers some ways through custom SQL to improve performance, but at the end of the day, does that buy you anything over iBatis?

Next, let's talk about error messages and exceptions. If I attempt to perform an operation on the database where I forget to provide a value for a not null column, I expect to get an error that says something about that column. What does Hibernate do? If you're only dealing with one table, it probably reports the right error. However, if you're dealing with a group of related tables, take your guess.

In one notable instance where I had a table with a one-to-one relationship to another table setup with full cascading, an error in the mapping of one table during an insert resulted in an error saying that the foreign key column couldn't be null. The real problem, however, was that the insert of the row in the related table failed due to a null column with a not null constraint. Until we learned that Hibernate exceptions were useless, we wasted a lot of time tracking down the wrong problem. The best debugging option is to look at the generated SQL.

Now, you may say, "...but what about your test cases for the related table?". Sorry, but I'm never given enough time to write test cases for every little thing in an application. You can wax poetic all you want about extreme programming concepts or whatever flavor of the month development method gets your goat, but I've programmed both ways, and writing test code takes longer unless your developers are incompetent.

Ooh...hope I didn't step on any toes there...moving on...

So let's talk about the biggest insanity in Hibernate...attached and detached objects. While some of these issues tie into lazy loading, there are still problems even if lazy loading is turned completely off.

Hibernate likes to promote itself as being easy to program because you use simple POJOs instead of complex EJB objects to move data in and out of the database. Of course, that's only a half truth. The real truth is that Hibernate introduces proxies throughout your code to create their imaginary universe where these are "just POJOs". Once the proxies get their hooks into your object, you can kiss simple POJO functionality like sending the object over an XML RPC protocol goodbye. Chances are that it will fail to initialize properly when it gets to the other side.

The only way I could overcome this little bit of fun was to completely reload any mapped collections included in an object that needed to go over the wire. Of course, turning on the delete orphan functionality of cascading relationships added some new fun to the mix. Hibernate detects the fact that you have disconnected the parent from the child and gripes about it with an exception. So, you really don't have a simple POJO that retains all of the fine qualities of a POJO after you let Hibernate dig in.

Now that delete orphan has been mentioned, it's a nice time to segway into a rant about its implementation. It appears as though delete orphan was designed to work exclusively with Hibernate's own collection implementations. When you perform an operation on the collection, the collection does whatever merriment it wants in the background to track the operation and reports back. Hibernate then takes the information stored in the collection and makes the same changes to the database.

Side Note: Going back to the issue above, why if delete orphan only takes action in the database upon a save/merge of the parent object does it need to track the fact that I'm tossing the Hibernate persistent collection in favor of a simple, java.util collection?

When I think of delete orphan, I think of the database loading the list of rows from the database, comparing it to the list of rows in memory, and executing the appropriate insert, update, and delete statements to bring the database in sync with the in-memory representation. Hibernate's idea of delete orphan seems like someone took the easy way out.

Don't get me wrong. Hibernate's method could be useful in some circumstances, but I want to be able to take a POJO, without any proxies or special collection classes, and have it persisted to the database just the way it is in memory with all of the dependent collections persisted correctly as well.

All of these issues caused me to spend considerable time digging through the Hibernate forums and Google looking for ways to circumvent these problems. In all of my searching, one thing always rang true. Hibernate developers act like a bunch of arrogant, holier-than-thou programmers labeling anyone and everyone incompetent while lauding their creation as perfect. Nice OS community building there guys. You definitely kept me from ever posting on the forums or, even worse, contributing to your project.

Of course, not all of my experiences with Hibernate were negative. Some of the good things:


  • Database Independence: One application we wrote runs Apache Derby for the Swing GUI and PostgreSQL at the web server.


  • SQL Queries: Taking advantage of object mapping by writing raw SQL queries was extremely simple.


  • Scalar Queries: Hibernate turns scalar queries (thow queries that do not return a mapped object) quickly and easily into an Object[][].



Unfortunately, the benefits do not outweigh the costs. Hibernate feels to me much like Ruby on Rails must feel to many Java developers. It's great for quick and dirty jobs, terrible for the big stuff.

Let the flaming begin...assuming anyone reads this stupid blog.

Labels:

Thursday, December 01, 2005

Trading: Story of My Life -- AMD

Well...I hope someone took my advice because I sure didn't. Was I scared to pull the trigger? Nope. I was too busy between work and moving to a new house that I didn't have money in the right place at the right time.

Anyway, if you haven't noticed, AMD ran from around $22 when I first posted about it to $26 and some change today. That would be a handy little 20% gain in a little over a month, but you do have to take into account what you would have done had you owned a sizeable percentage of the stock.

Looking at the chart, it's likely that I would have pulled out during the pullback on October 27th. However, I do love to play October weakness so I might have stuck with it. Outside of the 27th, I would have been set as long as I had a provider with a trailing stop loss. In the past, I haven't, but I definitely think it's worth it to save time and potentially increase gains by relieving the pressure of watching a stock.

Anyway, I hope someone dropped a huge chunk of change on it. If you're still in it, make sure you have a good exit strategy.

Labels: ,

Wednesday, October 19, 2005

Stock Thoughts: AMD

Advanced Micro Devices has come a long way from playing alongside Cyrix in the Intel clone market. As a chipmaker for PCs, they've gone from making cheap, discardable processors to exceeding Intel at its own game. The latest 64-bit chips for the desktop and the Opteron chips for the server have contributed to AMD outpacing Intel in the market. Additionally, Sun Microsystems jumped on the AMD bandwagon in a big way and has vaulted from nowhere to number 6 in the Intel-based server market.

So the big question is, why is the stock going down? Simple answer, it ran up too far and Intel warned recently. I'll be looking for a bounce off of obvious support levels before the end of the year.

Labels: ,

Friday, October 14, 2005

Why I Hate Maven...Continued

In my previous post, I forgot the most glaringly ridiculous part of Maven's feature set...the dependency system. It's all well and good that I can, as a developer, list my application's dependencies somewhere. However, what's the point of a system that flattens the dependency hierarchy? It's a tree so implement it as a tree.

For instance, what happens if you specify Hibernate 3 as a dependency with nothing else listed in an application that does little more than create a session and run a query? You end up with millions of compile and/or runtime errors because Hibernate requires at least 20 libraries.

Why wouldn't specifying Hibernate 3 as a dependency in Maven cause it to generate dependencies automatically for all of the other required libraries?

Like FreeBSD Ports or Gentoo Portage, if you ask for an application or library, the system should automatically resolve everything you need. There's no reason to chase your tail trying to figure out what version of CGLIB is required by Hibernate or what version of ASM is required by CGLIB. Do I even know what those libraries are? No. Should I need to know? Probably helpful but not central to my job.

Attached to the issue of the dependency tree is that of the contents of the JAR files themselves. When you look around ibiblio.org in the Maven repository, you find several libraries with a variety of options. One option might include no dependencies, the other might include all dependencies, the library may be split into parts, or the library may have one massive, all-encompassing jar to simplify dependency craziness. Additionally, version numbering is like the wild west.

One word...STANDARDIZE.

Labels:

I Hate Maven

Why do I hate Maven? For the exact reason that most people love it...the repository. With Ant and all dependencies checked into a source repository, my projects always build reliably. Having been forced to use Maven on a project, I've had to rig repositories with my own versions of libraries and never get a consistent build between different workstations. I guess I could set up my own personal repository on a server, but that takes time. Why mess with the repository? Is the storage saved by not storing libs in each project really that important? I certainly don't think so.

Hate may have been a bit extreme, but I'm the kind of developer who likes control. Maven takes it away and provides as your only reward some convenient goals and plugins like run and uberjar.

Unsubstantiated rant complete. My apologies to the Apache folks who tend to produce some amazing products and technologies. I'm especially looking forward to trying out Geronimo.

Labels:

Wednesday, October 12, 2005

Java vs. OO Design

For two years, I debated with one of our programmers about her object oriented (OO) design choices. In essence, she reduced a relational database driven Java application to a set of procedures losing almost all of the benefits of good object design. At the time, I was not studying industry trends and did not realize she was merely following current trends and best practices.

Now after studying industry trends and best practices, it seems that true OO design is slowly disappearing. However, I have stumbled upon one voice of opposition. Martin Fowler of ThoughtWorks has written an article on the AnemicDomainModel. In it, he suggests that developers are robbing their Domain Model by putting all of the logic in a service layer.

Mr. Fowler makes many of the same points I have made over the years. In fact, I'm reminded of the definition of an object as it has always been given to me:


An object consists of data and operations performed on that data.


In the Java world, JavaBean methods are not operations on the data. In fact, one has to wonder what benefit there is in creating getter and setter methods instead of just making the data public. In fact for objects (i.e. not base types), getter and setter methods are little more than public variables due to the returned value being a reference. In other words, the following C++ and Java are equivalent:

class A {
public:
Shape& getShape() { return shape; }
private:
Shape shape;
};

public class A {
private Shape shape;
public Shape getShape() { return shape; }
};

The difference is that the reference operator (&) in C++ makes the mistake much more obvious. Programmers I have employed did not even realize unintended consequences. It is even worse for setter methods:

public class A {
private Shape shape;
public void setShape( Shape shape ) { this.shape = shape; }
};

What happens if we have calling code like this:

Shape shape = (Shape) new Circle();
shape.setDiameter( 5 );
A a = new A();
a.setShape( shape );
.
.
.
shape.setDiameter( 10 );

What most Java developers do not understand is that the Shape object contained in class A refers to the Shape object created by the calling code. Consequently, the second Shape setDiameter invocation changes the size of the Circle stored in class A.

Most Java programmers reading this will probably disagree, but I challenge you to run an example and see what happens. As a side note, keep in mind that Strings are treated like base types.

So, after that lengthy tangent, the point is that a JavaBean is little more than a C struct, and a DAO is little more than a C module where every method takes a common struct as an argument.

OOPs...pun intended.

Labels:

Monday, October 10, 2005

Where's My Backwards Compatibility?

I've been around enough to know that the minute you question the open-source gods, you're likely to be cast into the burning fires of hell for an eternity of pain, suffering, and anguish. Nevertheless, they need to be raked over the coals for one very important thing...BACKWARDS COMPATIBILITY.

Let me tell you my current situation. I'm in the process of developing a small database system for a student organization where I'm using several new open-source technologies. Those include:


  • SwiXAT: An XML authoring toolkit for Swing.

  • Spring Framework: Best described as the swiss army knife of toolkits...a little something for every occasion.

  • Hibernate: A popular Object Relational Mapping tool.



As grateful as I am for the availility of these tools, they've given me no end of headaches with version dependencies and backwards compatibility. SwiXAT actually uses Spring and is based on version 1.1.5. Spring, in turn, has database libraries that use Hibernate. In version 1.1.5 of Spring, you use Hibernate 2.x. In version 1.2, you can use the newer versions of Hibernate numbered 3.x.

So, here's the fun. Hibernate 3.x includes the database dialect for Apache Derby (formerly IBM's Cloudscape), but previous versions of Hibernate do not directly support it. While I could dig up the code and package it myself, life would be simpler if I could just use Hibernate 3.x with all of its new whiz-bang features and bug fixes, right?

Wrong...here are the two gotchas...

First and most importantly, Hibernate completely reworked its package naming from net.sf.hibernate to org.hibernate as part of its conversion to a JBoss project. I'm not aware of a way to overcome that change without rewriting the code, and I might as well just upgrade as rewrite it myself.

So if I want Hibernate 3.x with org.hibernate namespaces, Apache Derby dialect support, and who knows what else, I need to upgrade to Spring 1.2. Great...the only problem is that SwiXAT uses methods from Spring that no longer exist.

So, because of everyone's lack of interest in backwards compatibility, I now need to rewrite SwiXAT to comply with Spring 1.2 and possibly have to manage my own codebase until the SwiXAT authors are able/willing to upgrade.

If open source projects wish to thrive in commercial space, they must pay attention to issues like these. Nobody likes forced upgrades. Spring could have easily included a deprecated wrapper for the missing functions required by SwiXAT as they appear to be nothing more than OOP self gratification on the part of the developers. Hibernate should have continued with releases under both package namespaces to give developers time to make the change themselves.

Now, can I solve all of these problems? Yes. However, the goal of these projects is to save developers like me time. At this point, have they saved me time? Hard to know until I finish the project.

Ready to be burned at the stake...do your worst.

Labels:

Monday, July 26, 2004

Equity Trading -- Mylan (MYL)

Talk about being really, really, really wrong about a company. Mylan announced today that it will be buying King Pharmaceuticals, and the stock dropped like a rock. I haven't fully researched the deal, but it appears that it will be diluting earnings substantially.

This just goes to show that you should always set your entry and exit points prior to a stock purchase and not deviate from those rules. If I had held on expecting the turn that should have come, I'd be something like 20% down right now. As it is, I only lost 5% trading Mylan.

Labels: ,

Tuesday, July 13, 2004

OOP: Information Hiding

While Java has ushered in a number of beneficial programming constructs, it has also undermined good object-oriented design approaches. As an example, consider the basic Java Bean. I'm not talking about Enterprise Java Beans but just plain old Beans.

A Bean has a simple mission in life...allow other code to get and set properties without knowing anything about the object or its internal structure. Java accomplishes this through its reflection APIs by using a simple, predictable Bean method signature. Commonly, the Bean methods directly correspond to private data members in the Bean class, however the JavaBeans specification does not require this practice.

Unfortunately, most programmers do not know and/or do not care about the specification. As a direct result, programmers often implement most data objects as beans. When the object consists of nothing more than primitive types such as int and String, I have no problem. It is when the object consists of non-primitive data types where I cry foul.

Why? It's simple Java pass-by-value programming, something most programmers fail to understand even at a reasonably advanced level.

When you return a primitive data type or pass it as a parameter, Java makes a copy of the data and sends the copy. However, when you work with non-primitive types (i.e. List, Stack, etc.), Java makes a copy of the reference to the object. While it is a subtle distinction, it is an extremely important one.

Consider the following code:


public class Example {
private int a;
private Vector b;
.
.
.
public int getA() { return a; }
public Vector getList() { return list; }
};


If your code calls example.getA() and modifies the result, the private member within example does not change. However, if your code calls example.getList() and calls addElement on the returned Vector, the Vector b within example DOES change. Consequently, the calling code becomes dependent on the private member type.

Java offers a variety of means by which this situation can be prevented. Cloning often works out to be the easiest approach. It keeps the simple structure of the bean-style programming, but it prevents programmers from relying on the underlying private member type by presenting them with a copy, much like Java already does for primitive data types (remember that String is a primitive type...tough one for a C++ programmer).

Self-discipline might....err....nevermind...

Ultimately, the goal is more easily maintained code. If you expose private data, you run the risk of making a black box transparent. What happens when that Vector needs to change to a Hashtable to provide faster access. All of those callers relying on example.getList().addElement( "hello world" ) will break. What do you do now that those calls are littered throughout several thousand lines of code?





Labels: