The topics introduced in this section address some of the issues of software quality, and how Python can help on this matter.
Before entering into details, let us just summarize some important concepts (you can find a good and more exhaustive description in [Meyer97]). There is no absolute quality in software: depending on the context, scale, scope and goals of the program being developped, you might very well either write on-the-fly short pieces of code to solve a temporary problem, or spend a significant effort to have your application follow an industrial design process. So, rather than only a global so-called standard that should be applied for each program you write, there are a few quality factors to be evaluated according to the actual needs of the project. Among these factors, one usually distinguish between internal and external factors. External quality factors are the ones that corresponds to visible requirements, directly important for the user of the software, such as validity, robustness or efficiency. Internal quality factors are properties of the code itself, such as legibility or modularity. In fact, internal factors often indirectly help to get external quality. Some factors, such as reusability, extensibility and compatibility, that we will study more thoroughly here, belong to external quality factors in the sense that they can be required by the users of a software library or the programmers of a shared source code; they are also important internal quality factors in the sense that they make the internal quality of the source code better. The aim of this chapter is mainly to describe these factors, as well as internal quality factors.
Theoretically, in order to get a program that performs a given task and solves the problem you have specified, a basic set of instructions such as: branching, repetitions, expressions and data structures can be sufficient. Now, the programs that you produce can become a problem by themselves, for several reasons:
So, depending on the context of the project, there are some issues which are just related to the management of source code by humans, as opposed to the specification of the task to perform. And if you think about it, you probably tend to use variable names that are relevant to your data and problem, aren't you? So, why? This is probably not for the computer, but, of course, rather for the human reader. So, in order to handle source structure and management issues, several conceptual and technical solutions have been designed in modern programming languages. This is the topic of this chapter.
Let us say that we have to develop source code for a big application and that we want this source code to be spread and shared among several team members, to be easy to maintain and evolve (extensible), and to be useful outside of the project for other people (reusable). What are the properties a source code should have for these purpose?
The most important concept to obtain these properties is called modularity, or how to build modular software components. The general idea related to software components is that an application program can be built by combining small logical building blocks. In this approach, as shown in figure Figure 19.1, building blocks form a kind of high-level language.
The simplest form of modularity is actually something that you already know: writing a function to encapsulate a block of statements within a logical unit, with some form of generalization, or abstraction, through the definition of some parameters. But there are more general and elaborated forms of components, namely: modules and packages.
So, what is modularity? As developped in [Meyer97], modularity is again not a general single property, but is rather described by a few principles:
import dna from Bio.Seq import Seqdna, Bio, Bio.Seq and Seq are syntactic units, not only files, directories or block of statements. In fact, Python really helps in defining components: almost everything that you define in a module is a syntactic unit.
You can view this approach as though not only the user of the application would be taken into account, but also the programmer, as the user of an intermediate level product. This is why there is a need for interfaces design also at the component level.
These properties may be easier to obtain by choosing an appropriate design methodogy. A design methodoly should indeed:
Programming is by definition a very repetitive task, and programmers have dreamed a lot of being able to pick off-the-shelves general purpose components, relieving them from this burden of programming the same code again and again. However, this objective has, by far, not really been reached so far. There are several both non technical and technical reasons for this. Non-technical reasons encompass organisational and psychological obstacles: although this has probably been reduced by the wide access to the Web, being aware of existing software, taking the time to learn it, and accepting to use something you don't have built yourself are common difficulties in reusing components. On the technical side, there are some conditions for modules to be reusable.