by Albert Dorofeev
I am writing this as a response to the tendency in many groups to building frameworks and generally middleware to answer the needs of software developers in general and driver developers in particular. I am confronted with this problem myself while examining the possible solutions to driver development cycle improvements in our operating system. ``Framework'' became a buzzword and many people think it is an ultimate panacea to all the problems the software development poses. I will try to show that this is not always quite so.
If you are confronted with the device driver development process you may be thinking of building a framework to ``make the life easier''. Or it may be a client that requests you to build a framework for a particular application. The latter happens more and more often. Let's think about it a bit from the point of view of software analysis.
When the customer says that he wants a framework he is providing us with a solution to his problem. Nothing is wrong with that if the customer analyzed the situation and came to a conclusion that a device driver framework is actually what he needs. However, if this is not a statement based on preliminary analysis of the actual problem it would be helpful to analyze the situation and see what the problem is instead of jumping to conclusions.
One clear sign of the trouble is the absence of clear requirements towards the framework (or any other software solution) development. The absence of requirements or very vague and unclear requirements mean that the problem analysis was not done and the customer has no idea what he actually needs.
Let's try to analyze and understand what is the problem with the device driver development process?
Device driver development costs a lot and it is very hard to predict the cost of a particular driver. As a consequence it is hard to plan device driver development. Even if you have to write a single driver it is hard to predict how much resources that is going to consume. Imagine what happens if you have to write, let us say, a hundred of those? So, what you would like to do is to take that uncertainty level down. You want to have a more precise planning for the drivers you develop. For that you have to have a way of getting better estimates on the resources that go into a single driver.
It is hard to write a device driver and to debug it. The driver development is like writing new operating systems, you need very skillful people and their time costs a lot. This brings us to the second point: we would like to spend as little as possible of those engineers' time on a single driver. The design and development of a driver may not take longer than it is strictly necessary because otherwise every such driver turns into a little but very expensive project on its own. In fact, we would like to develop drivers using some other resources (like CPU time) if possible rather than the very expensive driver developer's labour.
This is not all though. Driver development takes a long time. It is desirable and sometimes absolutely necessary to get the drivers in a much shorter time than you are used to. You may be developing a new modem card, porting your hardware from PCI to PCMCIA, creating a new platform and so forth. You can actually write a driver only when the hardware becomes available. On the other hand, you do not have much use for the hardware until you have a driver for it. The point here is that you want to get the driver written for that particular piece of hardware of yours in a minimal time frame.
So, what do we end up with? First of all, we want to shorten the development cycle of drivers. Second, we want to make the driver development process more uniform taking it from the area of art to the area of developing software that can be planned.
These are the ultimate goals. They may be reached through a multitude of activities that will be discussed later in this document.
Actually, if you come to think about the two directions stated above, you will notice that they are very dependent on each other. Or, rather, they have a strong positive feedback to each other. Shortening the development cycle in most cases means making the development process more uniform and strict and making the uniform development process will shorten the development cycle as a consequence.
You can think of different ways to achieve shorter development cycle, some of which are not at all software-oriented and some are. Let's have a look at some of the directions in which you may want to work:
This is a large section that became increasingly popular. Let's just remember object-oriented design, patterns, frameworks -one of the primary goals of each is the reuse of the code and sometimes the reuse of the original designs and ideas. There are basically three levels of reuse: full reuse, partial reuse and no reuse.
Applied to the device driver development, the first one means you do not develop a driver but you somehow get a driver for the device. This may include buying a driver from the OEM of you board, getting one for free from a friend or using a driver from a compatible device. That's all what there is to it. Unfortunately, this way is not always open.
If you are investigating the possibilities for code reuse then you would not probably want to fall into the ``no code reuse'' category because that would mean you have to write every driver from scratch. However, sometimes it may be an efficient solution to concentrate on other ways to improve the process.
Now the partial code reuse is the one where most of the attention is focused. In the real life it happens very often that you have to write a driver because you have no chance of getting one anywhere else or you are not willing to pay for it. In this case you want to ensure that this development is not only useful in itself but also will profit in the future for other drivers. It does not always work but that's the idea at least. Unless, of course, this is the only driver you write and you are sure you will not want to mess with drivers ever again, in which case you are better off paying someone to write a driver for you. So, people focused a lot of their attention towards the code and design reuse for the drivers and they came up with a few ideas:
Modules appeared quite a time ago too. It was noticed that if the system can be modularized in some way then some of the modules could be reused in other systems. The level of modularization may differ dramatically, of course. In application to device drivers, we can imagine a single driver to be modularized with the purpose of having a few well defined parts some of which would go into other drivers in the future. The modern high-level programming languages provide a number of techniques to modularize code.
Middleware and frameworks is a comparatively recent ``advance'' in the design techniques. Let's see how it applies to driver development. It has the same idea in the background as the libraries: move common functionality out of the driver and put it somewhere in a shared part accessible to all drivers. The approach of frameworks is claimed to be better because the shared part keeps the control and invokes the driver code when necessary. It is not clear whether this should be seen as an advantage, I prefer to think that it is simply different. What middleware provides you as a driver developer is a kind of a ``different world''. This environment is hopefully helpful in driver design and takes some burden off your fingertips. On the downside the middleware tends to grow too fast. The libraries are controllable - if you think a library is too big or too slow you just don't use it. You cannot stop using the middleware though - it has the control. This is a very dangerous position when a driver developer is not given a choice of refusing to use the provided software. Besides, why do you think middleware is aliased with ``bloatware'' so often?
I tend to think of modules and libraries as one way of ensuring the design and code reuse as opposed to the middleware and frameworks on the other hand. Due to the fact that libraries and modules are generally smaller and less costly to develop they are easier to sacrifice. The libraries and modules do not impose any control on the driver developer. The developer is free to choose whether to use one or not. This results in a Darwinistic evolution between the modules and libraries1 where the useful libraries survive and replace the useless and clumsy. This evolution process does not work for frameworks and middleware as you can guess. The middleware does not generally have enough competition due to the size and cost of development. The driver developers cannot choose between using or not a particular part of it for it imposes a great degree of control over the drivers developed. This does not necessarily mean that frameworks are useless, they can be useful but it is more difficult to ensure their usefullness in the absence of competition. And again the frameworks may be only accepted or rejected as a whole which makes the framework development a very risky investment.
Every of the abovementioned methods has about the same qualitative impact to the development cycle length and cost. You have to make an investment in the beginning to build up the supporting software. Hopefully this investment will pay off in the reduced cycle of the development during the supporting software life-cycle. It is easy to see that middleware and frameworks request much resources to be committed at the beginning stage of the project. The software is very short-lived these days and the framework must be very efficient to be able to return the investment in a short time frame. The design of the framework therefore must be considered as a major investment in a risky area and must be examined carefully before additional resources are committed to its implementation.
There is a number of ways that allow us to improve the driver development process. The development process here should include analysis, design, coding, testing and QA. Let's consider the following list of examples of what can be done in this direction:
As I was pointing out earlier the driver development process is an art in its current condition. It includes a huge amount of uncertainty and is hardly possible to plan. These methods attempt to impose a certain structure onto the driver development process. The structure and uniformity allow to follow up the development process more easily and provide a starting background for the development process.
Using tools can greatly improve the process as well. The following examples could be helpful in the driver development process:
Code generation tools are used to ``write'' code that is repetitive and easily isolated. This type of code usually is put in the libraries. However, if the code is ``almost but not quite'' the same every time, the generators can do a better job by analyzing the environment and changing the code appropriately. The libraries can be parameterized for greater flexibility but they cannot beat the generated code by size and performance because the libraries have to contain the code for all possible situations - dead weight code. The generators have their downsides too, the most obvious is that the generators must be tuned to produce fast and small code for every new situation that arises. Still in good hands code generation may be a very powerful tool able to cope with a large portion of the final code completely automatically.
Testing environments are crucial for driver development. Unfortunately, nobody still could come up with a testing environment that would be comfortable to use. The big problem with device drivers, of course, is their close relation with the kernel if the operating system and the ability to manipulate the hardware directly. The actions of the device driver are very hard to monitor sometimes because of timing constraints on their operation. The interrupt handling to top it all - and there is not much more than printing debug output that can help you. The dream of an automated testing environment haunts device driver developers in their dreams...
Automated build processes are well known by now. Of course, it is better to be able to start the building of the whole thing (whatever it is you need to test your driver) with a single command and be sure that no single file will be missed. Unfortunately, there are tradeoffs here as everywhere. The systems that allow close tracking of everything that matters including compiler flags slow down the building process. Faster systems may be missing a file here or there so that you'd have to do it by hand sometimes just to be sure.
All these tools taken together may form a neat, fast, and comfortable environment and, again, they may not. If they do, the development will certainly take less time on the average because of the lighter burden of the routine work that does not require imagination.
Whatever tools, environments, methods are provided the developers have to learn them before being able to apply them successfully in the design and development process. It usually takes some time before people recognize the most efficient ways of applying what they learned.
In order to reduce the learning curve period the driver developers should receive adequate training. This especially applies to cases when driver development should be done for unfamiliar platform, in a strange development environment, for a new operating system and so forth. Since the drivers are very sensitive to performance issues it is necessary to find the correct ways of applying programming strategies, libraries, frameworks, etc. The driver developer training may range from simple documentation like ``how-to'' guides to seminars, courses and coach training.
Driver development may be made more efficient if developers are highly motivated to perform their best. Motivation is a serious subject that was shown to affect the productivity greatly. Of course, the direct environment of the developer has a great influence on his motivation - extrinsic motivation - and we have no control over that environment.
Since we cannot affect the extrinsic motivation of the driver developers (pay raises, fringe benefits, awards etc.) we have to concentrate on providing ways to expand their intrinsic motivation. The intrinsic motivation stems from the relationship between the developer and the work itself. Intrinsic motivator can be feelings of achievement, challenge, competence and sheer interest in the job.
The tools (in the broadest sense) should stimulate creative and innovative behavior on the part of the driver developers. The driver development process may be ``enriched'' in a sense by providing automation of the simple, repetitive, boring tasks leaving more time for the creative design part of the task. The documentation should not concentrate only on providing step-by-step instructions for a number of tasks but also suggest new ways of looking at the process, promote a variety of ideas, provide a range of design patterns that can be helpful in stimulating the innovative thinking of the developer and challenging him to step away from the routine.
Well, as you see, the frameworks are just one of possible directions in one of the sections of what can be done to improve the development process. They are not the ultimate answer to the ultimate question. Their role in the software development was largely overinflated in the past years. When used inappropriately, the frameworks become counterproductive and turn into a huge burden on the developers.
However, the frameworks do take their humble place in your toolkit. They are not evil, the people who misuse them are. The frameworks may be a valuable tool when they are suitable for the purpose and you should regard them objectively as one of the valuable alternatives when you start you next project. If you decide to use them, you should be very clear on the reasons why you do so.
This document was generated using the LaTeX2HTML translator Version 98.1p1 release (March 2nd, 1998)
Copyright © 1993, 1994, 1995, 1996, 1997,
Computer Based Learning Unit, University of Leeds.