Keep in mind A good program is not one that just works A good - - PDF document

keep in mind
SMART_READER_LITE
LIVE PREVIEW

Keep in mind A good program is not one that just works A good - - PDF document

10/12/2019 Keep in mind A good program is not one that just works A good program is not one that just works Just working is not enough. A good software program is one that is Well organized Well commented and documented Easy


slide-1
SLIDE 1

10/12/2019 1 Keep in mind

Just working is not enough. A good software program is one that is

  • Well organized
  • Well commented and documented
  • Easy to read
  • Easy to understand

A good program is not one that just works A good program is not one that just works

Coding standards

Code for safety-critical systems must be certified by a certification authority that certifies that a software product complies with the requirements. Code for safety-critical systems must be certified by a certification authority that certifies that a software product complies with the requirements. Safety-critical means that a failure or a design error could cause a risk to human life. In order to be certified, safety-critical software must comply with given coding standards. For example:

  • DO-178

is used for avionic/aerospace applications

  • EN 50128

is used for railway systems

  • MISRA

is used for automotive systems

Safety Integrity Levels

The safety level associated with a safety-critical code is measured by a Safety Integrity Level (SIL) in terms of probability of failure per hour (PFH) The safety level associated with a safety-critical code is measured by a Safety Integrity Level (SIL) in terms of probability of failure per hour (PFH)

SIL PFH SIL0 > 10-5 SIL1 10-5 - 10-6 SIL2 10-7 - 10-8 SIL3 10-9 - 10-10 SIL4 10-11 - 10-12

Most safety-critical systems require a SIL4 certification for the control software.

Code complexity

“The complexity of a object is a measure of the mental effort required to understand and create that object.” [Myers, 1976] “The complexity of a object is a measure of the mental effort required to understand and create that object.” [Myers, 1976] “Code complexity is a major cause of unreliability in software” [McCabe, 1976]. “Code complexity is a major cause of unreliability in software” [McCabe, 1976]. Programmers writing safety-critical software should contain code complexity.

Complexity metrics

Source code complexity can be measured in several ways. It is important to distinguish between

  • the natural complexity of the problem and
  • the actual complexity of the solution

Ideally, we would like the actual complexity to be no greater than the natural complexity. Unfortunately, most often, software solutions are much more complex than they could be, hence we have that actual complexity >> natural complexity Unfortunately, most often, software solutions are much more complex than they could be, hence we have that actual complexity >> natural complexity

slide-2
SLIDE 2

10/12/2019 2 Simple vs. complex

#include <stdio.h> int main() { printf("Hello World\n"); return 0; } #include <stdio.h> #define MAX_SIZE 50 int main() { char s[MAX_SIZE] = "Hello World"; int i; i = 0; while (s[i] != '\0') { printf("%c", s[i]); i = i + 1; } printf("\n"); return 0; }

Complexity metrics

  • Maximum Nesting of Control Structures: any statement

inside another increments the metric by one. Source code complexity can be measured in several ways:

  • Number of lines of code (LOC)

It counts the number of bits required for a uniform binary encoding of the program text. It counts the number of bits required for a uniform binary encoding of the program text.

  • Program Volume (V):

V = (Nv + No) * log2 (Dv + Do)

  • Dv = # of distinct variables
  • Do = # of distinct operators
  • Nv = # of variable occurrencies
  • No = # of operator occurrencies
  • Cyclomatic

complexity: is the number

  • f

linearly independent paths. High cyclomatic complexity is an indication of inadequate modularization or too much logic in

  • ne function.

Coding standards

To produce software that has to be certified SIL4, programmers must follow some specific guidelines. They can be distinguished in: Coding rules they limit the use of language constructs that can be dangerous (e.g., MISRA-C 2012). Coding styles they are meant to improve code readability and maintainability.

Coding Rules

The Motor Industry Software Reliability Association (MISRA) provided some guidelines for the use of C language in safety-critical systems.

C can be used to write well structured and expressive programs, but can also be used to write perverse and extremely hard-to-understand code. The latter is not acceptable in a safety-related system. C can be used to write well structured and expressive programs, but can also be used to write perverse and extremely hard-to-understand code. The latter is not acceptable in a safety-related system.

Example of MISRA rules

4.7: If a function returns an error code, then that code shall be tested. 4.11: The validity of values passed to library functions shall be checked. 4.12: Dynamic memory allocation shall not be used. 9.3: Arrays shall not be partially initialized. 14.1: Loop counters shall not be floating point variables. 15.1: The goto statement shall not be used.

Example of MISRA rules

6.4.5: Every non‐empty case clause in a switch statement shall be terminated with a break statement. 6.4.6: All switch statements shall contain a final default clause. 6.4.7: A switch condition should not be of Boolean type. 7.5.4: Functions should not call themselves. 8.4.3: All exit paths from a function shall have an explicit return statement.

slide-3
SLIDE 3

10/12/2019 3 Coding Styles

  • 1. It simplifies program reading & comprehension;
  • 2. It facilitates program maintenance;
  • 3. It reduces the possibility of making mistakes;
  • 4. It

allows quickly identifying syntactic and semantic errors;

  • 5. It avoids irritating project reviewers.

Hence, adopt these rules since the beginning! Hence, adopt these rules since the beginning! Programming style is fundamental for many reasons: Style rules concern the following aspects:

  • 1. Horizontal spacing
  • 2. Vertical spacing
  • 3. Indentation
  • 4. Comments
  • 5. Code organization

Coding Styles

It refers to a set of rules to follow to separate objects contained in the same line of code. A TAB is not equivalent to a set of spaces!!! A TAB is not equivalent to a set of spaces!!! ···|···|···|···|···|···|···|···|···| int i; char c; floatx; int····k; char····a; float····y; Use an editor that does not replace TABs with spaces. Use an editor that does not replace TABs with spaces.

Horizontal spacing

Declarations Insert a TAB after each type identifier. Declarations Insert a TAB after each type identifier. int i; float x; Multiple declarations Insert a SPACE after each comma. Multiple declarations Insert a SPACE after each comma. int i,·j,·k; float x,·y,·z;

Horizontal spacing

Expressions

  • perators with 2 operands must have a space in

both sides: Expressions

  • perators with 2 operands must have a space in

both sides:  x = (a + 2) * (b - 1); Parentheses Never put a space after a left parenthesis or before a right one. Parentheses Never put a space after a left parenthesis or before a right one.  a=( a+5)*( b- 2 ); // AVOID  a = (a + 5) * (b - 2); // CORRECT

Horizontal spacing

Semicolons (;)

  • Never put a space before a semicolon;
  • Always put a space after a semicolon if it is not

the last character of the line. Semicolons (;)

  • Never put a space before a semicolon;
  • Always put a space after a semicolon if it is not

the last character of the line.

 for( i= 0;i <10 ;i++ ) // AVOID  for (i=0; i<10; i++) // CORRECT

Horizontal spacing

slide-4
SLIDE 4

10/12/2019 4 Horizontal spacing

Conditional statements

  • Always put a space between the instruction name

and the parenthesis specifying the condition. Conditional statements

  • Always put a space between the instruction name

and the parenthesis specifying the condition.  if( a < b )x = a; // AVOID  if (a < b) x = a; // CORRECT  while (v[i] < 0) i = i + 1;  for (i=0; i<10; i++) v[i] = 0;

int i, n; int sum, v[10]; for (i=0; i<n; i++) v[i] = 0; i = 0; while (i < n) { v[i] = i; i++; } }

good vertical spacing good vertical spacing

Vertical spacing

It refers to the use of newline to separate groups of statements. It refers to the use of newline to separate groups of statements.

int i, n; int sum, v[10]; for (i=0; i<n; i++) v[i] = 0; i = 0; while (i < n) { v[i] = i; i++; } }

It refers to the use of newline to separate groups of statements. It refers to the use of newline to separate groups of statements. bad vertical spacing bad vertical spacing

Vertical spacing Indentations

int main() { int i, k; for (k=0; k<dim; k++) { i = 0; while (v[i] < w[k]) { if (v[i] > max) max = v[i] + w[k]; i = i + 1; } }

It refers to the space put at the beginning of a line. Each nested section must be right-shifted of a TAB. It refers to the space put at the beginning of a line. Each nested section must be right-shifted of a TAB. good indentation good indentation

int main() { int i, k; for (k=0; k<dim; k++) { i = 0; while (v[i] < w[k]) { if (v[i] > max) max = v[i] + w[k]; i = i + 1; } }

It refers to the space put at the beginning of a line. Each nested section must be right-shifted of a TAB. It refers to the space put at the beginning of a line. Each nested section must be right-shifted of a TAB. bad indentation bad indentation

Indentations Parentheses

for (k=0; k<dim; k++) { i = 0; while (v[i] < w[k]) { if (v[i] > max) { max = v[i]; m = i; } i = i + 1; } } for (k=0; k<dim; k++) { i = 0; while (v[i] < w[k]) { if (v[i] > max) { max = v[i]; m = i; } i = i + 1; } }

There are two religions. As all religions, both are fine. There are two religions. As all religions, both are fine. But this allows you to save more vertical space. But this allows you to save more vertical space.

slide-5
SLIDE 5

10/12/2019 5

int main() { for (int k=0; k<dim; k++) v[k] = rand(); int max = 0; int m = 0; for (int i=0; i<dim; i++) { if (v[i] > max) { max = v[i]; m = i; } } }

Keep variable declarations before the code: Keep variable declarations before the code:

Separate declarations from code

TO BE AVOIDED

int main() { int k, i, m; // array indexes int max; // maximum array element for (k=0; k<dim; k++) v[k] = rand(); for (i=0; i<dim; i++) { if (v[i] > max) { max = v[i]; m = i; } } }

Keep variable declarations before the code: Keep variable declarations before the code:

Separate declarations from code

Preferred way Preferred way

Comments

They must be:

  • 1. short;
  • 2. meaningful;
  • 3. updated with code changes.

Comments must be used to explain the meaning of variables and functionality of parts of the program. Comments must be used to explain the meaning of variables and functionality of parts of the program. Do not exagerate! Long and trivial comments can worsen readability! Do not exagerate! Long and trivial comments can worsen readability!

a = b + c; // computes a as b+c count++; // increment the counter z = f(x,y); // f requires 2 arguments

Example of useless comments Example of useless comments Such comments are not only useless, but even dangerous, because increase the amount of text to read and obscure the structure of the program. Such comments are not only useless, but even dangerous, because increase the amount of text to read and obscure the structure of the program.

Comments

  • 1. at the beginning of a file, to explain its contain

and functionality;

  • 2. next to each declaration of variable, constant, or

data structure, to explain its meaning;

  • 3. before each function, to explain its functionality,

the meaning of each argument and the return value (if any);

  • 4. before non trivial operations;

They should be inserted in the following situations:

Comments Types of comments

Depending on their position and length, different styles should be used to write a comment. int r; // circle radius int x, y; // center coordinates Comments to variables Should be on the right of the declaration, separated by one or more TABs:

slide-6
SLIDE 6

10/12/2019 6

One line comments They should be written just before the instruction (or group of instructions) to be explained: // initialize array v for (i=0; i<dim; i++) v[i] = 0;

Types of comments

Long comments They should be written before the code to be explained, highlighting them with some border.

//----------------------------------------- // Function even(n) returns 1 if n // is an even number, 0 otherwise //----------------------------------------- int even(int n) { if (n % 2 == 0) return 1; else return 0; }

Types of comments

Organize code according to the following order:

  • 1. Header files (standard first, yours later)
  • 2. Global constants (separate them into groups)
  • 3. Function prototypes
  • 4. Global data structures
  • 5. Functions definitions
  • 6. Tasks definitions
  • 7. Main function

Code organization Code organization

Very important programming rule Any function (including main) should NOT be longer than one page. Any function (including main) should NOT be longer than one page.

  • If a function is longer than one page, it means

that you should define a new auxiliary function.

  • A program should be self explanatory by the

sequence of functions it contains.

35

General approach

The idea is to implement each library in a different file providing a set of functions for using it.

f1() f1() f3() f3() f2() f2() f4() f4()

Main program Main program Static global data structures Static global data structures

  • Static global data can only

be accessed through the provided library functions.

mylib.c project.c

Use of header files

C programs are normally organized into separately compiled modules.

  • The X.c file must include the X.h file
  • Global variables must be declared as extern in the X.h file
  • Other modules can access the functionality in module X by inserting

#include "X.h"

  • X.c has to be compiled only if changed; the rest of the times the linker will

link X’s code into the final executable without needing to recompile it. Except for the main module, each module X consists of a source file (X.c): contains global variable definitions, initializations and function definitions. header file (X.h): contains

  • nly:

structure type declarations, function prototypes, and extern global variable declarations. Module: group of declarations and functions that are developed and maintained separately and possibly reused in different projects. Good examples are the math and string Standard Libraries. Module: group of declarations and functions that are developed and maintained separately and possibly reused in different projects. Good examples are the math and string Standard Libraries.

slide-7
SLIDE 7

10/12/2019 7

  • Keep a module’s internal declarations out of the header file

Global variables or functions that are used only in module X must be declared as static in X.c and must not be mentioned in the X.h file.

  • Always use include “guards” in a header file

When several source files include the same header files, the compiler generates an error if the same entities are defined multiple times. To avoid this, you can make sure that a given include file is only included in a particular source code once with the #ifndef directive. For example “geometry.h” would start with: #ifndef GEOMETRY_H #define GEOMETRY_H and end with: #endif Do not start the guard symbol with an underscore! Leading underscore names are reserved for internal use by the C implementation.

Use of header files

  • A.h should include all strictly needed header files, but no more

If a structure type defined in module X is used as a member variable of a structure type A, then you must include X.h in A.h, so that the compiler knows how large the X member is. However, do not include header files needed only by the .c file. For instance <math.h> is usually needed only by the function definitions, therefore it should be included in the .c file, not in the .h file. Read more on: http://www.umich.edu/~eecs381/handouts/CHeaderFileGuidelines.pdf

Use of header files

  • File A.c should first include its A.h, then the other required headers
  • Never include a source .c file for any reason!

39

Makefile

#--------------------------------------------------- # Target file to be compiled by default #--------------------------------------------------- MAIN = balls #--------------------------------------------------- # CC is the compiler to be used #--------------------------------------------------- CC = gcc #--------------------------------------------------- # CFLAGS are the options passed to the compiler #--------------------------------------------------- CFLAGS = -Wall #--------------------------------------------------- # OBJS are the object files to be linked #--------------------------------------------------- OBJ1 = mylib1 OBJ2 = mylib2 OBJS = $(MAIN).o $(OBJ1).o $(OBJ2).o #--------------------------------------------------- # LIBS are the external libraries to be used #--------------------------------------------------- LIBS = -lpthread –lrt -lm `allegro-config --libs`

40

Makefile

#--------------------------------------------------- # Dependencies #--------------------------------------------------- $(MAIN): $(OBJS) $(CC) -o $(MAIN) $(OBJS) $(LIBS) $(CFLAGS) $(MAIN).o: $(MAIN).c $(CC) -c $(MAIN).c $(OBJ1).o: $(OBJ1).c $(CC) -c $(OBJ1).c $(OBJ2).o: $(OBJ2).c $(CC) -c $(OBJ2).c #--------------------------------------------------- # Command that can be specified inline: make clean #--------------------------------------------------- clean: rm -rf *o $(MAIN)

Important guidelines (1)

1. Write code according to the given style rules. 2. Do not use dynamic memory allocation. 3. Define all local variables at the beginning of a function. 4. Limit the use of pointers. 5. Limit the use of recursion. 6. Never use the goto and continue statements. 7. Use break only in the switch statement. 8. Avoid numeric constants in the code (exceptions: 0, 0.5, 1, 2) Your project should comply with the following guidelines Your project should comply with the following guidelines

Important guidelines (2)

9. Limit the use of global variables.

  • 10. Limit the number of arguments in functions.
  • 11. Avoid functions longer than one page (define new functions).
  • 12. Avoid lines longer than 80 characters (lines can be split).
  • 13. Limit nested critical sections (through local variables).
  • 14. Encapsulate all time-related functions in a separate library.
  • 15. Periodic tasks should never block, except to wait for their next

activation.

  • 16. Organize your program in different source files ( 5).

Your project should comply with the following guidelines Your project should comply with the following guidelines