Thursday, June 25, 2009

Reusability

                Reusability is the ability of software elements to serve for the construction of many different applications.The need for reusability comes from the observation that software systems often follow similar patterns; it should be possible to exploit this commonality and avoid reinventing solutions to problems that have been encountered before. By capturing such a pattern, a reusable software element will be applicable to many different developments.

                Reusability has an influence on all other aspects of software quality, for solving the reusability problem essentially means that less software must be written, and hence that more effort may be devoted to improving the other factors, such as correctness and robustness.the more autonomous the modules, the higher the likelihood that a simple change will affect just one module, or a small number of modules, rather than triggering off a chain reaction of changes over the whole system.

             Here again is an issue that the traditional view of the software lifecycle had not properly recognized, and for the same historical reason.you must find ways to solve one problem before you worry about applying the solution to other problems.But with the growth of software and its attempts to become a true industry the need for reusability has become a pressing concern.A simple architecture will always be easier to adapt to changes than a complex one.
                        
          Reusability will play a central role in the discussions of the following chapters, one of which is in fact devoted entirely to an in-depth examination of this quality factor, its concrete benefits, and the issues it raises.The object-oriented method is, before anything else, a system architecture method which helps designers produce systems whose structure remains both simple and decentralized.

Programming Environments

                   It is usable in many operating environments, for many sets of data.To become a generally usable programming product, a program must be written in ageneralized fashion. In particular the range and form of inputs must be generalized as much as the basic algorithm will reasonably allow. Then the program must be thoroughly tested, so that it can be depended upon. 

                          This means that a substantial bank of test cases, exploring the input range and probing its boundaries, must be prepared, run, and recorded. Finally, promotion of a program to a programming products.It requires its thorough documentation, so that anyone may use it, fix it, and extend it. As a rule of thumb,I estimate that a programming product costs at least three times as much as a debugged program with the same function.

                     Moving across the vertical boundary, a program becomes a component in a programming system. This is a collection of interacting programs, coordinated in function and disciplined in format.So that the assemblage constitutes an entire facility for large tasks.To become a programming system component, a program must be written so that every input and output conforms in syntax and semantics with precisely defined interfaces.

                    The program must also be designed so that it uses only a prescribed budget of  resources memory space, input output devices, computer time. Finally, the program must be tested with other system components, in all expected combinations. This testing must be extensive, for the number of cases grows combinatorially.It is time consuming, for subtle bugs arise from unexpected interactions of debugged components.

Robustness

                Robustness is the ability of software systems to react appropriately to abnormal conditions.Robustness complements correctness.Correctness addresses the behavior of a system incases covered by its specification; robustness characterizes what happens outside of that specification.As reflected by the wording of its definition, robustness is by nature a more fuzzy notion than correctness. 

                       Since we are concerned here with cases not covered by the specification, it is not possible to say, as with correctness, that the system should “perform its tasks” in such a case; were these tasks known, the abnormal case would become part of the specification and we would be back in the province of correctness. This definition of “abnormal case” will be useful again when we study exception handling.

                   It implies that the notions of normal and abnormal case are always relative to a certain specification; an abnormal case is simply a case that is not covered by the specification. If you widen the specification, cases that used to be abnormal become normal even if they correspond to events such as erroneous user input that you would prefer not to happen. “Normal” in this sense does not mean “desirable”, but simply “planned for in the design of the software”.

                Although it may seem paradoxical at first that erroneous input should be called a normal case, any other approach would have to rely on subjective criteria, and so would be useless.There will always be cases that the specification does not explicitly address. The role of the robustness requirement is to make sure that if such cases do arise, the system does not cause catastrophic events; it should produce appropriate error messages, terminate its execution cleanly, or enter a so-called “graceful degradation” mode.

The Programming

      One occasionally reads newspaper accounts of how two programmers in a remodeled garage have built an important program that surpasses the best efforts of large teams. And every programmer is prepared to believe such tales, for he knows that he could build any program.

            It is much faster than the thousand statements year reported for industrial teams.Why then have not all industrial programming teams been replaced by dedicated garage duos One must look at what is being produce a program.

      Ready to be run by the author on the system on which it was developed.That is the thing commonly produced in garages, and that is the object the individual programmer uses in estimating productivity.There are two ways a program can be converted into a more useful, but more costly, object.

      These two ways are represented by the boundaries in the diagram.Moving down across the horizontal boundary, a program becomes a programming product. This is a program that can be run,tested,repaired and extended by anybody.

Software Maintanence

                 Maintenance is what happens after a software product has been delivered.Discussions of software methodology tend to focus on the development phase.so do introductory programming courses. But it is widely estimated that seventy percentage of the cost of software is devoted to maintenance. No study of software quality can be satisfactory if it neglects this aspect.what is not acceptable is to have the knowledge of the exact length of the data plastered all across the program, so that changing that length will cause program changes of a magnitude out of proportion with the conceptual size of the specification change.

               A minute’s reflection shows this term to be a misnomer.A software product does not wear out from repeated usage, and thus need not be “maintained” the way a car or a TV set does. In fact, the word is used by software people to describe some noble and some not so noble activities. The noble part is modification.As the specifications of computer systems change, reflecting changes in the external world, so must the systems themselves. The less noble part is late debugging.Removing errors that should never have been there in the first place.

                                      More than two-fifths of the cost is devoted to user-requested extensions and modifications. This is what was called above the noble part of maintenance, which is also the inevitable part. The unanswered question is how much of the overall effort the industry could spare if it built its software from the start with more concern for extendibility. We may legitimately expect object technology to help.

                                            This is inevitable since the data must eventually be accessed for internal handling. But with traditional design techniques this knowledge is spread out over too many parts of the system, causing unjustifiably large program changes if some of the physical structure changes as it inevitably will.In other words, if postal codes go from five to nine digits,or dates require one more digit, it is reasonable to expect that a program manipulating the codes or the dates will need to be adapted. 

Portability

            Portability is the ease of transferring software products to various hardware and software environments.Portability addresses variations not just of the physical hardware but more generally of the hardware-software machine, the one that we really program, which includes the operating system, the window system if applicable, and other fundamental tools. In the rest of this book the word “platform” will be used to denote a type of hardware-software machine; an example of platform is “Intel X86 with Windows NT” .

              Many of the existing platform incompatibilities are unjustified, and to a naïve observer the only explanation sometimes seems to be a conspiracy to victimize humanity in general and programmers in particular. Whatever its causes, however, this diversity makes portability a major concern for both developers and users of software. No one likes to wait for the responses of an interactive system, or to have to purchase more memory to run a program.

           Efficiency must be balanced with other goals such as extendibility and reusability; extreme optimizations may make the software so specialized as to be unfit for change and reuse. Furthermore, the ever growing power of computer hardware does allow us to have a more relaxed attitude about gaining the last byte or microsecond.if the final system is so slow or bulky as to impede usage, those who used to declare that “speed is not that important” will not be the last to complain.

               The bottom curve is all too common: in the hectic race to add more features, the development loses track of the overall quality. The final phase, intended to get things right at last, can be long and stressful. If, under users’ or competitors’ pressure, you are forced to release the product early at stages marked by black squares in the figure the outcome may be damaging to your reputation.

Information Hiding

                     When writing a class, you will sometimes have to include a feature which the class needs for internal purposes only: a feature that is part of the implementation of the class, but not of its interface. Others features of the class possibly available to clients may call the feature for their own needs; but it should not be possible for a client to call it directly.In object oriented computation, there is only one basic computational mechanism: given a certain object, which is always an instance of some class,call a feature of that class on that object.

                         The mechanism which makes certain features unfit for clients’ calls is called information hiding.It is essential to the smooth evolution of software systems.In practice, it is not enough for the information hiding mechanism to support exported features and secret features.Class designers must also have the ability to export a feature selectively to a set of designated clients.They describe the effect of features on objects, independently of how the features have been implemented. 

                               It should be possible for the author of a class to specify that a feature is available to all clients, to no client, or to specified clients.An immediate consequence of this rule is that communication between classes should be strictly limited. In particular, a good object oriented language should not offer any notion of global variable; classes will exchange information exclusively through feature calls, and through the inheritance mechanism.

                               The language should make it possible to equip a class and its features with assertions, relying on tools to produce documentation out of these assertions and, optionally, monitor them at run time.Assertions have three major applications: they help produce reliable software; they provide systematic documentation; and they are a central tool for testing and debugging object-oriented software.