Industrial Logic -> Papers -> EJ Pilot Laptop Briefing System Design Audit

EJ Pilot Laptop Briefing System Design Audit

u u u

 
EJ's PLBS (Pilot Laptop Briefing System) is far from an ideal implementation but is nevertheless close to being a system that can be put into production. The system has numerous flaws, which we feel can be corrected over time, with an effort to AGGRESSIVELY REFACTOR the existing design and code.

Refactoring needs to be done immediately to fix some of the more unpleasant behaviors within the system. Initial refactorings would best be carried out in conjunction with mentors, such as those available through Noblestar or Industrial Logic.

The greatest challenge faced by the designers of the system involves the legacy BTRIEVE database. The existence of this database, and the large body of code used to access it, explains why so much C++ code was developed when Java is clearly a better choice for both building distributed systems and programming in objects.

Since it could be well over a year or two before an Oracle database replaces the BTRIEVE database, the team is faced with the choice of continuing to interact with BTRIEVE in the old style (i.e. a non-SQL approach that involves looping through records one at a time) or wrapping BTRIEVE with an SQL layer, which would allow PLBS Java applications to treat the database as if it were relational (like ORACLE, for example).

It is unclear at this time if it would pay to wrap BTRIEVE with an SQL layer. The task would involve relying on a third-party product, could require an upgrade to the existing version of BTRIEVE, and might involve developing code to make the whole thing function. In addition, existing bugs in the BTRIEVE database (such as problems with concurrency) would not go away, and could create problems within the SQL layer. Therefore, at this point, it would not be a good idea to pursue this path, even though it would be good to write SQL against the BTRIEVE database.

On the other hand, we think that the C++ section of PLBS should not continue to grow. Java is a much better language to use for future development, and therefore all staff should learn how to develop in Java (see BUSINESS VALUES). It is possible that the C++ DataManager program could be gradually refactored to first run reliably, and second, run with reduced responsibilities that could be handled by what is now called SessionManager.

PLBS was designed using CORBA, which we think was a good design decision. PLBS is a distributed, multi-lingual, multi-platform system that is required to interoperate with systems written in legacy languages. PLBS is therefore a perfect fit for CORBA. Inprise's VisiBroker CORBA implementation is also a good choice, because it is the industry-leading ORB (Object Request Broker), it comes in Java and C++ versions, it supports advanced distributed object architectures, and it includes Caffeine, a feature that allows Java programmers to serialize (i.e., pass by value) objects over a fast IIOP connection (see OBJECTS BY VALUE). VisiBroker also represents a possible replacement technology for MQSeries (see FAT-FREE CODE). We think that VisiBroker is a superior choice over Java's RMI (Remote Method Invocation) or other messaging products (such as Information Broker by Active Software), because it is a superior technology that was made to solve the problems inherent in the PLBS.

We did not like the overuse of VisiBroker's OAD within the system. Having one SessionManager and one DataManager for every remote call into the PLBS is not a good use of memory, and while it may help to get around a threading issue, it does not represent a sound design. At a minimum, we would like to see a handful of SessionManager servers using object factories to talk with unshared DataManagers. This particular refactoring would take some time to implement (as we note in AGGRESSIVELY REFACTOR).

Performance will continue to be an issue until the system goes through a thorough performance tuning. This will involve a good deal of refactorings (AGGRESSIVELY REFACTOR), which are best carried out with TEST SUITEs in place. A week or two of PAIR PROGRAMMING using mentors would produce the best performance tuning.

There is currently no disciplined development and coding process in place. This is hurting the PLBS team. The team needs a process, even if it is minimal. It is possible that a process will improve the quality and reliability of the code being produced.

Our Design Audit follows. The audit consists of three sections: Process, Technology, and People. We have provided 19 ideas that reflect PLBS problems and what we would propose to fix them. Each point has a name, which the team can begin to use in their vocabulary. The points may be skimmed quickly by first reading all text in the bold font. Each point contains two statements: the first states the problem; the second states the solution. In between these statements and after them, we provide details about each issue as it relates to the PLBS project. Please send all questions and feedback to joshua@industriallogic.com

  Industrial Logic, Inc.

 
Contents

Process

AGGRESSIVELY REFACTOR
TEST SUITE
PAIR PROGRAMMING
DESIGN AUDIT

Technology

PRECISION NAMING
FAT-FREE CODE
SMALL PARAMETER LISTS
SMALL METHODS
GUARD CLAUSES
DECOUPLED LOGGING
DECOUPLED DEBUGGING
OBJECTS BY VALUE
OPTIMIZED JAVA
SOFTWARE UPDATES

People

BUSINESS VALUES
SIMPLICITY FIRST
EGOLESS DEBUGGING
BORDERLESS DEVELOPMENT
INFORMATION SHARING

 
 

Aggressively Refactor

Early implementations of a system often need to be improved over time. Teams may focus on improving reliability, performance, scalablity, and maintainability. The key to making such improvements lies in what is called "refactoring."

vvv

In the early, middle, and late stages of development, systems need to be improved. However, it is extremely hard to make improvements, since slight changes can introduce all sorts of bugs. Nevertheless, if changes aren't made, the system may not perform adequately or will be very hard to administer or maintain.

The PLBS is in such a state. The system works, but not as well as most would hope. It would be great to throw away the existing code and rewrite the system from scratch, but that is not practical. So the existing system needs to be improved and deployed ASAP.

But how can the team set about making improvements when there are already known bugs and the team can't afford to introduce new ones?

The answer is to use refactoring. Refactoring involves setting up tests that may be run against the system to ensure that the "right" behavior is obtained, followed by making slight improvements to the design and/or code, followed by retesting the code to see that the "right" behavior is still obtained.

Refactoring can involve something as minor as renaming a badly named variable (PRECISION NAMING), reducing the size of a very large method (SMALL METHODS), or changing how data is passed around in a distributed system (OBJECTS BY VALUE). Refactoring is best carried out with a good suite of tests (TEST SUITE).

Refactoring may also be done in the absence of a TEST SUITE: In this case, developers must perform tests manually. (This is not nearly as effective as having automated tests, which may be run whenever developers wish to check in newly modified code).

Therefore:

Rely on aggressive refactoring as a way of gradually improving quality. Use mentors to help make simple, powerful refactorings that will greatly improve a system.

vvv

When teams are aggressively refactoring their code, quality is continually being improved, and future maintenance costs may be greatly reduced. The key is to know how to make gradual improvements and to be disciplined in writing unit tests (see TEST SUITE).

To address immediate performance and reliability concerns, the PLBS team could consider the following refactorings:

  • Rewrite Swing-based Libretto code using the AWT. See notes at the bottom of OPTIMIZED JAVA.

  • Pass objects by value, instead of reading and writing byte arrays on both the server and client sides. See OBJECTS BY VALUE.

  • Reduce SessionManager/DataManager dialogues. To help performance, reduce the number of calls between SessionManager and DataManager. For example, SessionManager currently calls DataManager's getCrewMovements(), which returns a collection of crew movements. After receiving this data, SessionManager turns back to DataManager for more information, passing back (in a loop) each of the elements that DataManager just passed to SessionManager in the previous call. The team could consider refactoring this code to let SessionManager make just one call, in which DataManager will retreive crew movements and the additional data required by SessionManager.

  • Simplify reports. DataManager currently spends a lot of time turning BTRIEVE data into HTML. The HTML reports are nice, and it is simple for the Libretto laptop to display them, but it may save time to simply pass back plain text. The Libretto client, and/or the program used to send faxes, could convert the plain text to something more readable, using a simple, efficient formatting strategy.

  • Run a few SessionManagers, not one per Libretto connection. This is a more difficult refactoring to implement, but it should result in a faster PLBS system. SessionManager can create objects that contain their own DataManager references, and then serve up these objects to Libretto clients. Much of this work can happen before a Libretto client connects, using pooling techniques. (Note: we will need to discuss this further - it is not a simple refactoring). This will also help improve speed, should you need to log all data to Oracle.
 
 
Martin Fowler, author of Analysis Patterns and UML Distilled, is currently hard at work on a new book about refactoring.

We have had the pleasure of helping review Martin's manuscript, and we think it is going to be a classic work. We're also pleased that Martin has published a small collection of his refactorings on the Addison-Wesley web site.

To learn more about refactoring, please visit Martin's work in progress on Refactoring.

Besides a number of the ideas presented below, you will find links to specific refactorings from Martin's growing catalog.

 
 

Test Suite

. . . the software in question is needed in production ASAP. Yet the software itself is not ready for production.

vvv

. . . No one is completely comfortable with the existing body of code. While it solves a business need, it is a little too slow or unreliable to be considered production-ready. Yet the software is needed today. Test Suite helps provide a safety net that will enable a team to make incremental improvements.

The vast majority of software projects get into this position. Code is traditionally developed without attention to testing code, which programmers usually think of writing after they have completed writing the real code. Such testing code is often never written at all or in great haste toward the end of a project, when there is little time.

The problem with this approach is that it makes it far more difficult to actively improve the production worthiness of software code, because there is no measuring stick to know if, after a refactoring, the code is any better or worse. Manual tests work only so well, and often don't catch important bugs.

Therefore:

Write a series of unit tests that confirm when the system is running correctly and when it is not. Automate these tests into a single suite that may be run without user input, at the touch of a button.

vvv

Once a series of tests has been written, a team can safely begin to AGGRESSIVELY REFACTOR. Such refactorings will incrementally improve performance, reliability, software architecture, and code quality, while helping team members incrementally become better software designers and developers.
 
 

Pair Programming

. . . every team consists of people at different levels of experience who write code of varying quality. Pair Programming explains how to make teams grow while producing better-quality software.

vvv

Talented software developers know how to write good software, on time, within budget. Yet such developers are a rare breed and are difficult to retain. So how can a company produce good software without many highly experienced developers?

The vast majority of companies have this problem: They need highly experienced developers who simply aren't available. In the Midwest, the problem is particularly accute. Companies struggle to find the right people, and either lose them to higher bidders when they do find them or don't find them at all.

The trick is to transform a team of decent, but not highly experienced, developers into a powerful unit, capable of producing quality software.

In our experience, one the best ways to transform a team is by increasing individual experience and educating people through a process called Pair Programming. This process involves having two people write and AGGRESSIVELY REFACTOR code together at one computer.

This may seem as if it could waste a lot of time. But in fact it does the opposite: It reduces the bugginess of code, improves code design while it is being written, and generally leads to easier-to-maintain, better-quality code.

When we mentor companies, we often do so by pairing up with their developers to write or refactor code. When we leave, team members pair up with each other, changing partners every week or two.

This has the added bonus of making every team member aware of the many different areas of the system. Companies suffer tremendously when a team member leaves and no one can pick up his or her work. Pair Programming helps prevent this from happening by giving everyone a chance to work on different areas of the system.

Therefore:

Develop code in pairs, working side by side on pieces of a system. Use mentors to jumpstart the pair programming process, and give all team members a chance to pair program with each other.

vvv

Pair programming works best when pairs are given (or select) small chunks of work to complete. If a pair can't complete the work chunk within two to three days, the work chunk is either too big, or another pair will need to take a look at it. . . .
 
 

Design Audit

. . . once a team is up and running and producing software, the question is: Are they heading on the right path, or veering off course? Design Audit describes a simple way to help teams stay on track.

vvv

Software designs, development teams, and development processes often get into unhealthy states during the course of systems development. If these problems aren't diagnosed and corrected, the problems can undermine the success of a project.

People go to doctors for regular checks-up. But many software development efforts go on for months and years without going in for a "doctor's visit," sometimes called a "process check" or "design audit."

Such audits can save a vast amount of time and headaches. Often, an outsider can see things that team members just can't.

Audits that are done effectively will find the problems and offer up solutions. Then, the trick is for the team to implement the suggested solutions.

PAIR PROGRAMMING is a way of doing design audits at a very low level, where team members help each other find and fix problems.

Management of the PLBS has already seen the need for and obtained an audit. Given the effectiveness of this audit (i.e., how much did it cost, how much time and money and how many headaches did it save), management may consider additional audits periodically throughout systems development.

It should be stated, however, that projects that get off to a good start sometimes don't need audits. We have found that by judiciously using experts early on in the development process, many of the problems that appear late in the game may be avoided, thus reducing the need for audits.

Therefore:

Submit systems for periodic "check-ups" by experts who can quickly diagnose problems and suggest practical solutions.

vvv

It can also be a good idea to use diffent vendors for audits, provided they are all experts.

 
 
Kent Beck and Erich Gamma, have teamed up to write a utility called JUnit, which allows programmers to write tests, bundles these tests in suites, and execute them all at the touch of a button.

JUnit is absolutely free and comes with some example code and documentation. It is very easy to install and use. We'd highly recommend using this tool to create your own Test Suites.

 
 

Precision Naming

It is easier to maintain software that reads like English than software that is filled with codes or unintelligble names. Precision naming discusses the importance of spending time to come up with names that mean something to another reader of the code.

vvv

Software that is hard to understand is a liability: The code becomes difficult to maintain, thus making life difficult for programmers and bloating company maintenance budgets.

In a piece of code in the PLBS system, I came across the following number: 8640000. I had no idea what this number was. I inquired about the number and discovered that it was being used to do some date arithmetic. There is nothing wrong with using 8640000 in an algorithm, but it needs to be called NUMBER_OF_SECONDS_IN_A_DAY, or whatever it happens to be, not some "magic number."

I saw numerous examples of "magic" numbers scattered throughout the code. In a call to a method like "getgreat" (which is badly named itself), a programmer passed in the number 6. But what does 6 mean? It means nothing to someone who didn't write the code or who isn't familiar with the getgreat method. Such code needs to be made more intelligable, because while it is no big deal on a very small project, as a system grows, there can be so many of these "magic numbers" that it becomes very difficult to make sense of or maintain the code.

Therefore:

Choose intention-revealing, precise names for all of your variables, constants, methods names, and object names. If you find something that is badly named, refactor the code by making the name change.

vvv

Some of the worst names encountered during the audit were getClientStuff() and sendClientStuff() .
 
 

Fat-Free Code

Given a large body of code, the challenge for any team member is to understand the code, in order to be able to maintain or enhance it. Yet what if there is code in the system that does nothing at all?

vvv

Code that serves no useful purpose whatsoever is a liability: It can complicate what should be simple, confuse and mislead others, and generally lead to unwanted behavior.

In the PBLS, I saw too much fat: code that might have been used but had been abandoned and never removed. Such code made sections of the PBLS programs seem more complex than they needed to be, and contributed to code bloat.

In one case, I found a line of code that was actually left over from a copy-and-paste operation. This line of code really served no purpose whatsoever and could easily have contributed to a nasty, for-do loop bug.

Generally speaking, removing all non-essential code from a system helps make a system easier to maintain, enhance, and debug, and this should be an ongoing goal of all EJ programmers. This is especially true of any code that has been checked into version control. If code is no longer being used, it should be removed from the latest release of the software as early as possible.

Therefore:

Remove all code as soon as it becomes non-essential.

vvv

One of DataManager's largest pieces of "fat" is the use of POOLS. Pools of connections into the BTRIEVE database are not being used. Yet a good part of the code used to implement this feature remains in the DataManager code. It would be a good idea to refactor DataManager to remove this unused code, making the program simpler to read and simpler to (eventually) rewrite in Java and ORACLE.

PLBS currently relies on IBM's MQSeries to obtain data from the Jeppesen system. From our analysis, MQSeries did not seem to be a good choice for the following reasons:

  • MQSeries is generally used to transport data that absolutely must get to its destination (regardless of connection problems or hardware failures). Yet the data being passed to PLBS's DataManager did not seem to fit this description.

  • There is an efficiency problem introduced by MQSeries: A PLBS programmer reported that some functions in Jeppesen return a lot of data, which has to be heavily parsed into one string before MQSeries can pass it to the DataManager. Using CORBA to communicate with Jeppesen would make this much more efficient, since little or no parsing would need to occur.

  • MQSeries is a fairly complex, costly piece of technology to own, and it is not always easy to find (or retain) people who know how to use it. If the product is not absolutely necessary, we think it is a good idea to replace it. CORBA may be a better solution.
 
 

Small Parameter Lists

. . .
PRECISION NAMING helped explain the importance of accurately naming variables and methods. Now we'll consider the importance of keeping parameter lists short.

vvv

It's difficult to understand methods that expect too many parameters: Programmers can focus on about five to seven parameters, beyond which their eyes glaze over and their comprehension declines.

Many of the methods within the PLBS expect too many parameters. This makes the code difficult to read and understand. Generally speaking, the coding pattern seems to rely heavily on passing in many paramters to methods and then passing out many values through "out" paramters.

A much simpler and better way to program is to use structures and/or objects to pass data in and get data out. Passing in and getting back well-named (see PRECISION NAMING) structures and/or objects is a much better coding practice, which will make systems easier to understand, update, and maintain.

Therefore:

Keep parameter lists small. Use structures or objects to contain larger numbers of variables, and favor return results over "out" parameters or references.

vvv

When a method is well-named and when it expects a small, managable number of parameters, the method itself can still be too long (see SMALL METHODS).

 
 
Martin Fowler discusses the importance of writing intention-revealing names in Change Method Signature, one of the refactorings from his forthcoming book.
 
 

Small Methods

. . . To complete making a method easy to understand, enhance, and maintain, make the method body small, delegating calls to other methods within the greater method.

vvv

Methods that are large (on the order of hundreds of lines of code) are difficult to understand, maintain, and enhance, and thus represent a liability within a system.

The vast majority of methods within the PLBS (both in C++ and Java) are far too long.

The length of these methods contributes to a style of coding that harkens back to the days of Fortran or COBOL. This is far from what represents either well-structured or object-oriented code. And while it may be relatively easy for a method's author to understand, debug, and extend such code, it is typically difficult for other team members (current or new) to manage.

Therefore:

Create methods that are small in size and easy to understand. Let such methods delegate calls to other, smaller methods that are responsible for their own pieces of work.

vvv

A good way to shorten the size of methods is to use GUARD CLAUSES. . . .

 
 
Martin Fowler discusses how to replace big methods with smaller methods in Extract Method, one of the refactorings from his forthcoming book.
 
 

Guard Clauses

. . . how can you make complex, nested logic simpler? An excellent technique for simplifying code is to introduce guard clauses.

vvv

Nested condition logic--"if" statements within "if" statements within "if" statements--is hard to read, hard to maintain, and not a good way of writing code.

The PLBS code is rife with highly nested conditional logic. Methods go on for pages and pages, with outer "if" statements stretching for hundreds of lines. This is a poor style of coding because it can be very easy to introduce bugs when modifying or enhancing such code.

The solution to using nested conditional logic is to write code that checks for certain conditions upfront, and if they are not met, exits the caller from the method. These boolean checks are called "guard clauses."

The code that kicks the caller out of the method can either throw an exception or return an error code. It would be wise to AGGRESSIVELY REFACTOR the PLBS's highly nested condition logic into a series of guard clauses.

Therefore:

Replace all nested condition logic with guard clauses, to make the code simpler to follow and easier to enhance and maintain.

vvv

It is very helpful to have TEST SUITEs in place before refactoring nested logic into guard clauses. . . .
 
 

Decoupled Logging

. . . writing out log files is a common task. Yet how can you program a system so that business logic and logging aren't tightly coupled?

vvv

Code that writes input or output to a log file is often mixed with business logic, complicating code unnecessarily.

The PLBS is required to log inputs and outputs to log files. Yet the logging code is heavily mixed in with PLBS's business logic, making routines more complex than they need to be, and more difficult to modify when a change must be made to either logging or business logic.

In the SessionManager, log data is being written to an Oracle database, which is a time-consuming activity that can easily fail when given an unavailable database or a bad user name or password. Thus, a good deal of error handling is also needed to ensure that logging is successful, and this extra code contributes to code bloat within a method (see SMALL METHODS).

To minimize complexity and method length, and to reduce coupling between logging code and business logic, it is best to use object wrappers (known as Decorators) for logging activities. In VisiBroker, this is best accomplished using either Smart Stubs, Interceptors, or Object Wrappers, while in straight object-oriented code, this is best implemented using the Decorator pattern (see Design Patterns, by Gamma, Helm, Johnson, & Vlissides).

Therefore:

Decouple logging code from business logic by wrapping business objects with logging objects that delegate calls to business objects. Logging wrappers may log data either before and/or after business logic calls.

vvv

Wrapping objects is a powerful way of adding behavior to a system without having to modify the system. DECOUPLED DEBUGGING is a way of using object decoration (or wrappering) to easily turn a system's debugging output on or off. . . .
 
 

Decoupled Debugging

. . . It is difficult to debug a system that is multi-lingual or composed of distributed objects. Debug code helps but if it is tangled up with business logic it can slow down a system, make it harder to maintain, or be difficult to turn on or off. Decorators provide a way to simplify this process without sacrificing the need to write robust debugging code.

vvv

In distributed systems, debugging code may need to live within a running system, but it does not have to be mixed in with business logic.

Most of the debugging code in the PLBS is completely mixed in with business logic. Combined with all of the logging code, the logic within many methods has become overly complex. In addition, most of the debugging code has no way of being turned on or off. Thus, all performance tests of the system contain the time it takes to write out debugging output (a task that can actually consume a lot of wasted time).

A simpler, better way of writing debugging code, especially for distributed systems, is to use object decoration (i.e., the Decorator pattern). In VisiBroker, one can use Smart Stubs, Interceptors, or Object Wrappers.

The decorators can be written such that a system can optionally turn on or off debugging: This is best accomplished by creating object factories that can return either "debug-wrapped" objects or "debug-free" objects.

Therefore:

Decouple debug code from business objects, such that the debug code may be added or removed at will, using object decoration.

vvv

. . .

 
 
Martin Fowler discusses how to simplify conditional logic in the following refactorings:
 
 

Objects By Value

. . . when writing distributed systems, designers must decide when to pass client programs references to remote objects, raw data, or object passed by value.

vvv

Sending raw data from a remote object to a client is sometimes the best idea and sometimes the worst. When making the decision, designers must consider network time, marshalling and unmarshalling time, code complexity on the sending and receiving sides, and ultimately what will support the most efficient, extensible behavior.

In the PLBS, the SessionManager spends some time packaging up some data to send to a remote client (on a Libretto), and when that data gets to its destination, it then needs to be unpackaged before it can be used by the remote client. In addition, the remote client sends data to the SessionManager in the same fashion.

This looks like a rather inefficient way of spending time, given that VisiBroker supports the passing of objects by value. When programs pass objects by value, they do not have to spend time packaging up data and unpackaging it: The programs simply use the objects as they would any variable.

This is highly advantageous since it means that the object's data does not have to be exposed (i.e., it can remain encapsulated, and thus may change its format at a later date, with no side effects on either client or server).

Therefore:

Send and receive objects by value when it is faster and easier to do so.

vvv

iSessionManagerImpl's getClientStuff method may be refactored to return the contents of dataObject, instead of relying on a byte_arrayHolder and an "out" parameter. The simplest way to implement the refactoring will be to reverse the return parameter with an "out" parameter (i.e., instead of returning an int, make the int an "out" parameter and let the method return the contents of dataObject). The new method signiture would look as follows:

public Vector getClientStuff(IntHolder returnCode)

In the current method, dataObject is filled with the contents of a variable named vectorToSend. In the refactored method, the return result of the method can simply be vectorToSend.

Please note that we generally prefer using CORBA exceptions vs. passing int return results, but that would involve a larger refactoring. In addition, the method name getClientStuff should itself be refactored to express what is really passed back to the Libretto (see PRECISION NAMING).

 
 
For a good discussion of how to serialize objects using VisiBroker, please refer to the Programming VisiBroker class notes (these notes were handed out for the five-day class).

In the chapter on Caffeine, you'll find a simple example of how to pass Hashtables and Vectors by value, and you'll also learn how to pass your own objects by value.

The chapter also explains VisiBroker's extensible_structs, and how you can use them to represent pass-by-value objects in your IDL code.

 
 

Optimized Java

. . . there are optimized ways of using any language. But many textbooks and most courses rarely cover optimization techniques.

vvv

Many of the most basic and widely used Java objects and language elements are extremely inefficient and ought to be removed from any program that needs to execute with speed.

Most good designers and programmers know that it is best to optimize a system after designing and writing the system. Profilers are great tools for finding inefficiencies, and they can often point developers into areas of code that they would not expect to be bottlenecks.

Profiling Java code on a number of projects has revealed the slowness of a number of the JDK's objects (such as Vector and Hashtable) and language elements (such as "instanceof").

If one studies how code is implemented in the JDK itself, one will learn many coding optimization tricks.

To ensure that the PLBS runs as quickly as possible, it will be best to use a good profiling tool and to replace the inefficient Java code with more optimized Java code.

Therefore:

Frequently use a profiling tool to find and fix inefficient areas of a system. Learn which features and elements of a language are inherently slow, and begin to avoid using them when writing time-critical code.

vvv

We've used two Java profiling tools that you may consider using: JProbe by KL Group (800-663-4723), priced at approximately $499/developer, and OptimizeIt! 3.0 Professional by Intuitive Systems (408-245-8540), priced at approximately $389. Both of these products will take you a little time to learn, but will be useful over the long haul. The two products tied for a "Best of Show" award at a recent SIGS Conference for Java Development.

We'd also suggest that you use Java arrays in place of Vectors whenever possible. We have found arrays to be much faster than Vectors (the JDK itself uses arrays under the hood).

In addition, instead of using Java's slow instanceof operator (for an example, see SessionManager's sendClientStuff() method), it will be faster to use either codes to identify your classes, or to use polymorphism (in which case you won't care about the identity of your classes).

PLBS's Libretto client is currently quite slow to start and execute. It uses the Java Foundation Classes (a.k.a. Swing), which is a very good framework, but still not entirely fast (you can write efficient Swing code, but it takes a lot of time).

We would suggest a quick rewrite of the Swing-based client program, using Java's faster, simpler AWT (Abstract Windowing Toolkit). And contrary to what we heard from PLBS programmers during the audit, it is possible to implement "hot-keys" (or keys that the pilots may type to move from screen to screen, instead of using the mouse). Since the current user interface of the Libretto client is neither complex nor sophisticated, it should not take more than a few days to migrate the Swing-based code to AWT.
 
 

Software Updates

. . . code changes over time, and it is often necessary to redistribute newer versions of code. Everyone wants this to be a painless process, so many products advertise that they do code updates painlessly. But are these tools necessary or is it relative easy to write a code distribution process for a distributed system?

vvv

Distributing newer versions of code can be relatively easy to implement. And yet companies often think they need to buy expensive software to manage this process.

The PLBS has a definite requirement to remotely update code on the Librettos when PLBS client code changes. The team has purchased a product called Backweb which may or may not make this a painless process.

Yet it is unclear that a tool is needed at all. Since the Libretto program that is running is a fully fledged Java application, it is not subject to certain sand-box limitations, which would prevent a program from writing to a hard drive. It is therefore quite possible that the system could update itself by simply downloading a JAR file and writing it to the appropriate directory.

Therefore:

Carefully consider how to perform software updates without a tool before deciding to introduce yet another tool into a system's administrative process.

vvv

. . .
 
 

Business Values

. . . software systems are developed to solve business objectives. Inidividual preferences, such as languages, methodologies, or products, must be subordinate to these objectives.

vvv

If individuals pursue their own agendas in the implementation of systems, business objectives may be compromised. Technologies are often chosen not because they are the best solution but because of individual comfort levels with that technology.

Java is a simpler, cleaner, lanaguage than C++ that allows developers to be more productive. The Java community is expanding rapidly while C++ is in decline. Using C++ because of someone's personal comfort level will leave the enterprise with a more complex, harder-to-maintain, more expensive system.

This is an example of a business value. Given EJ's existing code base, the quickest migration path towards Java is best for the enterprise. Given that PLBS already contains C++ code, it is clear that the quicker this code is refactored to Java code, the better off EJ will be.

To be highly effective business technologists, team members within EJ's staff must make their own preferences secondary to more important business objectives.

Therefore:

Keep the overall business objectives uppermost in consciousness when choosing technological solutions.

vvv

. . .
 
 

Simplicity First

. . . it is difficult to create simple, easy-to-use software. The majority of designers and programmers overcomplicate software, and this added complexity has a high cost for an enterprise.

vvv

Technologists often overengineer software, making it more complex and flexible than it needs to be.

Simplicity does not seem to one of the overarching BUSINESS VALUES of the PLBS team.

Much time, energy and money can be wasted in the effort to create flexible software. Yet often a large percentage of the built-in flexibility is never used, thus contributes to the "fat" within a system (see FAT-FREE CODE).

Simplicity is not a license to hack. It is a challenge to write software that is simple, functional, and easy to enhance. The PLBS team would do well to aim for simplicity, as it continues to design, debug and refactor the system.

Therefore:

Design and write software that solves business objectives in a simple way, without introducing unecessary flexibility.

vvv

. . .
 
 

Egoless Debugging

. . . bugs can be extremely difficult to resolve. It's often more efficient to let another programmer attempt to debug some code than it is to struggle for days by onself.

vvv

When a programmer gets rooted down by a bug, he or she can waste an inordinate amount of time trying to find a solution. This effort can rob a project of valuable time and reduce the programmer's productivity to a crawl.

Bugs can often be resolved more efficiently when programmers remove themselves from the situation, and invite others to have a look.

It is often a challenge to do this, as it can involve suspending one's ego in favor of getting to a solution faster.

The PLBS team is already doing this, to an extent. The recent C++ memory bug was resolved relatively easily when another pair of eyes looked over the bug, offering a simpler solution to the problem.

Therefore:

When faced with difficult bugs, put aside one's ego and work with team members to find a solution.

vvv

. . .
 
 

Borderless Development

. . . what is the best physical configuration for a development team?

vvv

Software developers are more productive when they work together than when they work alone. Yet it is commonplace for developers to work in cubicles and offices, isolated from their team.

Therefore:

Create borderless development environments in which developers may easily communicate and work together.

vvv

. . .
 
 

Information Sharing

. . . when individuals make it a habit to share the knowledge that they acquire, the team itself may become more productive.

vvv

Developers often learn new techniques from books, magazines, friends or mentors. Yet often they fail to share their new found knowledge with the members of their team.

The PLBS team is working with languages and products that are relatively new to them. Everyday individuals learn new things about the various technologies. This is valuable information. If it is shared with the rest of the team, the team itself can become more productive.

Since the PLBS team does not currently work in a BORDERLESS DEVELOPMENT environment, they may best share information by using an email list server or by posting notes on a shared wall.

It is very important to share ideas and techniques that increase productivity or reduce complexity. Such ideas can come from valuable training classes, PAIR PROGRAMMING or a meeting with a mentor.

Therefore:

Remember the most valuable new knowledge you acquire and endeavor to share it with your team.

vvv

A pattern language is an excellent medium for sharing hard-won knowledge.

 

FacebookFacebook  TwitterTwitter  linked inLinkedIn