Wednesday, February 28, 2007

Semi Annual Unofficial Gadget/Cool Tool Review

Since sometime last year when I talked about WinDirStat (a pretty cool tool), I have been busy acquiring other cool things, so I thought I would post about them, in case anyone cares. Here are my reviews, in no particular order:

  1. RoboForm. For anyone who may be trying to manage several online sites with several different user ids and passwords, this should be considered essential. You simply choose one master password (which you absolutely must keep secret), and it manages all the rest. With a simple click it can generate a random password, so you can have a different password for each site. Of course you can edit and manage the list. It also attaches to your web browser (it works with both IE and Firefox quite well) and permits one-click login to any site. I have RoboForm2Go (as well as the regular version on my home PC) which runs entirely from my 5GB Seagate pocket drive. Perfect for work.
  2. Seagate 5GB (and 6GB) portable hard drive. It's physically bigger than a flash drive, (it's about 2 1/2" in diameter) but it's a real (and really small) hard drive that runs off a USB connection. Has a cool blue drive light that flashes when the drive is accessed. I have used it every day for the past 15 months.
  3. OCZ 4GB flash drive. Very small, appears ruggedly made. Cool orange drive light. It's only $35 after the rebate, too. Just got this thing. We'll see how well it performs over time.
  4. eVGA GeForce 7950GT KO 512MB graphics adapter. This puppy is (at least) 10x faster than my previous GeForce 7300GS, particularly when generating shadowed, final renderings with Home Designer Pro 7.0 CAD software. Last night I generated a 4-light shadowed night view in about 5 minutes (314 seconds, or so). With the old adapter, it might have taken an hour--I had never tried even using 4 lights to cast shadows, before. I did have problems with the enclosed CD (it wouldn't read on my system), but I downloaded the latest drivers from the eVGA web site and they installed without any problems. It's a tad noisy--you can hear the fan pretty plainly, but I have no complaint. It also supports 2 DVI monitors simultaneously, though I only have a single flat panel.
  5. Home Designer Pro 7.0. I upgraded last fall from the 6.0 version, and the changes/improvements are significant. There's a completely new rendering engine, and they've opened up the program for all the many 3D object add-ins (some are free, and some are $$ purchasable). It costs about $450 from Amazon.com, which is a lot to pay unless you want/need a program with this amount of power and flexibility.
  6. Dell Wireless Printer Adapter 3300. I don't recommend this device. It works most of the time (from my home PC), but isn't reliable when accessed from my wife's PC (which is less than 1 foot away). They also don't tell you that the device has its own status web server built in, which can be quite helpful when it comes time to troubleshoot the damn thing. Which is far too often, IMHO. When it hangs--you must reboot everything. Yes, you heard me right!
  7. Dell AIO 924 printer. It's one of those "all in one" devices that has a scanner, copier, fax, and color inkjet printer all in one box. Prints fast and with good quality, too. The scanner and copier also seem adequate. Not too sure it scans colors very accurately, though. No experience with the fax. The "low ink" light comes on when the cartridge reaches 25% full. What? Do they think everyone will swap out the cartridge when there's still 50 pages left in it? (Obviously, yes.)
  8. TigerColor ColorImpact. This is a cool program that makes color manipulation easy. (Ever need a good complimentary color when creating a web site layout?) I use it all the time when working with color schemes in my house designs. It's not free (or necessarily cheap), but for anyone working with color for the web, for art projects (well, computer art projects, anyway), etc., it's a really powerful tool.
  9. Intuit Turbo Tax. It's the program I use to file my taxes. Pretty convenient, too, particularly if you file electronically. Buy it; don't buy it--I could care. However, I consider my time to have some value, and the $50 you spend (plus $19.95 per return filed) probably comes back to you in saved effort. It certainly gets your refund more quickly than paper filing.
  10. Firefox 2.0, and Firefox Portable. Overall, these are an improvement over version(s) 1.5.x. Certain things, such as managing add-ins, are simpler and easier. I really like the add-in dictionary that puts red lines under misspelled words. Yeah, it works almost like MS Word. The portable version runs entirely from a USB drive. No polluting of the registry or saving of voluminous cached copies of pages (unless you really want it to).
  11. Samsung LN-S4095D 1080p HDTV. This is a great TV, though I see I paid a few hundred $$ more than the current going price. Oh well, such is the cost of opportunity. Regardless, I am quite happy with the TV.
  12. Cable HDTV DVR. Good god, man! How did I live without this thing? Once you can watch your favorite shows on your schedule, and once you can pause the Big Game so you can tinkle in peace ... *sigh* I don't care whose you buy/rent, just do it. You will be glad you did.
Well, that's all I can think of, for the time being. I know I have at least one more gadget sitting at home, waiting to be opened and installed, but since it requires I actually drag my PC and printer downstairs to be with the wireless router on a wired-and-up-close basis ... it will probably wait for that Saturday or Sunday when there's absolutely nothing to watch on TV.

Wednesday, February 21, 2007

Software Architecture: Service Oriented Architecture, Part 1

This post begins a discussion of enterprise software architecture. (Find another definition, here.) Because it's currently such a popular buzz phrase, we start with some thoughts on SOA (service oriented architecture).

Just to establish the playing field (or "level set", to use a popular buzz phrase), here are some characteristics I would ascribe to services:

  • Services are exposed (though not necessarily "publicly") so that a wide variety of clients may access them. For many, this implies web services, but in some environments this may imply EJB or some other mechanism. This may also imply a non-RPC style message, though that is a slightly different discussion.
  • Services are stateless. That is, the service does not "remember" the results of prior calls, and there is no order dependencies between various service methods.
  • Services should be as simple as possible to use, and should not require the client (the thing calling the service) to do a lot of "work" to setup for a call, or necessarily upon return from a call. A dead giveaway that a service is poorly designed is the amount of client code required just to make some given function call (other than the "plumbing" code that may be required). One of the arguments used against services is the relatively large amount of plumbing code (AKA "glue") needed to support their use.
  • A service should make few, if any, assumptions about its clients, nor can clients assume anything about the service (other than the interface contract). This is usually called "loose coupling". In particular, service clients should be ignorant of the service's implementation, and vice versa.
  • Service interfaces should be as immutable as possible. Forever. I say "should be" because in the real world, sometimes things have to change. However, the cost of changing a service interface is very high.
  • Services do not necessarily have to be transactional. If not, then each update function should have a compensating transaction ("undo" function).

The above list is by no means exhaustive, and I reserve the right to modify my definition at any time.

Transactions

Today we will talk about transactions, and why they might not be quite as good an idea as previously thought. First off, let's get a perspective from Sun, in their J2EE Blueprints, section 8.8:

"Most enterprise information systems support some form of transactions. For example, a typical JDBC database allows multiple SQL updates to be grouped in an atomic transaction.

Components should always access an enterprise information system under the scope of a transaction since this provides some guarantee on the integrity and consistency of the underlying data. Such systems can be accessed under a JTA transaction or a resource manager (RM) local transaction."

Unfortunately, this view is both naive and makes assumptions about the nature of the types of "systems" that will participate in any given sequence of service method calls. Specifically, systems (enterprise or otherwise) are not databases, and should never be viewed this way by clients. (This is a huge pet peeve of mine.) While we may design service methods to be transactional, I don't think anything should be assumed about the nature of the underlying data store(s), nor can we be tied to a particular kind of client environment, either. (Sun seems to favor the JEE client environment, for some reason.)

From another document on SOA, this quote from Microsoft's Principles of Service Design states:

"While services are designed to be autonomous, no service is an island. A SOA-based solution is fractal, consisting of a number of services configured for a specific solution. Thinking autonomously, one soon realizes there is no presiding authority within a service-oriented environment—the concept of an orchestration "conductor" is a faulty one (further implying that the concept of "roll-backs" across services is faulty—but this is a topic best left for another paper). The keys to realizing autonomous services are isolation and decoupling. Services are designed and deployed independently of one another and may only communicate using contract-driven messages and policies."

Requiring a transaction for every service method may seem like a good idea, but it can't always be done. Some system data stores may simply not be transactional. I can think of one in particular: LDAP. The best you could do would be to create a compensating transaction (and here I use the word "transaction" in the sense that a method call, being an interaction with the service, is considered a transaction with the service).

There can be some problems, however, with compensating transactions:

  • Maintaining system integrity across multiple services can become very difficult, especially as the number of failure scenarios increases.
  • If updates must be ordered (i.e., performed in a specific sequence), so must the undos, usually.
  • Keeping both updates and "undos" idempotent can also be quite difficult. Particularly, the undo must not "undo" an update that was never applied!
  • In some scenarios, concurrent reads by other clients will see the results of "partially committed" updates that may be subsequently undone. These are in essence uncommitted reads, which may be a problem. It most certainly can become a problem when "undoing" a transaction that was applied based on the results of a prior uncommitted read.

The above difficulties might lead one to devise "service coordinators" that exist for the sole purpose of ensuring the integrity of their underlying systems. That is, we aggregate our enterprise systems below the service boundary, exposing services as essentially autonomous (single unit of work) functions. One call does all, in other words. Clearly, for some situations this may be necessary. Hide all the complexity behind a nice, clean, service boundary.

One suggestion is to ensure that all participants are transactional except for one. The non-transactional update is performed last (after it is known that all the others have at least provisionally committed), so that the transaction would only need rolling back if the non-transactional update failed. If the transaction fails before executing the non-transactional component, then no compensating update is needed. This, though, seems counter to Sun's recommendation. You may also want to order updates with the most-likely-to-fail being performed first, so that the amount of work is minimized when an "expected" failure occurs. Of course, you don't always have this flexibility.

The order of updates may be important, but with compensating transactions, knowing exactly what needs to be undone can become impossibly complex, again, unless the number of non-transactional services (participating in an update function) is limited. I would recommend not having updates be dependent on the results from prior, uncommitted updates in the same transaction. These update transactions would not be idempotent, in any event.

Clearly, this issue (and many of the issues inherent to the design of services) is quite complex and there is no one, single, right answer. At no point along the way can judgment be eliminated in favor of a cut-and-dried cookie-cutter approach.

At some lower layer in the service stack transactions may be necessary, if not required. This may be the essence of the "Enterprise Service Bus" approach. At other, "higher" layers in our model, transactions may not either be practical or even possible.

In the next post we will talk about reliable messaging.

Note to self ...

When you go in front of a Grand Jury to testify, and you're not sure, tell them you don't remember accurately. Don't say something you aren't completely certain is true, because it will probably come back to haunt you.

This has been a public service announcement.