Sei sulla pagina 1di 24

Advance Software Engineering

Introduction: Life cycle models, Requirement Analysis and specification, Formal requirements specification. Fundamental issues in software design: Goodness of design, cohesions, coupling. Function-oriented design: structured analysis and design. Overview of object oriented concepts. Unified Modeling Language (UML). Unified design process. User interface design. Coding standards and guidelines. Code walkthrough and reviews. Unit testing. Black box and white box testing. Integration and system testing. Software quality and reliability. SEI CMM and ISO 9001. PSP and Six Sigma. Clean room technique. Software maintenance issues and techniques. Software reuse. ClientServer software development.

Life cycle model: Definition:

A software life cycle model (also called process model) is a descriptive and diagrammatic representation of the software life cycle.
A life cycle model represents all the activities required to make a software product transit through its life cycle phases. It also captures the order in which these activities are to be undertaken. In other words, a life cycle model maps the different activities performed on a software product from its inception to retirement. During any life cycle phase, more than one activity may also be carried out.

Need for a software life cycle Model:


The development team must identify a suitable life cycle model for the particular project and then adhere to it. Without using of a particular life cycle model the development of a software product would not be in a systematic and disciplined manner. A software life cycle model defines entry and exit criteria for every phase. A phase can start only if its phase-entry criteria have been satisfied. So without software life cycle model the entry and exit criteria for a phase cannot be recognized. Without software life cycle models it becomes difficult for software project managers to monitor the progress of the project. Without using of a particular life cycle model the development of a software product would not be in a systematic and disciplined manner. When a software product is being developed by a team there must be a clear understanding among team members about when and what to do. Otherwise it would lead to chaos and project failure.

Different software life cycle models


Many life cycle models have been proposed so far. Each of them has some advantages as well as some disadvantages. A few important and commonly used life cycle models are as follows:

Classical Waterfall Model


Iterative Waterfall Model Prototyping Model Spiral Model


Evolutionary Model

Classical waterfall Model:


The classical waterfall model is intuitively the most obvious way to develop software. This model can be considered to be a theoretical way of developing software. But all other life cycle models are essentially derived from the classical waterfall model. Classical waterfall model divides the life cycle into the following phases as shown in fig.2.1:

Feasibility Study

Requirements Analysis and Specification Design Coding and Unit Testing Maintenance

Integration and System Testing

Fig 2.1: Classical Waterfall Model

Feasibility Study: The main aim of feasibility study is to determine whether it would be financially and technically feasible to develop the product. i) At first project managers or team leaders try to have a rough understanding of what is required to be done by visiting the client side. They study different input data to the system and output data to be produced by the system. ii) After they have an overall understanding of the problem they investigate the different solutions that are possible. iii) Based on this analysis they pick the best solution and determine whether the solution is feasible financially and technically. They check whether the customer budget would meet the cost of the product and whether they have sufficient technical expertise in the area of development.

Analysis and Specification: The aim of the requirements analysis and specification phase is to understand the exact requirements of the customer and to document them properly. This phase consists of two distinct activities, namely

Requirements gathering and analysis, and


Requirements specification

The goal of the requirements gathering activity is to collect all relevant information from the customer regarding the product to be developed. This is done to clearly understand the customer requirements so that incompleteness and inconsistencies are removed. The requirements analysis activity is begun by collecting all relevant data regarding the product to be developed from the users of the product and from the customer through interviews and discussions. After all ambiguities, inconsistencies, and incompleteness have been resolved and all the requirements properly understood, the requirements specification activity can start. During this activity, the user requirements are systematically organized into a Software Requirements Specification (SRS) document.

Design: The goal of the design phase is to transform the requirements specified in the SRS document into a structure that is suitable for implementation in some programming language. Two distinctly different approaches are available: the traditional design approach and the

object-oriented design approach. i) Traditional design approach Traditional design consists of two different activities; first a structured analysis of the requirements specification is carried out where the detailed structure of the problem is examined. This is followed by a Structured design activity. During structured design, the results of structured analysis are transformed into the software design. ii) Object-oriented design approach In this technique, various objects that occur in the problem domain and the solution domain are first identified, and the different relationships that exist among these objects are identified. The object structure is further refined to obtain the detailed design.

Coding and Unit Testing:The purpose of the coding and unit testing phase (sometimes called the implementation phase) of software development is to translate the software design into source code. Each component of the design is implemented as a program module. The end-product of this phase is a set of program modules that have been individually tested. During this phase, each module is unit tested to determine the correct working of all the individual modules. It involves testing each module in isolation as this is the most efficient way to debug the errors identified at this stage.

Integration and System Testing: Integration of different modules is undertaken once they have been coded and unit tested. During the integration and system testing phase, the modules are integrated in a planned manner. The different modules making up a software product are almost never integrated in one shot. Integration is normally carried out incrementally over a number of steps. Finally, when all the modules have been successfully integrated and tested, system testing is carried out. The goal of system testing is to ensure that the developed system conforms to its requirements laid out in the SRS document. System testing usually consists of three different kinds of testing activities:

testing: It is the system testing performed by the development team.


testing: It is the system testing performed by a friendly set of customers.

Acceptance testing: It is the system testing performed by the customer himself after the product delivery to determine whether to accept or reject the delivered product.

Maintenance: Maintenance of a typical software product requires much more than the effort

necessary to develop the product itself. Many studies carried out in the past confirm this and indicate that the relative effort of development of a typical software product to its maintenance effort is roughly in the 40:60 ratio. Maintenance involves performing any one or more of the following three kinds of activities: i) Correcting errors that were not discovered during the product development phase. This is called corrective maintenance. ii) Improving the implementation of the system, and enhancing the functionalities of the system according to the customers requirements. This is called perfective maintenance. iii) Porting the software to work in a new environment. For exampleporting may be required to get the software to work on a new computer platform or with a new operating system. This is called adaptive maintenance.

Shortcomings of the classical waterfall model : Error of any phase is detected at the end of the entire lifecycle. It does not allow for very much Iteration. Hard dates on phases. The dates set for completing Analysis and Design are major milestones thatdevelopers are measured against

Iterative Waterfall Model:


Iterative development is the heart of a cyclic software development process developed in response to the weaknesses of the waterfall model. It starts with an initial planning and ends with deployment with the cyclic interactions in between i.e. it provide feedback paths from every phase to its preceding phases. The feedback paths allow for correction of the errors committed during a phase .The rest of the phases of development are same as classical water fall model. The model is pictorially shown in fig 2.2

Fig 2.2 Iterative Waterfall model

Shortcomings:
i) It cannot effectively handle the different types of risks that are in real life software project. ii) Once a developer completes his work, he idles waiting the phase to get over. i.e. wastage of time due to waiting for the job.

Prototyping Model:
Objectives Explain what a prototype is. Explain why and when a prototype needs to be developed during software development. Identify the situations in which one would prefer to build a prototype. State the activities carried out during each phase of a spiral model. Identify circumstances under which spiral model should be used for software development. Tailor a development process to a specific prototype.

Prototype

A prototype is a toy implementation of the system. A prototype usually exhibits limited functional capabilities, low reliability, and inefficient performance compared to the actual software. A prototype is usually built using several shortcuts. A prototype usually turns out to be a very crude version of the actual system.

Need for a prototype in software development


There are several uses of a prototype. An important purpose is to illustrate the input data formats, messages, reports, and the interactive dialogues to the customer. This is a valuable mechanism for gaining better understanding of the customers needs i.e. How the screens might look like How the user interface would behave How the system would produce outputs This is something similar to what the architectural designers of a building do; they show a prototype of the building to their customer. The customer can evaluate whether he likes it or not. A similar thing happens in the case of a software product and its prototyping model. Another reason for developing a prototype is that it is impossible to get the perfect product in the first attempt. The experience gained in developing the prototype can be used to develop the final product. A prototyping model can be used when technical solutions are unclear to the development team.

Where to use Prototype Model


A prototype of the actual product is preferred in situations such as: User requirements are not complete Technical issues are not clear

Fig 3.1 Prototyping Model The prototyping model of software is shown in fig 3.1. In this model a prototyping starts with an initial requirement and gathering phase .A quick design is carried out and a prototype is build. The developed prototype is submitted to the customer for evaluation. Based on the customer feedback we may go for development or again go for the redesign as per customer demand. The code for the prototype is usually thrown away, but the experience gained while developing the prototype helps for actual development. The rest of the phases of development are similar to the waterfall model.

Evolutionary Model:
This life cycle model is also referred to as the successive versions model and sometimes as the incremental model. In this lifecycle model the software is first broken down into several module which can be incrementally constructed and delivered. The development team first develops the core modules of the system. Each evolutionary version may be developed using an iterative waterfall model of development. The development model is shown in fig 4.1. C
B

Fig 4.1. Evolutionary model (A,B,C are modules of the software model) Each successive version of the product is fully functioning capable of performing more useful work than the previous version. In this model the user gets a chance to experiment with a particularly developed software much before the complete version of the software is ready.This model is useful only for very large products.

Spiral Model

The Spiral model of software development is shown in fig. 4.2. The diagrammatic representation of this model appears like a spiral with many loops. The exact number of loops in the spiral is not fixed. Each loop of the spiral represents a phase of the software process. For example, the innermost loop might be concerned with feasibility study. The next loop with requirements specification, the next one with design, and so on. Each phase in this model is split into four sectors (or quadrants) as shown in fig. 4.2. The following activities are carried out during each phase of a spiral model.

Fig 4.2 Spiral Model

First quadrant (Objective Setting) During the first quadrant, it is needed to identify the objectives of the phase. Examine the risks associated with these objectives. Second Quadrant (Risk Assessment and Reduction) A detailed analysis is carried out for each identified project risk. Steps are taken to reduce the risks. For example, if there is a risk that the requirements are inappropriate, a prototype system may be developed. Third Quadrant (Development and Validation)

Develop and validate the next level of the product after resolving the identified risks. Fourth Quadrant (Review and Planning) Review the results achieved so far with the customer and plan the next iteration around the spiral. Progressively more complete version of the software gets built with each iteration around the spiral. Where to use spiral model ? The spiral model is called a meta model since it encompasses all other life cycle models. Risk handling is inherently built into this model. The spiral model is suitable for development of technically challenging software products that are prone to several kinds of risks. However, this model is much more complex than the other models this is probably a factor deterring its use in ordinary projects.

Comparison of different life-cycle models


The classical waterfall model can be considered as the basic model and all other life cycle models as embellishments of this model. However, the classical waterfall model can not be used in practical development projects, since this model supports no mechanism to handle the errors committed during any of the phases. This problem is overcome in the iterative waterfall model. The iterative waterfall model is probably the most widely used software development model evolved so far. This model is simple to understand and use. However, this model is suitable only for wellunderstood problems; it is not suitable for very large projects and for projects that are subject to many risks. The prototyping model is suitable for projects for which either the user requirements or the underlying technical aspects are not well understood. This model is especially popular for development of the user-interface part of the projects. The evolutionary approach is suitable for large problems which can be decomposed into a set of modules for incremental development and delivery. This model is also widely used for object-oriented development projects. Of course, this model can only be

used if the incremental delivery of the system is acceptable to the customer. The spiral model is called a meta model since it encompasses all other life cycle models. Risk handling is inherently built into this model. The spiral model is suitable for development of technically challenging software products that are prone to several kinds of risks. However, this model is much more complex than the other models this is probably a factor deterring its use in ordinary project.

1. Identify the definite stages through which a software product undergoes during its lifetime. Ans.: - The definite stages through which a software product undergoes during its lifetime are as follows: Feasibility Study Requirements Analysis and Specification Design Coding and Unit Testing Integration and System Testing, and Maintenance 2. Differentiate between structured analysis and structured design. Ans.: - Traditional design consists of two different activities; first a structured analysis of the requirements specification is carried out where the detailed structure of the problem is examined. This is followed by a structured design activity. During structured design, the results of structured analysis are transformed into the software design. 3. Identify at least three activities undertaken in an objectoriented software design approach. Ans.: - In this technique, various objects that occur in the problem domain and the solution domain are first identified, and the different relationships that exist among these objects are identified. The object structure is further refined to obtain the detailed design. 4. Identify three reasons for the necessity of developing a prototype during software development. Ans.: - There are several uses of a prototype. An important purpose is to illustrate the input data formats, messages, reports, and the interactive dialogues to the customer. This is a valuable mechanism for gaining better understanding of the customers needs: how screens might look like

how the user interface would behave how the system would produce outputs

Write whether true of false. Justify your answer. 1. Evolutionary life cycle model is ideally suited for development of very small software products typically requiring a few months of development effort. Ans.: - False

Explanation: - The Evolutionary model is very useful for very large problems where it becomes easier to find modules for incremental implementation. 2. Prototyping life cycle model is the most suitable one for undertaking a software development project susceptible to schedule slippage. Ans.: - False. Explanation: - The prototype model is suitable for projects whose user requirements or the underlying technical aspects are not well understood. 3. Spiral life cycle model is not suitable for products that are vulnerable to large number of risks. Ans.: - False. Explanation: - The spiral model is suitable for development of technically challenging software products that are prone to several kinds of risks.

Basic issues in software design

Objectives
To understand the different design approaches and how the entire program is broken down into different modules ,and how they are related to each other. What standards we need to follow while designing and coding. Lecture 9 Software design Objective:
Identify the software design activities. Identify the primary differences between analysis and design activities Identify the important items developed during the software design phase. State the important desirable characteristics of a good software design. Software design deals with transforming the customer requirements, as described in the SRS document, into a form (a set of documents) that is suitable for implementation in a programming language. A good software design is seldom arrived by using a single step procedure but rather through several iterations through a series of steps. Design activities can be broadly classified into two important parts: Preliminary (or high-level) design and Detailed design.

Difference between analysis and design


The aim of analysis is to understand the problem with a view to eliminate any

deficiencies in the requirement specification such as incompleteness, inconsistencies, etc. The model which we are trying to build may be or may not be ready. The aim of design is to produce a model that will provide a seamless transition to the coding phase, i.e. once the requirements are analyzed and found to be satisfactory, a design model is created which can be easily implemented.

Items developed during the software design phase


For a design to be easily implemented in a conventional programming language, the following items must be designed during the design phase. Different modules required to implement the design solution. Control relationship among the identified modules. The relationship is also known as the call relationship or invocation relationship among modules. Interface among different modules. The interface among different modules identifies the exact data items exchanged among the modules. Data structures of the individual modules. Algorithms required to implement each individual module.

Cohesion
Most researchers and engineers agree that a good software design implies clean decomposition of the problem into modules, and the neat arrangement of these modules in a hierarchy. The primary characteristics of neat module decomposition are high cohesion and low coupling. Cohesion is a measure of functional strength of a module. A module having high cohesion and low coupling is said to be functionally independent of other modules. By the term functional independence, we mean that a cohesive module performs a single task or function. A functionally independent module has minimal interaction with other modules.

Classification of cohesion
The different classes of cohesion that a module may possess are as follows

Coincidental cohesion:
A module is said to have coincidental cohesion, if it performs a set of tasks that relate to each other very loosely, if at all. In this case, the module contains a random

collection of functions. It is likely that the functions have been put in the module out of pure coincidence without any thought or design. For example, in a transaction processing system (TPS), the get-input, print-error, and summarize-members functions are grouped into one module. The grouping does not have any relevance to the structure of the problem.

Logical cohesion:
A module is said to be logically cohesive, if all elements of the module perform similar operations, e.g. error handling, data input, data output, etc. An example of logical cohesion is the case where a set of print functions generating different output reports are arranged into a single module.

Temporal cohesion:
When a module contains functions that are related by the fact that all the functions must be executed in the same time span, the module is said to exhibit temporal cohesion. The set of functions responsible for initialization, start-up, shutdown of some process, etc. exhibit temporal cohesion.

Procedural cohesion:
A module is said to possess procedural cohesion, if the set of functions of the module are all part of a procedure (algorithm) in which certain sequence of steps have to be carried out for achieving an objective, e.g. the algorithm for decoding a message.

Communicational cohesion:
A module is said to have communicational cohesion, if all functions of the module refer to or update the same data structure, e.g. the set of functions defined on an array or a stack.

Sequential cohesion:
A module is said to possess sequential cohesion, if the elements of a module form the parts of sequence, where the output from one element of the sequence is input to the next. For example, in a TPS, the get-input, validate-input, sort-input functions are grouped into one module.

Functional cohesion:
Functional cohesion is said to exist, if different elements of a module cooperate to achieve a single function. For example, a module containing all the functions required to manage employees pay-roll exhibits functional cohesion. Suppose a module exhibits functional cohesion and we are asked to describe what the module does, then we would

be able to describe it using a single sentence.

Coupling
Coupling between two modules is a measure of the degree of interdependence or interaction between the two modules. A module having high cohesion and low coupling is said to be functionally independent of other modules. If two modules interchange large amounts of data, then they are highly interdependent. The degree of coupling between two modules depends on their interface complexity. The interface complexity is basically determined by the number of types of parameters that are interchanged while invoking the functions of the module.

Classification of Coupling
Even if there are no techniques to precisely and quantitatively estimate the coupling between two modules, classification of the different types of coupling will help to quantitatively estimate the degree of coupling between two modules. Five types of coupling can occur between any two modules. This is shown below

Data coupling:
Two modules are data coupled, if they communicate through a parameter. An example is an elementary data item passed as a parameter between two modules, e.g. an integer, a float, a character, etc. This data item should be problem related and not used for the control purpose.

Stamp coupling:
Two modules are stamp coupled, if they communicate using a composite data item such as a record in PASCAL or a structure in C.

Control coupling:
Control coupling exists between two modules, if data from one module is used to direct the order of instructions execution in another. An example of control coupling is a flag set in one module and tested in another module.

Common coupling:

Two modules are common coupled, if they share data through some global data items.

Content coupling:
Content coupling exists between two modules, if they share code, e.g. a branch from one module into another module.

Function-oriented design
The following are the salient features of a typical function-oriented design approach: 1. A system is viewed as something that performs a set of functions. Starting at this highlevel view of the system, each function is successively refined into more detailed functions. For example, consider a function create-new-library-member which essentially creates the record for a new member, assigns a unique membership number to him, and prints a bill towards his membership charge. This function may consist of the following sub-functions: assign-membership-number create-member-record print-bill Each of these sub-functions may be split into more detailed sub functions and so on. 2. The system state is centralized and shared among different functions, e.g.data such as member-records is available for reference and updating to several functions such as:

create-new-member delete-member update-member-record Object-oriented design


In the object-oriented design approach, the system is viewed as collection of objects (i.e. entities). The state is decentralized among the objects and each object manages its own state information. For example, in a Library Automation Software, each library member may be a separate object with its own data and functions to operate on these data. In fact, the functions defined for one object cannot refer or change data of other objects. Objects have their own internal data which define their state. Similar objects constitute a class. In other words, each object is a member of some class. Classes may inherit features from super class. Conceptually, objects communicate by message

passing.

Function-oriented vs. object-oriented design approach


The following are some of the important differences between function-oriented and object-oriented design. Unlike function-oriented design methods, in OOD, the basic abstraction are not real-world functions such as sort, display, track, etc, but real-world entities such as employee, picture, machine, radar system, etc. For example in OOD, an employee payroll software is not developed by designing funtions such as update-employee-record, get-employee-address, etc. but by designing objects such as employees, departments, etc. Grady Booch sums up this difference as identify verbs if you are after procedural design and nouns if you are after object-oriented design In OOD, state information is not represented in a centralized shared memory but is distributed among the objects of the system. For example, while developing an employee pay-roll system, the employee data such as the names of the employees, their code numbers, basic salaries, etc. are usually implemented as global data in a traditional programming system; whereas in an object-oriented system these data are distributed among different employee objects of the system. Objects communicate by message passing. Therefore, one object may discover the state information of another object by interrogating it. Of course, somewhere or other the real-world functions must be implemented. In OOD, the functions are usually associated with specific real-world entities (objects); they directly access only part of the system state information.

Model
A model captures aspects important for some application while omitting (or abstracting) the rest. A model in the context of software development can be graphical, textual, mathematical, or program code-based. Models are very useful in documenting the design and analysis results. Models also facilitate the analysis and design procedures themselves. Graphical models are very popular because they are easy to understand and construct. UML is primarily a graphical modeling tool. However, it often requires text explanations to accompany the graphical models.

Why We Need a Model


An important reason behind constructing a model is that it helps manage complexity. Once models of a system have been constructed, these can be used for a

variety of purposes during software development, including the following: Analysis Specification Code generation Design Visualize and understand the problem and the working of a system Testing, etc. It is a good idea to explicitly mention the purpose for which a model has been developed, along with the model.

Unified Modeling Language (UML)


UML, as the name implies, is a modeling language. It may be used to visualize, specify, construct, and document the artifacts of a software system. It provides a set of notations (e.g. rectangles, lines, ellipses, etc.) to create a visual model of the system. Like any other language, UML has its own syntax (symbols and sentence formation rules) and semantics (meanings of symbols and sentences). Also, we should clearly understand that UML is not a system design or development methodology, but can be used to document object-oriented and analysis results obtained using some methodology. UML was developed to standardize the large number of object-oriented modeling notations that existed and were used extensively in the early 1990s. The principles ones in use were: Object Management Technology [Rumbaugh 1991] Boochs methodology [Booch 1991] Object-Oriented Software Engineering [Jacobson 1992] Odells methodology [Odell 1992] Shaler and Mellor methodology [Shaler 1992]

UML diagrams
UML can be used to construct nine different types of diagrams to capture five different views of a system. Just as a building can be modeled from several views (or perspectives) such as ventilation perspective, electrical perspective, lighting perspective, heating perspective, etc.; the different UML diagrams provide different perspectives of the software system to be developed and facilitate a comprehensive understanding of the system. Such models can be refined to get the actual implementation of the system. The UML diagrams can capture the following five views of a system: Users view Structural view Behavioral view Implementation view Environmental view

Fig 12.1 Different Types of Diagram and view supported in UML

Users view:
This view defines the functionalities (facilities) made available by the system to its users. The users view captures the external users view of the system in terms of the functionalities offered by the system. The users view is a black-box view of the system where the internal structure, the dynamic behavior of different system components, the implementation etc. are not visible. The users view is very different from all other views in the sense that it is a functional model compared to the object model of all other views. The users view can be considered as the central view and all other views are expected to conform to this view. This thinking is in fact the crux of any user centric development style.

Structural view: The structural view defines the kinds of objects (classes) important to the understanding of the working of a system and to its implementation. It also captures the relationships among the classes (objects). The structural model is also called the static model, since the structure of a system does not change with time. Behavioral view: The behavioral view captures how objects interact with each other to realize the system behavior. The system behavior captures the time-dependent (dynamic) behavior of the system. Implementation view:

This view captures the important components of the system and their dependencies. Environmental view: This view models how the different components are implemented on different pieces of hardware.

Use Case Model Objectives


Identify different use cases of a system. Identify the purpose of use cases. Represent use cases for a particular system. Explain the utility of the use case diagram. Factorize use cases into different component use cases. Explain the organization of use cases. The use case model for any system consists of a set of use cases. Intuitively, use cases represent the different ways in which a system can be used by the users. A simple way to find all the use cases of a system is to ask the question: What the users can do using the system? Thus for the Library Information System (LIS), the use cases could be: issue-book query-book return-book create-member add-book, etc

Purpose of use cases


The purpose of a use case is to define a piece of coherent behavior without revealing the internal structure of the system. The use cases do not mention any specific algorithm to be used or the internal data representation, internal structure of the software, etc. A use case typically represents a sequence of interactions between the user and the system. These interactions consist of one mainline sequence.

How to represent Use Case Diagram


Use cases can be represented by drawing a use case diagram and writing an accompanying text elaborating the drawing.

In the use case diagram, each use case is represented by an ellipse with the name of the use case written inside the ellipse. All the ellipses (i.e. use cases) of a system are enclosed within a rectangle which represents the system boundary. The name of the system being modeled (such as Library Information System) appears inside the rectangle. The different users of the system are represented by using the stick person icon. Each stick person icon is normally referred to as an actor. An actor is a role played by a user with respect to the system use.

Example :
The use case model for the Supermarket Prize Scheme is shown in fig. 12.2.The use cases correspond to the high-level functional requirements. From the problem description and the context diagram, we can identify three use cases: register-customer, register-sales, and select-winners. As a sample, the text description for the use case register-customer is shown.

Fig 12.2 Example of Supermarket prize Scheme. Text description U1: register-customer: Using this use case, the customer can register himself by providing the necessary details. Scenario 1: Mainline sequence 1. Customer: select register customer option.

2. System: display prompt to enter name, address, and telephone number. 3. Customer: enter the necessary values. 4. System: display the generated id and the message that the customer has been successfully registered. Scenario 2: at step 4 of mainline sequence 1. System: displays the message that the customer has already registered. Scenario 2: at step 4 of mainline sequence 1. System: displays the message that some input information has not been entered. The system display a prompt to enter the missing value. The description for other use cases is written in a similar fashion.

Potrebbero piacerti anche