Purpose of modules

Standard Pascal does not provide mechanisms for separately compiling parts of a program and then assembling them before execution. The desire of developers of commercial Pascal compilers to include in the language tools that increase its modularity is quite understandable.

Module it is a self-compiling unit of program that includes various components of the declaration section (types, constants, variables, procedures, and functions) and possibly some executable statements of the initial part.

The basic principle modular programming is the principle of “divide and conquer”. Modular programming is the organization of a program as a collection of small independent units, called modules, the structure and behavior of which are subject to certain rules.

Using modular programming makes it easier to test a program and detect errors. Hardware-dependent subtasks can be strictly separated from other subtasks, which improves the portability of created programs.

The term “module” in programming began to be used in connection with the introduction of modular principles when creating programs. In the 70s, a module was understood as any procedure or function written in accordance with certain rules. For example: " The module must be simple, closed (independent), visible (from 50 to 100 lines), implementing only one task function, having one input and one output point».

Parnas was the first to more or less clearly formulate the main properties of the software module: “ One module should be enough to writeminimum knowledge about another's text" Thus, in accordance with the definition, a module could be any separate procedure (function) of both the lowest level of the hierarchy (implementation level) and the highest level, at which only calls to other module procedures occur.

Thus, Parnas was the first to put forward the concept of information hiding in programming. However, the only syntactic constructs that existed in the languages ​​of the 70s, such as procedure and function, could not provide reliable information hiding, since they were influenced by global variables, the behavior of which in complex programs can be difficult to predict.

This problem could only be solved by developing a new syntactic construction that is not influenced by global variables.

This design was created and called a module. Initially, it was assumed that when implementing complex software systems, a module should be used along with procedures and functions as a structure that unites and reliably hides the details of the implementation of a certain subtask.

Thus, the number of modules in the complex should be determined by decomposing the task at hand into independent subtasks. In the extreme case, a module can even be used to enclose just one procedure, if it is necessary that the local action it performs is guaranteed to be independent of the influence of other parts of the program due to any changes.

The specialized syntactic construction of a module was first proposed by N. Wirth in 1975 and included in his new language Modula. How much the properties of the language change with the introduction of the module mechanism is evidenced by the following remark N. Wirth made about the later Modula-2 language: “Modules are the most important feature that distinguishes the Modula-2 language from its predecessor Pascal.”

In terms of their organization and the nature of their use in the program, Turbo Pascal modules are close to package modules (PACKAGE) of the Ada programming language. In them, just like in Ada packages, some “visible” interface part is explicitly allocated, in which descriptions of global types, constants, variables are concentrated, and also the headings of procedures and functions are provided. The appearance of objects in the interface part makes them available to other modules and the main program. The bodies of procedures and functions are located in the executable part of the module, which can be hidden from the user.

Fig.2. Sequence of software project development

The importance of modules for software project development technology can be demonstrated by the diagram in Fig. 2.

Modules are an excellent tool for developing application libraries and a powerful tool for modular programming. An important feature of modules is that the compiler places their program code in a separate memory segment. The segment length cannot exceed 64 KB, but the number of simultaneously used modules is limited only by the available memory, which allows you to create large programs.

Module structure

Every module has the following structure:

Unit <имя_модуля>;

iinterface

<интерфейсная часть>;

implementation

<исполняемая часть>;

<инициирующая часть>;

Here UNIT - reserved word(unit); begins the module header;

<имя_модуля>- module name (correct identifier);

INTERFACE – reserved word (interface); starts the interface part of the module;

IMPLEMENTATION – reserved word (implementation); starts the executable part of the module;

BEGIN – reserved word; starts the initiating part of the module; and the begin construction<инициирующая часть>optional;

END – reserved word – sign of the end of the module.

Thus, a module consists of a header and three components, any of which can be empty.

Below is the general structure of the module, supplemented by comments explaining the meaning and purpose of each section of the module.

Unit ModuleId;

{Interface section}

interface

(This section describes the interaction of this module) (with other user and standard modules, as well as) (with the main program. In other words, interaction) (of the module with the “outside world.”)

{Interface section import list}

(In this list, identifiers are listed separated by commas) (of modules whose interface parts information should be)

(to be available in this module. It is advisable to describe here) (identifiers of only those modules whose information is from) (used in descriptions of the interface section of this module.)

{Interface section export list}

const (The export list consists of subsections of the description of constants,) type (types, variables, procedure headers and functions that) var (defined in this module, but which are allowed to be used) procedure (allowed in all other modules and programs that include the name) function (of this module in its uses line. For procedures and functions) (only headers are described here, but with a mandatory one) (a full description of the formal parameters.)

{Implementation section}

implementation

(This section indicates the implementation (personal) part) (of the descriptions of this module, which is not available for other) (modules and programs. In other words - “inner kitchen”)

{Implementation Section Import List}

(In this list, separated by commas, the identifiers) (of those modules, the information of the interface parts of which should) (be available in this module. It is advisable to describe here) (identifiers of all necessary modules, information from) (which are not used in the descriptions of the interface section of this) ( module and the use of which no one should know) (another module.)

{Subsections of internal descriptions for the module}

label (These subsections describe labels, constants, types,) const (variables, procedures and functions that describe) type (the algorithmic actions performed by this module, and) var (which are the “personal property” of this module only) procedure (only this module . These descriptions are not available to any) function (another module. Headings of procedures and functions in this) (subsection can be specified without a list of formal) (parameters. If the headers are specified with parameters, then) (their list must be identical to the same list for ) (corresponding procedure (function) in the interface section)

{Initialization section}

(This section specifies the initial settings operators) (necessary to start the correct operation of the module. Operators) (initialization sections of modules used in the program) (executed at the initial start of the program in the same) (the order in which the module identifiers are described in) (in the uses clause. If initialization statements are not required, ) (then the word begin can be omitted.)

end.

Module header and how modules relate to each other

The module header consists of the reserved word unit followed by the module name. For the correct operation of the Turbo Pascal environment and the ability to connect tools that facilitate the development of large programs, The module name must match the disk file name, which contains the source text of the module. If, for example, we have a module header

Unit primer;

then the source text of this module should be located on disk in the file primer.pas.

The name of the module serves to connect it with other modules and the main program. This connection is established with a special offer:

uses <список модулей>

Here USES– reserved word (uses);

<список модулей>- list of modules with which communication is established; list elements – module names separated by commas.

If modules are used in the program, then offeruses <список модулей> should appear immediately after the program title, i.e. should open the description section of the main program. Modules can use other modules. In modules the uses clause<список модулей>may appear immediately after the word interface or immediately after the word implementation. Two uses clauses are also allowed, i.e. it can stand here and there.

Interface part

The interface part opens with a reserved word INTERFACE. This part contains declarations of all global module objects (types, constants, variables and subroutines) that must be accessible to the main program and (or) other modules. When declaring global subroutines in the interface part, only their title is indicated, for example:

Procedure AddC(x,y: complex, var z: complex);

Procedure MulC(x,y: complex, var z: complex);

When starting to develop each program, you should keep in mind that it is, as a rule, a large system, so measures must be taken to simplify it. To do this, such a program is developed in parts, which are called software modules. This method of program development itself is called modular programming. A software module is any fragment of a process description, designed as an independent software product suitable for use in process descriptions. This means that each program module is programmed, compiled and debugged separately from other program modules, and thereby physically separated from other program modules. Moreover, each developed software module can be included in different programs, if the conditions for its use declared in the documentation for this module are met. Thus, a software module can be considered both as a means of combating program complexity and as a means of combating duplication in programming (i.e., as a means of accumulating and reusing programmer knowledge).

Modular programming is the embodiment in the process of program development of both general methods of dealing with complexity: ensuring the independence of system components and using hierarchical structures. To implement the first method, certain requirements are formulated that the software module must satisfy, i.e. The main characteristics of a “good” software module are identified. To implement the second method, tree-like modular program structures are used (including trees with fused branches).

  1. Main characteristics of the software module

Not every software module helps simplify a program. Selecting a good module from this point of view is a serious creative task. Several criteria are used to evaluate the acceptability of the allocated module. Thus, Holt proposed the following two general such criteria:

    a good module is simpler on the outside than on the inside;

    a good module is easier to use than to build.

Myers suggests using more constructive characteristics to assess the acceptability of a software module:

    module size;

    module strength;

    coupling with other modules;

    routineness of the module (independence of the history of calls to it).

Size A module is measured by the number of statements or lines it contains. The module should not be too small or too large. Small modules result in a cumbersome modular program structure and may not be worth the overhead associated with their design. Large modules are inconvenient to study and change; they can significantly increase the total time of retranslations of the program when debugging the program. Typically, software modules ranging in size from several tens to several hundred statements are recommended.

Module strength - this is the measure of it internal connections. The higher the module strength, the more connections it can hide from parts of the program external to it and, therefore, the greater the contribution it can make to simplifying the program. To assess the strength of a module, Myers proposes a set of seven classes of modules, ordered by strength. The module has the weakest degree of strength, durable by coincidence. This is a module whose elements have no meaningful connections. Such a module can be isolated, for example, if repetition of the same sequence of statements is detected in different places in the program, which is compiled into a separate module. The need to change this sequence in one of the contexts may lead to changes in this module, which may make its use in other contexts erroneous. This class of software modules is not recommended for use. Generally speaking, the ordering of classes of modules proposed by Myers according to the degree of strength is not indisputable. However, this is not very significant, since only the two highest strength classes of modules are recommended for use. I will look at these classes in more detail.

Functionally durable A module is a module that performs (implements) one specific function. When implementing this function, such a module can use other modules. This class of software modules is recommended for use.

Informationally durable A module is a module that performs (implements) several operations (functions) on the same data structure (information object), which is considered unknown outside this module. For each of these operations, such a module has its own input with its own form of access to it. Such a class should be considered as a class of software modules with highest degree strength. An information-strong module may implement, for example, an abstract data type.

Modular programming languages ​​at least have facilities for specifying functionally robust modules (for example, the FUNCTION module in FORTRAN). There were no means for specifying informationally robust modules in early programming languages. These means appeared only in later languages. Thus, in the Ada programming language, the means of specifying an informationally durable module is a package.

Clutch module is a measure of its data dependence on other modules. Characterized by the method of data transmission. The weaker the coupling of a module with other modules, the stronger its independence from other modules. To assess the degree of coupling, Myers proposes an ordered set of six types of coupling modules. The worst type of module coupling is content cohesion. This is the concatenation of two modules when one of them has direct references to the contents of the other module (for example, to a constant contained in the other module). Such coupling of modules is unacceptable. It is also not recommended to use general area grip- this is a chain of modules when several modules use the same memory area. This type of coupling of modules is implemented, for example, when programming in FORTRAN using COMMON blocks. The only type of module coupling that is recommended for use by modern programming technology is parametric clutch(Myers data chaining) is the case when data is passed to a module either when it is accessed as the value of its parameters, or as a result of its access to another module to evaluate some function. This type of module coupling is implemented in programming languages ​​using calls to procedures (functions).

Module routine - this is its independence from the background of appeals to it. The module is called routine, if the result (effect) of accessing it depends only on the values ​​of its parameters (and does not depend on the history of accessing it). The module is called dependent on background, if the result (effect) of accessing it depends on the internal state of this module, changed as a result of previous accesses to it. Myers does not recommend using history-dependent (unpredictable) modules, since they provoke the appearance of tricky (elusive) errors in programs. However, such a recommendation is not constructive, since in many cases it is the history-dependent module that is the best implementation of an information-secure module. Therefore, the following (more cautious) recommendation is more acceptable:

    a routine module should always be used unless this results in poor (not recommended) module couplings;

    history-dependent modules should only be used when necessary to provide parametric coupling;

    in the specification of a history-dependent module, this dependence must be clearly formulated in such a way that it is possible to predict the behavior (execution effect) of this module during different subsequent calls to it.

In connection with the last recommendation, it may be useful to define an external representation (oriented to inform a person) of the states of a history-dependent module. In this case, the effect of performing each function (operation) implemented by this module should be described in terms of this external representation, which will significantly simplify predicting the behavior of this module.

The essence modular programming consists of dividing a complex problem into a number of simpler subtasks and creating programs to solve them quite independently of each other. Modularity is one of the basic principles of building software projects. In general, a module is a separate functionally complete program unit, in some way identified and combined with others, a means of defining a logically related set of objects, a means of their selection and isolation. The module is a means of decomposing not only control structures, but also data structures. This was greatly facilitated by the development of the concept of “data type”.

A module is a unit of compilation, storage, as well as a unit of design and separate development of a software project by a team of developers. Thus, a module is understood as a means of defining a logically connected set of objects, a means of highlighting and isolating them.

Creating modules and using their objects in programs is one of the techniques lean programming which is due to the following circumstances.

Firstly, a module usually defines objects that are carriers of the basic concepts of some “subject” domain, so that the module defines the context of this subject area. Therefore, programs that will perform various processing algorithms in this area will be able to use ready-made and, importantly, identical definitions of basic objects.

Secondly, both modules and programs that use them are compiled regardless(the module must be compiled before the program using it). Thanks to this the compilation time big program using ready-made modules is significantly reduced, which is important when debugging programs when you have to compile them many times.

The third important property of the module is that it hides, “encapsulates” the representation and implementation of the objects it exports, so that their possible changes in the module (when configuring it or adapting to new hardware capabilities) do not require any modifications to user programs.

All modules use mnemonic names for the objects they define (constants, variables, types and subroutines), which makes it easier to understand their purpose and remember, satisfies the requirement text clarity programs.

Programming languages ​​that support a modular approach describe a module as a software unit consisting of two main parts - a specification (interface) and an implementation. The specification provides such characteristics of module objects that are necessary and sufficient for the use of these objects in other modules and programs. This allows you to use module objects based only on information about their interface (without waiting for their full description). The implementation part of the module describes the representation and processing algorithms associated with certain module objects.

The module is one of the tools that facilitates program verification. The module, as a means of creating an abstraction, highlights the specification and localizes implementation information.

Modules also serve the purpose of creating a problem-oriented context and localizing machine dependencies.

Modular programming concept

The concept of modular programming can be formulated in the form of several concepts and provisions:

  • Functional decomposition of a task is the division of a large task into a number of smaller, functionally independent subtasks - modules. The modules are interconnected only by input and output data.
  • A module is the basis of the concept of modular programming. Each module in a functional decomposition is a “black box” with one input and one output. The modular approach makes it possible to painlessly modernize the program during its operation and facilitates its maintenance. Additionally, the modular approach allows you to develop parts of programs of one project on different languages programming, and then, using packaging tools, combine them into a single boot module.
  • The solutions implemented should be simple and clear. If the purpose of the module is not clear, then this indicates that the decomposition of the initial or intermediate task was not carried out with sufficient quality. In this case, it is necessary to analyze the task again and, possibly, carry out an additional division into subtasks. If there are complex places in the project, they need to be documented in more detail using a well-thought-out comment system. This process must be continued until it is truly possible to achieve a clear understanding of the purpose of all modules of the task and their optimal combination.
  • The purpose of all module variables should be described using comments as they are defined.

Literature

  1. MM. Bezhanova, L.A. Moskvina. Practical programming. Techniques for creating programs in Pascal. M.: Scientific World, 2000, 270 p.
  2. Istomin E.P., Novikov V.V., Novikova M.V. High-level methods of computer science and programming: Textbook. - St. Petersburg. LLC "Adreevsky Publishing House", 2006 - 228 p.

Structured programming

The most commonly known definition of structured programming is a programming approach that uses three constructs to transfer control in a program: follow, select, and loop.

Boehm and Giacopini's classic theorem on structured programming states that every regular program (that is, a program with one input and one output, without loops or unreachable branches) can be written using the following logical structures:

sequences of two or more statements;

dichotomous choice;

repetition;

Dijkstra proposed abandoning the unconditional jump operator and limiting himself to three constructions - sequence, choice and loop;

Donald Knuth demonstrated cases in which the unconditional jump operator was useful (such as breaking out of multiple nested loops) and criticized Dijkstra's assertion.

In 1965, academician Glushkov drew attention to the fact that structured programs can be considered as formulas in some algebra. Knowing the rules for transforming expressions in such an algebra, it is possible to carry out deep formal (and, therefore, automated) transformations of programs.

Structured programming– not an end in itself, its main purpose is to obtain a good program. However, even the best program requires jump statements, for example when exiting many nested loops.

Modular programming

Modular programming is a method of programming in which the entire program is divided into a group of components called modules, each of which has its own controlled size, clear purpose and detailed interface with the external environment. The only alternative to modularity is a monolithic program, which, of course, is inconvenient. Thus, the most interesting question when studying modularity is determining the criterion for dividing into modules. Modular programming is based on three main concepts.

The principle of withholding information. Each component hides a single design decision, i.e., the module serves to hide information. The approach to program development is to first generate a list of design decisions that are particularly difficult to make or that are most likely to change. Then individual modules are defined, each of which implements one of the specified solutions.

Axiom of modularity. A module is an independent program unit that serves to perform some specific program function and to communicate with the rest of the program. The software unit must satisfy the following conditions:


– block-based organization, i.e. the ability to call a program unit from blocks of any degree of nesting;

– syntactic isolation, i.e. highlighting a module in the text syntactic elements;

– semantic independence, i.e. independence from the place where the program unit is called;

– generality of data, i.e. the presence of own data that is saved with each access;

– completeness of definition, i.e. independence of the program unit.

Assembly programming. Modules are software building blocks from which a program is built.

Coupling modules– a measure of the relative independence of a module from other modules. Independent modules can be modified without modifying other modules. The weaker the module's clutch, the better. Let's look at the different types of clutch.

– independent modules are an ideal case. The modules know nothing about each other. You can organize the interaction of such modules by knowing their interface and appropriately redirecting the output data of one module to the input of another.

– data chaining (parametric) is chaining when data is passed to a module as the values ​​of its parameters, or as a result of its call to another module to calculate a certain function. This type of chaining is implemented in programming languages ​​when accessing functions (procedures).

The routineness of a module is the independence of the module from previous calls to it (from the background). A module is routine if the result of its operation depends only on the number of parameters passed (and not on the number of calls). A module should be routine in most cases, but there are also cases where a module should save history. When choosing the degree of routine of a module, three recommendations are used:

– in most cases we make the module routine;

– history-dependent modules should be used only in cases where it is necessary for data concatenation;

– the specification of a history-dependent module must clearly state this dependence so that users can predict the behavior of such a module.

When designing a rather complex software after determining its general structure, the components are decomposed in accordance with the chosen approach until elements are obtained that, in the designer’s opinion, do not need further decomposition.

As mentioned earlier, currently two methods of decomposition of developed software are used, associated with the corresponding approach:

Procedural (or structural - according to the name of the approach);

Object.

The result of procedural decomposition is subroutine hierarchy(procedures), in which functions related to decision making are implemented by subroutines upper levels, and direct processing - by subroutines of lower levels. This is consistent with the principle of vertical management, which was formulated along with other recommendations structural approach to programming. It also limits possible options transfer of control, requiring that any subroutine return control to the subroutine that called it.

The result of object decomposition is a set of objects, which are then implemented as variables of some specially developed types (classes), which are a set of data fields and methods that work with these fields.

Thus, with any decomposition method, a set of subroutines associated with the corresponding data is obtained, which are organized into modules during the implementation process.

ModulesModule called standalone compiled software unit. The term "module" is traditionally used in two senses. Initially, when the size of programs was relatively small and all subroutines were compiled separately, a module was understood as a subroutine, i.e. a sequence of related program fragments that are accessed by name. Over time, when the size of programs grew significantly, and it became possible to create libraries of resources: constants, variables, type declarations, classes and subroutines, the term “module” began to be used in the sense a stand-alone compiled set of software resources.

The module can receive and/or return data through shared memory areas or parameters.

Initially, the following requirements were imposed on modules (still understood as subroutines):

Separate compilation;

One entry point;

One exit point;

Compliance with the principle of vertical management;

Ability to call other modules;

Small size(up to 50-60 language operators);

Independence from call history;

Perform one function.

The requirements for one entry point, one exit point, independence from call history and compliance with the principle of vertical control were caused by the fact that at that time, due to serious limitations on the amount of RAM, programmers were forced to develop programs with the greatest possible repeatability of codes. As a result, routines with multiple entry and exit points were not only common, but also considered a high class of programming. The consequence was that programs were very difficult not only to modify, but also to understand, and sometimes simply to completely debug.



Over time, when the basic requirements of the structural approach began to be supported by programming languages, and the module began to be understood

a separately compiled resource library, the requirement for module independence became basic.

Practice has shown that the higher the degree of independence of modules, the:

It is easier to understand a separate module and the entire program and, accordingly, test, debug and modify it;

There is less likelihood of new errors appearing when correcting old ones or making changes to the program, i.e., the likelihood of a “ripple” effect;

It is easier to organize software development by a group of programmers and easier to maintain.

Thus, reducing the dependency of modules improves the manufacturability of the project. The degree of independence of modules (both subroutines and libraries) is assessed by two criteria: coupling and coherence.

Coupling of modules.Clutch is a measure of module interdependence that determines how well the modules are separated from each other. Modules are independent if each of them does not contain any information about the other. The more information a module stores about other modules, the more interlocked it is with them.

There are five types of module coupling:

According to;

According to the sample;

On management;

By general data area;

By content.

Coupling by data assumes that modules exchange data represented by scalar values. For small quantities transmitted parameters, this type provides the best technological characteristics of the software.

For example, the Max function assumes data concatenation through parameters of a scalar type:

Function Max(a, b: integer) : integer;

If a>b then Max:=a else Max: =b;

Pattern clutch assumes that modules exchange data combined into structures. This type also provides good characteristics, but they are worse than the previous type, since the specific transmitted data is “hidden” in structures, and therefore the “transparency” of communication between modules is reduced. In addition, if the structure of the transmitted data changes, it is necessary to modify all modules that use it.

Thus, the MaxEl function described below assumes pattern concatenation (parameter a is an open array).

Function MaxEl(a:array of integer):integer;

Var i:word;

MaxEl:=a;

for i:=l to High(a) do

if a[i]>MaxEl then MaxEl: =a[i];

At clutch control one module sends to another some information object (flag) designed to control the internal logic of the module. In this way, software operating modes are often configured. Such settings also reduce the clarity of interaction between modules and therefore provide even worse manufacturability characteristics of the developed software compared to previous types of connections.

For example, the MinMax function assumes control chaining, since the value of the flag parameter affects the logic of the program: if the MinMax function receives a flag parameter value equal to true, then it returns the maximum value of the two, and if false, then the minimum:

Function MinMax(a, b: integer; flag: boolean): integer;

if(a>b) and (flag) then MinMax: =a

else MinMax: =b;

Concatenation over a common data area assumes that modules work with a common data area. This type of clutch is considered unacceptable because:

Programs that use this type of coupling are very difficult to understand when maintaining the software;

An error in one module, leading to a change in general data, may appear during the execution of another module, which significantly complicates error localization;

For example, the function MaxA, using the global array A, is linked to the main program over a common area:

Function MaxA:integer; Var i:word;

MaxA: =a; for i:= Low(a)+l to High(a) do if a[i]>MaxA then MaxA: =a[i];

Keep in mind that "memory routines" whose actions depend on call history use shared-area concatenation, which makes their operation generally unpredictable. It is this option that C and C++ static variables use.

When content based clutches one module contains calls to the internal components of another (passes control inside, reads and/or changes internal data or the codes themselves), which completely contradicts the block-hierarchical approach. A separate module in this case is no longer a block (“black box”): its contents must be taken into account during the development of another module. Modern general-purpose procedural programming languages, such as Pascal, of this type concatenations are not explicitly supported, but for languages low level, such as Assembler, this kind of coupling remains possible.

In table 2.1 shows the characteristics various types clutches according to expert estimates. The first three types of clutch are considered acceptable, since the use of the others leads to a sharp deterioration in the manufacturability of the programs.

As a rule, modules are linked together in several ways. Taking this into account, the quality of software is usually determined by the type of clutch with the worst characteristics. So, if data coupling and control coupling are used, then control coupling is considered decisive.

In some cases, module coupling can be reduced by removing unnecessary connections and structuring the necessary connections. An example is object-oriented programming, in which, instead of a large number of parameters, a method implicitly receives the address of the area (structure) in which the object's fields are located, and explicitly receives additional parameters. As a result, the modules are linked in a pattern.

Connectivity of modules.Connectivity - a measure of the strength of the connection between functional and information objects inside one module. If cohesion characterizes the quality of separation of modules, then connectivity characterizes the degree of interconnection of elements implemented by one module. Placing strongly related elements into one; module reduces intermodular connections and, accordingly, mutual influence of modules. At the same time, placing strongly coupled elements in different modules not only strengthens intermodular connections, but also complicates the understanding of their interaction. Combining loosely coupled elements also reduces the manufacturability of modules, since such elements are more difficult to mentally manipulate.

There are the following types of connectivity (in descending order of level):

Functional;

Consistent;

Informational (communicative);

Procedural;

Temporary;

Logical;

Random.

At functional connectivity all module objects are designed to perform one function (Fig. 2.1, a): operations combined to perform one function, or data associated with one function. A module whose elements are functionally related has a clearly defined purpose; when it is called, one task is performed, for example, a subroutine for finding the minimum element of an array. Such a module has maximum connectivity, which results in its good technological qualities: ease of testing, modification and maintenance. It is with this that one of the requirements of the structural decomposition “one module - one function” is connected.

For the same reasons, unstructured distribution of functions between modules - resource libraries - should be avoided. For example, if when designing text editor If an editing function is assumed, it is better to organize a module - a library of editing functions - than to place some functions in one module and some in another.

At sequential connectivity functions, the output of one function serves as the input data for another function (Fig. 2.1, b). As a rule, such a module has one entry point, that is, it implements one subroutine that performs two functions. Data used by sequential functions is also considered to be connected sequentially. A module with sequential connectivity of functions can be divided into two or more modules, both with sequential and functional connectivity. Such a module performs several functions, and, therefore, its manufacturability is worse: it is more difficult to organize testing, and when performing a modification, you have to mentally separate module functions,

Information related consider functions that process the same data (Fig. 2.1, V). When using structured programming languages, separate execution of functions can only be achieved if each function is implemented by its own subroutine. Although previously in such cases they usually used different entry points into a module designed as one subroutine.

Despite the combination of several functions, the information-related module has good manufacturability indicators. This is explained by the fact that all functions that work with certain data are collected in one place, which allows only one module to be adjusted when the data format changes. Data that is processed by one function is also considered informationally related.

Procedurally bound functions or data that are parts of one process (Fig. 2.1, d). Typically, modules with procedural coherence of functions are obtained if the module combines the functions of alternative parts of the program. With procedural coherence individual elements modules are extremely weakly connected, since the actions they implement are connected only by a common process, therefore, the manufacturability of this type of communication is lower than the previous one.

Temporal connectivity functions implies that these functions are performed in parallel or over a period of time (Fig. 2.1, d). Temporal coherence of data means that it is used in a certain time interval. For example, functions that are executed when a process is initialized have temporary connectivity. The distinctive feature of temporal cohesion is that the actions implemented by such functions can usually be performed in any order. The content of a module with temporal coherence of functions tends to change: new actions may be included and/or old ones may be excluded. The high probability of modifying a function further reduces the manufacturability of modules of this type compared to the previous one.

Logical connection is based on combining data or functions into one logical group (Fig. 2.1, e). An example is the processing functions text information or data of the same type. A module with logical function coherence often implements alternative versions of the same operation, such as integer addition and addition real numbers. From such a module one part of it will always be called, and the calling and called modules will be connected in control. Understanding the logic of the operation of modules containing logically connected components is usually more difficult than modules using temporary connectivity, therefore their manufacturability indicators are even lower.

In the event that the connection between the elements is small or absent, they are considered to have random connectivity. A module whose elements are connected randomly has the lowest indicators of manufacturability, since the elements combined in it are not connected at all.

Please note that in the three penultimate cases, the connection between several subroutines in a module is due to external reasons. And in the latter it is completely absent. This is accordingly projected onto the technological characteristics of the modules. In table 2.2 presents the characteristics various types connectivity according to expert estimates.

Analysis of the table 2.2 shows that in practice it is advisable to use functional, sequential and informational connectivity.

As a rule, with a well-thought-out decomposition, the modules of the upper levels of the hierarchy have a functional or sequential coherence of functions and data. Data service modules are characterized by information connectivity of functions. Data from such modules can be linked in different ways. Thus, modules containing a description of classes in an object-oriented approach are characterized by the informational coherence of methods and the functional coherence of data. Obtaining modules with other types of connectivity during the decomposition process most likely means insufficiently thought-out design. The only exceptions are resource libraries.

Resource Libraries. There are two types of resource libraries: subroutine libraries and class libraries.

Subroutine libraries implement functions that are similar in purpose, for example, a library for graphical information output. The connection between subroutines in such a library is logical, and the connection between the subroutines themselves is functional, since each of them usually implements one function.

Class libraries implement classes that are similar in purpose. The connectivity of class elements is informational; the connectivity of classes among themselves can be functional - for related or associated classes and logical - for others.

As a means of improving the technological characteristics of resource libraries, the division of the module body into an interface part and an implementation area is currently widely used (sections Interface and Implementation - in Pascal, h and cpp files in C++ and Java).

Interface part in this case, it contains a set of resource declarations (subroutine headings, variable names, types, classes, etc.) that this library provides to other modules. Resources that are not declared in the interface part are not accessible from the outside.

Region implementation contains the bodies of routines and possibly internal resources (routines, variables, types) used by those routines. With this organization, any changes to the library implementation that do not affect its interface do not require revision of the modules associated with the library, which improves the technological characteristics of library modules. In addition, such libraries are usually well-debugged and thought out, since they are often used by different programs.