This site contains older material on Eiffel. For the main Eiffel page, see

Eiffel for embedded systems at Hewlett-Packard

``Eiffel is the perfect embedded language...'':
an interview of Christopher Creel, HP CCD (Color laserjet and Consumables Division)  

How HP used ISE Eiffel to develop leading-edge printer software, used Design by Contract to preserve the work of its best designers, and in the process found bugs in its legacy software, discovered a flaw in a hardware chip, and learned a few lessons -- such as how to do in weeks what used to require months.

Few industries are more lucrative and more challenging than the printer business. This is one of the areas where Hewlett-Packard has built its unparalleled reputation, through its justly famous and wildly successful printer line. In 1994 alone, HP sold 5 million DeskJet printers and almost 4 million LaserJets.

          An obsession with quality  

As company co-founder David Packard writes in his book The HP Way:

    ``More for less'' became the goal for each new LaserJet model... DeskJet single-handedly created the revolution in color printing... The essence of customer satisfaction at Hewlett-Packard is our commitment to quality, a commitment that begins in our laboratories and extends into every phase of our operations.

An obsession with quality in software is the very definition of ISE Eiffel, so it is not surprising that HP has chosen ISE Eiffel to help maintain and increase its edge in the printer business. HP's printer division has been taking advantage of Embedded Eiffel, to tackle some of the most difficult challenges of this fiercely competitive industry.

          Zero Memory Leak. No excuses.  

Printer firmware raises some of the most difficult issues of any embedded development. A software error does not just mean that your job doesn't print: it can cause all kinds of catastrophes, starting with jamming and ending, in the worst case, with a broken engine!

Printer manufacturers typically rely on software to provide customers with sophisticated functionality while minimizing hardware costs. As a result, printer software can be extremely complex, reaching into the many hundreds of thousands of lines of code. Yet for cost reasons the result must fit in extremely limited ROM and RAM space, and take advantage of every CPU clock cycle available.

The RAM requirements are particularly tough. Because printers typically remain turned on for months, it is not enough for the software to use as little memory as possible: it must return every single byte that it ever uses. This Zero Memory Leak requirement was one of the key demands placed on the Eiffel software, and was met by ISE's garbage collection mechanism.

          Threads and GC: total independence  

Garbage collection was in fact one of the primary reasons why HP selected Eiffel in the first place. The printer software had to be multithreaded, taking advantage of the natural concurrency of printer tasks to divide the processing into a number of parallel threads. ISE Eiffel provides both a sophisticated multithreading library, EiffelThreads, which works in concert with the garbage collection mechanism.

A unique property of this combination is that each thread has its own garbage collector. In most existing thread-GC solutions, all threads share a single GC, so that if one thread runs out of memory all other threads must come to a halt until the GC has run its course. With ISE Eiffel, each GC manages the memory for one thread, so that no thread ever penalizes another's memory management. This one of the key properties of the environment that enabled HP to use software to meet some of the most ambitious goals for its new printers.

Christopher Creel talks about embedded Eiffel

Christopher Creel, R&D Firmware Engineer at Hewlett Packard, recently talked with Ann Bailey of Business Communications about his experiences of using Eiffel for embedded systems development at Hewlett-Packard.

In this candid and wide-ranging discussion, Christopher tackled many issues, from the use of Eiffel to improve the software culture of a company to the role of Design by Contract, how to manage the results of a company's programming gurus, and the future of object technology in the embedded world. Here are some excerpts for the benefit of readers.

What were the goals of this project? What were you trying to achieve?

What we originally set out to do was just a feasibility study. We were never supposed to ship this thing as a product! All we were trying to do was figure out if Eiffel was a good language for embedded applications -- a better alternative to the more classical languages that have been done in an embedded world.

          ``We feel that Eiffel is the perfect embedded language.''  

This is what most of HP would be interested in, since most of HP is doing embedded work.

This is an interesting study in how one division broke away and decided to try something that has not classically been used in the embedded systems world. And, as it turns out, we feel that Eiffel is the perfect embedded language.

Initially you were not going to ship. How did you start?

          ``The issues are RAM, ROM and speed.''  

To understand why we were asking ourselves whether Eiffel was a suitable language, you have to ask why it would not be suitable. Many people are comfortable with C++ as a language for the embedded world. With Eiffel the three primary concerns are the obvious ones: RAM, ROM and speed.

We have to fit into a small amount of RAM. We have to fit into a small amount of ROM (this is where our code goes).

And it's got to be fast. In fact embedded engineers have classically been speed fanatics.

          ``The primary issue is cultural.''  

But there was more to the feasibility study than those three requirements. The primary issue is cultural. We had to deal with the C-C++ culture.

What's the C-C++ culture?

It's the conviction that the engineer is God. The engineer can do anything. You withold nothing from the engineer. You put your ultimate trust and faith in the engineer's abilities.

Many people in the embedded world have been brought up with an arrogant view of software engineering: that we are infallible, that ultimately we'll be able to ship a product that is error-free because we are such fabulous engineers.

Most of the companies in this country still have the "Engineer is God" culture, whether they are using C or C++ or something else; even Java still has much of that culture.

It really gives an individual a warm fuzzy feeling to have his or her manager implicitly say "I trust you never to make a mistake".

Eiffel is the antithesis in every way, shape and form of the C-C++ culture. The ground assumption with Eiffel is that the engineer is not only fallible but extremely so, to the point that you must question every single thing that you're doing.

          ``Eiffel means questioning that the Engineer is God.''  

How did that culture affect the feasibility study?

It broadens the question. It means that just meeting the first three requirements -- RAM, ROM and speed -- may not be enough.

Ultimately software is not a science, not even an engineering practice; it's a human event. You have to give these fallible humans something that they will be willing to use. They might not be willing to put these types of restrictions on themselves, to give up the "Engineer is God" culture.

I'm surprised that culture has worked and hasn't been challenged. What if something goes wrong?

That's why we started this project to begin with.

Why try anything else? What was broken? We were of course meeting the cultural requirements -- the warm and fuzzy feeling. We were meeting the RAM, ROM and speed requirements, what may be called the "CPU clock cycles" -- how fast and tight an application will run.

          ``We had the CPU clock cycles, but not the engineering clock cycles''.  

But in the requirements for shipping a product there is yet another factor, what I like to call the "engineering clock cycles": how fast an engineer can turn out a quality product -- a product that works not just in the lab but in a factory where it gets bumped by forklifts all day long, and with code that is more or less bug-free.

We were failing on this miserably, we are still failing on that miserably, and frankly many large companies are failing on this miserably.

But then we found that our competitors were able to increase their engineering clock cycles by giving up on the CPU clock cycles. They were loosening up on all of our first three requirements: loosening up on RAM space, on ROM space and on speed. But as a result they were able to speed up their engineers to produce more features faster than we could.

And we also found that the customers liked it! They liked having a whole bunch of new features. All of a sudden our archaic yet fast products weren't meeting consumer demands. That's why we decided to try something different.

We decided that if our competitors were willing to give up a little bit on the first three requirements -- on the CPU clock cycles -- then maybe we could figure out a way to continue beating them on these performance requirements while tackling the fourth one, engineering clock cycles.

How do you get the engineering cycles without losing the CPU cycles?

The only way to achieve this is to step away from the C-C++ culture.

          ``As the complexity grows, errors start creeping in.''  

But if you stop assuming that the Engineer is God, and accept instead that you have lots of highly fallible engineers, you suddenly realize that most likely the state of your software is horribly flawed! Just as flawed as the humans are.

To make it worse, as the size of the software applications grows, its complexity puts more and more of a burden on the engineers, and errors start creeping in. This is unusually bad in the embedded world because it is classically filled with electrical engineer majors who have had no training or experience in large scale software engineering. They started a few years ago with small embedded applications, but now the applications have grown tremendously, often half a million to a million lines of code.

          ``We are in the Do Or Die phase. That's where Eiffel comes in.''  

It's that combination that makes the situation critical: human fallibility, and lack of software engineering skills. That's why I decided to try Eiffel.

We are in the Do Or Die phase; that's where Eiffel comes in. Eiffel one hundred percent corrects the cultural problems, by accepting that humans are fallible.

There is another very interesting aspect of Eiffel that few people can pick up on, because many people are not all that versed in large-scale software engineering and the realities of the software industry today. It has to do with the contribution of Eiffel's Design by Contract to preserving the work of the top engineers.

          ``Design By Contract saves the work of the one-ten engineers.''  

In most companies today, you have a small group of hard guns who are responsible for the core job. They are the engineers who come in, do the dirty work, and then get out.

Fred Brooks, in his book The Mythical Man-Month, called them the "one-ten engineers" because such an individual can do the work of ten normal engineers. Every company has one of them. They sit down one day from nine to five, and do more than some other engineer who has to work from eight until twelve an entire week.

So now you do have an engineer who really is God-like! But then the question becomes of how to harness that engineer's abilities to avoid disaster when he or she leaves.

          ``That's where C and C++ really fall apart.''  

That's where C and C++ really fall apart. We have seen the result when someone a great engineer leaves after writing this beautiful thing. A year later the other engineers come in, and because they don't immediately understand the solution they will start hacking it, and in the process they destroy it.

The consequence for the quality of the code base is a lowest common denominator effect: even though you have this great engineer, after a while the result of his work starts to degrade to the level of the work of those who are not as good, or don't care as much. Because C and C++ allow this God-like atmosphere there is nothing stopping them. They are allowed to do anything -- including destroying the good work of their betters.

They don't do this on purpose, of course; they just don't know any better. But it makes them feel bad, so you also get a slow degradation of morale; engineers become unhappy, get burned out, leave the company.

That is one of the biggest problems with the Engineer Is God culture: expectations are so high, and results so far from the expectations, that people's lives become miserable.

          Design by Contract to the rescue.  

Eiffel remedies this. You assume nothing. You assume everything is wrong. You assume everyone is out to screw you up. And then you assume that everyone is going to try and wreck your good work. That is where Design by Contract comes into place.

How does Design by Contract help preserve the work of the top engineers?

You build a white-box framework -- effectively, a scaffold. It tells you where to put the pieces but it really isn't the mechanism itself. It s simply a template, a specification, to which you will plug in the working components -- the implementations.

          ``You forever eradicate an entire class of bugs.''  

Any contract that you put in there will exist forever. That engineer, that one-ten engineer who builds these contracts at the base level, eradicates an entire class of bugs forever. Because he or she can see further into the future than most engineers, he puts the contracts in place for all eternity, once and for all destroying errors that other engineers could make 6 months, 2 years or 10 years down the road because they don't see the whole picture.

Eiffel has lots of other things, all those wonderful software engineering aspects. But in my opinion the most powerful concept in the entire Eiffel approach, which so few people really touch on, is that you can take that one-ten engineer and project his good intentions into the future forever. No one can ever destroy those good intentions again. That is unique and incredibly powerful.

          ``Morale goes up.''  

That's not to minimize all the other aspects, of course. Eiffel is single-mindedly focused on large-scale software engineering. Entire classes of maintenance problems, for example, disappear thanks to the simplicity of the control structure, the one-entry one-exit functions. That is just one minor example; there are many others. Eiffel, just by its design -- Bertrand is really a brilliant linguist. He has such incredible depth into what is required of a language to make it good, to eradicate entre classes of potential defects. But the best thing is this ability to preserve the work of the one-ten engineer. By becoming a contract lawyer he can build contracts into the base classes of the architecture. Because he can see further than the less experienced engineers, he can use the contracts to rule out all kinds of things that could go wrong in the future.

Because of the language itself, because of the way everything is designed for large scale software engineering, because of this ability to utilize your one-ten engineers better, morale goes up. You don't necessarily have to hack and kludge anymore.

How do you document the best engineer's intentions?

Eiffel is just rife with the idea of implicit documentation. As opposed to having a separate document that an engineer will probably throw away or use to balance his table, you take that document and embed it into the code.

Most people, when hearing about embedding information into code, think of comments. Comments are what I call benign documentation. They don't do anything, they become outdated, people don't read them or even remove them.

          ``With Eiffel you get proactive documentation.''  

With Eiffel you get what I call proactive documentation. Whenever you have a condition that must hold somewhere, you make it part of the code through an assertion. Much of the time it's simple stuff, like "this value must be between 0 and 255". You document all these assumptions that engineers make, especially the one-ten engineers, and you make them an enforceable part of the code!

C has a limited form of that, the assert instruction. In Eiffel it's an integral part of the language, it's closely integrated with the object-oriented structure of your software, and it serves both as proactive documentation -- to express the intent of the one-ten designer -- and as a testing, quality assurance, validation tool.

Through these mechanisms Eiffel gives the original engineer the ability to limit future engineers' choices, to lead them by the hand when they make changes and additions. It's much more powerful in that respect than C and C++ or any of the other languages I've studied.

          ``C++ is C.''  

Languages often get used far beyond different their original purpose. C is a great example. It started out as a relatively clean language. It was meant to build operating systems, low level stuff. Bertrand calls it a portable assembly language. And then what happened? They said "Ah this is the language, we'll never need another one as long as we live, it lets you do anything!" But as it turns out it's a terrible software engineering language. So what do they do? They come up with C++. C++ is C. It is not a different language. Many people have described C++ as a fancy macro-language for a macro-interpreter for C.

Yes, you can do anything in C. It's just that the complexity issues are so great that now you need an initial parser in order to get down to C. When that parser came, in the form of C++, everyone said "Oh this is the perfect language. We're never going to add anything again." But then they added multiple inheritance, then templates, namespaces, exception handling. They kept adding these things because they found that the language was deficient, yet they never wanted to admit that they need another language.

          ``Such incredible rigor, yet such openness.''  

So do we want HP as a whole to use nothing but Eiffel? No. Eiffel has this great loophole. It's this wonderful software engineering language with such incredible rigor, yet it has this amazing loophole in it -- the external clause. You can say that a feature of a Eiffel class is actually implemented externally, so you can call out to any language you'd like from within Eiffel. Therefore if we feel that Eiffel is inappropriate for a certain task, no problem -- you simply call out into the language that is appropriate. That is how we are using it today.

How does that work in your team?

Our team is the imaging team within CCD (HP's Color LaserJet and Consumables Division). Part of our C-C++ culture is that you're building software like ROM. You're building it to last. It's going to be around for a thousand years.

The cold, harsh reality is that if your architecture lives intact for more that a year, you have built something so phenomenal that it will go down in the history books.

          ``Everything is changing all the time.''  

Everything is changing all the time, all the parameters. That is the greatest thing about software. It's a human event, not a science. Science moves very slowly. How often does physics get a new set of axioms? But we aren't dealing with natural phenomena. We are dealing with a stream of consciousness.

The mentality in my team is: as an architect it is my responsibility to make myself obsolete. If I have not made myself obsolete at the end of a project, if I need to be around at the completion of a project to help the next team along, then I have failed, radically failed. Furthermore, everything I build I must build it to be replaced.

How do you do build something to be replaced?

Build it so that it is easily destructible. Build it so that an engineer can come in and say, "Boy this thing is really old, it's really archaic, we've got to get rid of it."

          Eiffel as an insurance against job insecurity.  

If you succeed, someone can remove a component and stick in another without any disruption to the rest of the system. So you need to build your stuff such that it is totally expendable, and also such that you yourself are expendable, because ultimately you are -- whether you like to think so or not.

The engineer is expendable?

There is no more job security, on either the employer or the employee side. These days engineers are coming and going at an amazingly fast rate, especially in areas like Silicon Valley. I've heard stories from friends of mine who have had headhunters come up and tap them on the shoulders in the parking lots "Hey, I've got a great company just down the street and we will pay you twice what you are getting now". As a company you need to protect yourself against the effects of that. You cannot use the traditional approach, which was to embed your documentation into your engineers or into your external documents. The external documents will become obsolete; the human document will leave.

The documentation has got to be in the code, it has to be expendable. Eiffel supports this, because the documentation and the interfaces are all in Design by Contract, and the system is structured into clusters, every one of which is expendable.

          ``Eiffel: the ideal orchestration mechanism.''  

Where in your engineering structure do you put Eiffel?

Eiffel shifts the focus away from CPU cycles to engineering cycles. C does the reverse.

So you should use Eiffel where those engineering cycles count. That is the majority of your software: contrary to what many engineers think, most of your cycles are not CPU cycles. If you have a large system -- say between two hundred and fifty thousand and a million lines of code, which is very large for an embedded system -- there is usually some kind of mechanical event that occurs due to some stimulus. The majority of the processing activity usually takes place right after that mechanical event

For instance if you had a scanner where you scan the information and than you do some kind of processing and than you ship it out to disk but the majority of your code is really dealing with data management in orchestration -- and Eiffel is an ideal orchestration mechanism. That's 90% of our code.

What was your biggest challenge?

Getting a run-time into a legacy system that doesn't play nice. Our legacy code is large, its memory management is rather complex. Getting memory in the embedded world is never an easy task, it is a resource that is like water in the desert. And so just finding memory for the run-time is going to be difficult. Exception handling is also an interesting question.

          ``You make Eiffel a static library.''  

Eiffel makes a few assumptions. For instance, it assumes that there is an exception handling mechanism available. It assumes that there is such a thing as longjmp and setjmp and these types of mechanisms. They are not always present in the embedded world. It makes certain assumptions about memory -- allocating and reclaiming it. These are hard questions.

These are only a few assumptions, but we must meet them. Fortunately we found an operating system that does: VxWorks. This gives us exception handling and memory management, pretty much like Unix.

Then we had to figure out how to drop in the run-time. And that was a difficult task, to figure out where to put it in, where to start it up, where to initialize it. You have to make the Eiffel runtime into a static library, without a "root object", able to interact with a multithreaded legacy application written in C.

          ``The Eiffel run-time allows you to specify all kinds of memory management schemes.''  

Another requirement was that each thread had to have its own garbage collector. We wanted a bunch of different threads to use Eiffel: then if there were only one garbage collector and one of them went into garbage collection, all threads would have had to stop, and that's bad.

Also, we needed to be able to start up and shut down garbage collectors at will.

We found that the Eiffel run-time indeed allows you to specify all sorts of different memory allocation and reclamation schemes; you can tell it to allocate very small but slow, or very big and fast.

Also crucial was memory reclamation. When a thread dies, with its garbage collector, it is essential for that thread to relinquish all of its memory for another thread to use.

Yet another requirement, for the use of Eiffel in concert with a complex legacy system, was to make sure that all information on the stack was thread-specific: we found that some of our code was jumping around using setjmp and longjmp; so when they did a long jump, had that variable data been stored on the stack, it would have gotten blown away by the longjmp. No matter what our horrific things our legacy code might do, the Eiffel stuff needed to be separate.

          ``ISE had a real slick solution for this stuff.''  

It kind of fire-walled away into ROM bad things our legacy code would do.

Fortunately ISE had a real slick solution for this stuff. Each thread had its own private variables and that is where the actual garbage collector went. Whenever you wanted to get the garbage collector you just got it from the threads context. That worked out real great. We were able to blow away garbage collectors at the drop of a hat. Boy, it's real sweet!

Were the RAM requirements tough to meet?

We needed to stay between 50K and 70K. Fortunately ISE Eiffel seems to accommodate that just fine.

          ``ISE gave us a laundry list of things that could be kept or removed.''  

Actually ISE gave us a really nice solution. When we dealt with other run-time vendors they just said "Sure, we can do this, we can get it down for you". What ISE did was that they gave us a laundry list of stuff and they said: "here are the things that we can remove to meet your ROM requirements. Go through the list, check off the stuff that you don't want".

It was like a price list -- this is how much this thing costs and if we remove it this is how much you'll save --, only with "cost" meaning number of bytes. That helped us quickly determine just how big this thing was going to be.

          ``You develop your stuff at home in your underwear eating cheetos, bring it to work, and it just runs.''  

One of the interesting side benefits of using Eiffel in the embedded world is that you can develop your functionality independently of the embedded code.

ISE Eiffel is so portable between the different platforms that you can develop it on your PC at home in your underwear while you're eating cheetos and then when you're ready you can go to work, plug the thing in, and usually it just works because you've tested it independently of the actual printer code. When we brought it to the printer code we might get one or two contract failures, but that was usually about it. Most of the times it just worked the first time we plugged it in.

What about the contract failures?

          ``Thanks to the contracts we found bugs in the legacy code. We found a chip defect thanks to Eiffel!''  

They were very important! Rarely were they due to the Eiffel code. Usually it was due to the legacy code interfacing with the Eiffel code. What we often found was that we found bugs that we had no idea were there -- strictly thanks to the Eiffel code.

We actually found a chip problem this way: Eiffel found a floating-point bug on the chip we were using. Everything was working fine on the simulator; usually when things work on the simulator they work on the hardware, but in that case when we moved to the hardware an assertion failed. In the end we found it was a problem with a floating-point operation on the chip!

          ``Just having Eiffel code improved our existing legacy code.''  

We also found, by putting Eiffel rescue clauses on the Eiffel side in our external functions, that if the C code failed because of some horrible thing, the Eiffel code could actually recover for the C code. Just the very existence of Eiffel on our legacy code improved the quality of our existing legacy code.

We had never really thought that was going to happen, nor did we know to what extent it was going to happen, but it did happen twice.

          ``This was a powerful moment for our management.''  

This floating-point precision problem in particular was really big. Potentially these are million-dollar problems; look at the Intel Pentium bug. So it was a real powerful moment for my management when that happened.

          ``Once written we barely touched the Eiffel stuff. We never had any problem with it.''  

What lessons did you learn?

I spent ninety five percent of my time working on the C side, just getting the C side prepared for Eiffel and getting the C code working correctly with Eiffel. Once we got that all set up we never had any problems. We never had any problems with the Eiffel code -- the stuff that we developed outside of the printer. And we barely ever touched it. Once we wrote it we barely ever touched it.

Most of our time was spent just trying to get the C stuff, dealing with the average problems of C -- overwriting an array boundary, writing some null values, all of the things that fallible humans do.

So the lessons learned were not really the ones we were seeking. We were looking for answers to: Could we use Eiffel for our RAM, ROM, speed requirements? Could we get it into our cultural requirements? But a lot of the more powerful lessons were "Holy smokes, if we drop this in, it actually heals our legacy code, it's like putting balm on a wound!"

          ``We could do in two weeks what we were previously doing in months.''  

It was also an eye opener. "Look how slow we're moving! We built this Eiffel stuff in two weeks and it's taken us months to get it to work in the legacy code. Come on! Why is this? We should be moving as fast as we are on the Eiffel side".

That showed us that engineering clock cycles would vastly improve if we could just get going.

Portability was the other great eye-opener -- developing the Eiffel code at home while eating cheetos, then coming in and dropping it in. It's one hundred percent portable! It has the exact same behavior on three platforms -- on Unix, on my PC and on the hardware. Our current legacy code isn't all that portable; we can't take it off the hardware and put it on my PC at home. But here I am taking Eiffel code and using it all over the place.

          ``An ideal system for medium to large scale embedded systems.''  

So, yes, Eiffel is indeed an ideal system for medium to large scale embedded systems where your ROM requirements are somewhere below 300K.

Another good point. For C and C++, when your features grow, your code grows with it. The curves are either the same of exponential. You're eating up more and more ROM in order to accomplish particular features. With Eiffel, because of its powerful reuse mechanisms, your ROM requirements really don't go up nearly as fast. So while your initial outlay in ROM might be relatively large, say 300K for an entire system, as your features grow it's a long term investment because ROM requirements will grow much more slowly as you add features.

What about RAM?

For the system that we are doing right now, which is really sophisticated already, we're shooting at about 70K.

I would say that Eiffel is an ideal solution for medium- to large-scale embedded applications: because ROM size does not increase as quickly and because it takes away all the trouble and pain and heartache that we go through just to make sure that we're not overwriting array boundaries, accessing non-existent variables, de-allocating memory that we either never allocated, or forgetting to deallocate memory -- all aspects of memory management.

          ``Microsoft Word overwites an array boundary and you have a GPF. We overwrite an array boundary and your printer gets damaged.''  

This is very important to embedded people. Say Microsoft Word overwrites an array boundary and you get a general protection fault. Big deal -- you can shut the thing down and no one knows. Now say you override an array boundary and you get a general protection fault on your printer: your five- hundred page job just got blown away in the middle, you got to restart the whole thing -- you might have gotten a paper jam, you might even have damaged the engine.

C and C++ have the memory management problems and don't support large scale software engineering, so you're up for all sorts of problems. Smalltalk has the memory management but it really wasn't designed as a large scale software engineering language so you can do some pretty amazing hacking with it. It doesn't allow you to extend that one-ten engineer's good intentions as well as Eiffel does.

We didn't expect that using Eiffel improved our legacy code just by the fact that it caught bugs that we had never seen before.

Any final thoughts?

There is an untapped market for Eiffel in embedded and legacy systems. HP sees Eiffel as a major force in large scale software engineering if it is positioned correctly.

          ``They are using C, C++, Java. HP can use Eiffel and kick their butts.''  

We know that we are ahead of our competitors in this. Most people are still using C, C++, perhaps Java. HP can use Eiffel and kick their butts.

Of related interest