Translate

Search This Blog

Total Pageviews

Saturday, August 29, 2015

Running With RAPTOR

When developing a program, it is essential to plan out the program, normally using pseudocode. RAPTOR  allow you to practice this pseudocode and give you a chance to see a “real-life” application of programming skills.

RAPTOR is a visual programming environment based on flowcharts that are created to solve particular programming problems.
Normally, programmers use flowcharts to design a program or part of a program before writing the actual code. RAPTOR allows you to take flowcharting one step further by allowing you to test (run) your program design and to confirm that your logic works correctly to solve your problem.
In a programming logic course, RAPTOR is useful for several reasons. Compared with other programming languages, the RAPTOR language has minimal syntax (grammar), which means you spend less time learn it and debugging syntax errors.
You can concentrate on the most important aspect of programming: developing good logic and design. Also, the RAPTOR program is visual because it uses diagrams that allow you to understand the flow of control of the statements in your program.
RAPTOR screens
Several versions of RAPTOR are available. Download the last release (actually 4.0.6.004 from FALL 2014 VERSION (Updated 22 April 2015)) exist also portable version  and older releases too.
After you download and install RAPTOR, you can open the program by locating the little RAPTOR icon on your computer. You will see two screens(see Figure):
  • the RAPTOR work area screen 
  • and the MasterConsole screen .
When you first open RAPTOR your MasterConsole may be shrunk or hidden behind the main screen and you may have to click it to reveal it. You can resize the screens as you wish; it’s convenient to view them side-by-side.

When you execute a RAPTOR program you're in main tab, the program begins(refer to Work area) at the Start symbol at the top and follows the arrows to the End symbol(that's a template one can delete that symbols).
That's the smallest RAPTOR program (which does nothing). By placing additional RAPTOR statements between the Start and End symbols you create more meaningful RAPTOR programs.

 Prompts you after drag one symbol onto
the  Work area
To create a RAPTOR program, you drag instances(after dragging the flowcharting symbol change his colour from blue to red to show you the actual status) of each flowcharting symbol from the left side to the middle area(the joint point is shown trough a change in the mouse shape from ? to normal with a + to the right then you can drop the symbol) of the screen, as shown in Figure. RAPTOR will prompt you to save your file as soon as you drag one symbol onto the screen(Work area). Then you can begin to create your program. 

Backups

RAPTOR makes backup files of your programs automatically. After you work on a program for some time, if you look in Windows Explorer or MyComputer, you will see a group of files under your RAPTOR file. The RAPTOR file has the extension .rap and is identified by the RAPTOR icon. The backup files are named with the same name as your program but include .backup0, .backup1, and so on.
These files can be ignored and, when you are finished creating your program, can be deleted.
Entering information into a dialog box
To enter information into a symbol that you have dragged to the screen, double-click it. A dialog box (a small window) will open, which allows you to enter the information that is possible or required for that symbol. E.g. for an Assignment box, as shown in Figure, double-clicking the box will open the dialog box. Assignment boxes allow you to enter information about variables.


Variables

The identifiers in raptor aren't case sensitive so the identifier x is considered the same as X , so the statement Set X = 32 assigns the value of 32 to the variable named X.
In RAPTOR, an arrow (in Ubuntu can't notice any arrow except a space between an R-value and L-value) pointing left  assigns the value on the right-hand side to the variable named on the left-hand side. Therefore, X  32 assigns the value of 32 to the variable named X.
In Figure, the box directly under the Start symbol (X  32) assigns the value 32 to the variable X.
The next statement, X  X + 1 says “X now is assigned the value it had (32) plus 1.” So, after that statement executes, the previous value of
X is replaced by the value 33.
The next statement, X  X * 2 says “assign to the variable X the present value of X multiplied by 2.” In this case, X had the value 33 and, after the statement is executed, it contains the value 66(Notice it in the Watch window).
All RAPTOR variables are of type Number or String.
A Number can be either a whole number (an integer) or a decimal number (a floating point number).
RAPTOR does not distinguish between number types.
A String is a text value into " ", like "Hello, friend" or "pony" or a single character like "e" or "W" or even a number, as long as the number is not used for any computations. For example, a ­ telephone number such as "352-381-3829" is a String.
A variable can have its value set or changed/updated in RAPTOR by one of the three ways:
  • The value can be entered from an Input statement
  • The value can be calculated from an equation in an Assignment statement
  • The value can be returned from a procedure Call (more on this later)
As in most languages, it’s necessary to associate several things with a new variable.
A variable must be given:
  • a name, 
  • a data type, 
  • and often an initial value.

Declaring variables

When a RAPTOR program begins its execution, no variables exist. The first time RAPTOR encounters a new variable name, it automatically creates a new memory location and associates this variable name with the new memory. Therefore, in RAPTOR you don’t need to declare variables explicitly, as we probably do in the pseudocode with Declare statements.
The variable will exist from the point at which it is created in the program execution until the program terminates.

Initializing variables

Attempts to use a variable named X before it is created(had
been assigned any value).
When a new variable is created in RAPTOR, it must be given an initial value. This is slightly different from other languages where it is possible to declare a variable without giving it a value at that time.
The initial value in RAPTOR determines the variable’s type. If the value is a number, the variable is of type Number. If the initial value is text, the variable is of type String.
Note that any initial value that is enclosed in quotes is considered text(String) e.g. :
  • If the variable myNum is set to 34, it is stored with the Number type.
  • If the variable myWord is set to "34", it is stored with the String type.
A variable’s data type cannot change during the execution of a program.
Beware! While a variable in RAPTOR can be created “on the fly” (i.e., by simply entering a variable name and giving it a value), a variable cannot be used until it has been created(see Figure).

Common Errors and Their Causes

     The variable Y has not been given a value
Error 1: Variable ____ doesn't have a value.

There are two common reasons for this error:







     The variable (Mile) name is misspelled













Error 2: Variable ___ not found!
This error means you have tried to use a variable before you have declared it or assigned it an initial value(like the first case in Error 1).

Error 3: Can’t assign string to numeric variable _____.
Can’t assign numeric to string variable _____.

This error occurs if your statements attempt to change the data type of a variable.
In newer versions of RAPTOR, you may be allowed to change a data type “on the fly” but this is never a good programming practice.













RAPTOR Symbols

 3 of the 6 RAPTOR symbols and instructions
Now lets provide details about each of the basic symbols: Input,
Assignment, and Output. The other symbols will be covered later.






Input Symbol

Every programming language has statements that enable the program to get information from the user via the keyboard or mouse and display that information on the computer screen. This allows the user to enter instructions to the program or supply the program with necessary information.
In RAPTOR, when an Input symbol is executed, a prompt(as dialog window) is displayed prompting the user to enter some value; the user then enters a value which is stored in a given variable. The Enter Input dialog box (see Figure ) shows what is displayed when you drag an Input symbol onto your flowchart and double-click in the symbol.
In the Enter Prompt Here box at the top, you enter the text you want the user to see. The text typed in this box will be displayed to the user when the program is run and, therefore, should explain what information needs to be input. This text must be enclosed in quotes. Make sure your prompt is clear and complete.
The Enter ­Variable Here box holds the name of the variable where the information the user enters will be stored. You can enter the name of a variable you have previously declared or you can declare a new variable and enter it here.
  • The information entered will be stored in a variable and used later in the program. For example, if you are calculating the cost of buying widgets and the user enters $1.50 for the price of one widget, this will be stored in a String variable called Price; the dollar sign ($) prevents it from being considered a Number. This will give you an error when you use Price in a calculation. Since Price must be a Number, the dollar sign cannot be part of the user’s
    entry. Be sure to tell the user not to include units when entering numbers.
    For example, a good prompt might read, "Enter the price of a widget, without the $ (i.e., 1.50 for a widget that costs $1.50)."
     
  • If you are asking the user to enter a text response, you must be specific. For example, if you want the user to choose yes or no, you must tell the user what to type because, to a computer, "yes" is not the same as "y" or "YES". A good prompt for this example might read, "Do you want to continue? Type 'y' for yes or 'n' for no."


Nested Quotes

At this point it is helpful to point out a situation that occurs frequently when coding an output text. Imagine you want the following output to explain to the user how to enter a choice:
Do you want to play the game again? Type "y" for yes, "n" for no.
Often the output includes some text that needs to be wrapped in quotes. However, a String, to the computer, is any text enclosed in quotes. The computer understands that the beginning of a String starts with the first quote symbol (") and ends when it encounters a second quote symbol ("). If the output text shown above was to be stored in a variable named YourChoice and was coded as follows:
YourChoice = "Do you want to play the game again? Type "y" for yes,
"n" for no."
the computer would process "Do you want to play the game again? Type" as the String to be stored in YourChoice and then display an error because the next character, y, is unintelligible to a computer interpreter or compiler.
That is why we not must nest quotes within a String. We must use a different symbol for internal quotes (those that are part of the String text) than the outer quotes, which mark the beginning and end of the String. In this case, a single quote (') indicates that we are still inside the original text String. In some languages, the outer quotes must be double quotes ("), while in other languages double quotes can be nested inside single quotes as well as the other way around.
The correct way to write the code for the YourChoice variable, then is:
YourChoice = "Do you want to play the game again? Type 'y' for yes,
'n' for no."

Using the Input Box to Change the Value
of a Declared Variable



















Using the Input Box to Declare and Initialize
a Variable





















Assignment Symbol

The Assignment symbol is used to set the value of a variable or to perform a computation and then store the results in a variable. The value stored in the variable can be retrieved and used in a statement later in the program.
The dialog box shown in Figure is used to enter the name of the variable being assigned and its value.
The variable name is entered in the small text box: Set ________.
The value is entered in the large text box: to ________. This value can be a number, character, or a string of text. If this is the first time the variable has been used, its type is set by the value you enter. If you type a number, the variable becomes a Number type.
You can also type in a computation for the value of a variable. The result will be assigned to the variable.

Here is how RAPTOR processes an Assignment statement:
  • First, the expression on the right-hand side of the Assignment operator is evaluated.
  • Then, that value is placed in the memory location associated with the variable on the left side, replacing whatever data value had been stored there previously.

Expressions

The expression (or computation) of an Assignment statement can be any simple or complex equation that results in a single value. An expression is a combination of values (either constants or variables) and operators. A computer can perform only one operation at a time. RAPTOR follows the same mathematical order as used in other languages.
An operator or function directs the computer to perform some computation on data. Operators are placed between the data being operated on (e.g., X + 3), whereas functions use parentheses to indicate the data they are operating on (e.g., sqrt(4.7)).
When executed, operators and functions perform their computation and return their result. The result of evaluating an expression in an Assignment statement must be either a single number or a single string of text. While many expressions will compute numbers, you can also perform simple text manipulation in RAPTOR by using a plus sign (+) to join (concatenate) two or more strings of text into a single string. You can also join numerical values with strings to create a single string. The following Assignment statement demonstrates string manipulation:
Full_name  = "Joe " + "Alexander " + "Smith"
The value of Full_name, after this Assignment statement, is Joe Alexander Smith.

Output Symbol

In RAPTOR, an Output statement displays a value to the MasterConsole screen when it is executed.
When you define an Output statement by clicking on the Output symbol in your flowchart, the Enter Output dialog box asks you to specify the text or expression to display and whether or not the output should be terminated by a newline character.
If you check the End current line box, any future output will start on a new line below the displayed text.
You can output text, the value of a variable, or any combination of text and variables.
Note: For the user we cannot just list the values of the variables; we need to add some explanation of what these values represent in the MasterConsole screen.

Comments

The RAPTOR development environment, like many programming languages, allows comments to be added to your program. All good programs include comments if the code itself is not self-explanatory. While in the beginning, comments often seem redundant or even downright silly since beginning programs are small and not particularly complex, it is a good idea to get into the habit of including comments.
To add a comment to a symbol in your flowchart, right-click the mouse button on the statement symbol(rclick in Linux get mostly in an unhandled exception so use Edit > Comments in Menu bar ) and select the Comment line before releasing the button. Then, enter the comment text into the Enter Comment dialog box. The resulting comment can be moved in the RAPTOR window by dragging it, but normally you would not need to move the default location of a comment.
Typically, you should not comment every statement in a program but should include comments before each new section of a program.

Documentation Is Always Important

Often a program can achieve the desired results in one of several ways. The decision about which code to use is up to you, the programmer. While many examples are short and simple,real programs may be much longer and more complicated.
P­rofessional programmers often work on code written by other people. It is easier for a programmer to edit someone else’s code if the programmer knows what the segment is designed to do. This is one reason why it is so important to use documentation in the form of comments to explain what your code is doing.

The Assignment Operator and the Comparison Operator in RAPTOR

RAPTOR allows you to use either a single or a double equals sign to indicate a comparison within a test condition. RAPTOR “understands” that a single equals sign indicates comparison by its placement in the diamond shape. RAPTOR also accepts the double equals sign as a comparison operator.
For example, if the condition you wish to check is “Is the value of Count equal to 5?” you could enter either of the following into the Enter Selection Condition  Count = 5 or Count == 5 . 
It's better use the double equals sign to indicate a comparison because it
is an important distinction which, in a typical programming language, can wreak havoc on a program if used incorrectly.

The Call Symbol and Subcharts

The Call symbol, is used to call submodules from the main program, as these submodules, named subcharts in RAPTOR, are needed.
Subcharts help break a RAPTOR program into logical parts, called as needed by the main program, to simplify design, ensure that flowcharts are manageable, and reduce the chance for errors.

When you start a RAPTOR program, you’ll see a main tab in the upper-left corner of the work area. To create a subchart, simply right-click the main tab and select Add subchart from the menu. Enter the name of your subchart and a new editing window will appear. The name you give your subchart is automatically created in this new window after you click yes when prompted.
 a new subchart named Calculations
Now you can begin to build your subchart. After you have created your program, to call a subchart, simply insert the Call symbol where you want it in your program(main tab), and enter the name of the subchart that you want it to be called.

A subchart may be called from the main flowchart or from other subcharts or even from within itself but be careful if you decide to try this! It can easily result in an infinite loop (a loop that runs forever).
As the program runs, when the Call is encountered, control will transfer to the subchart. After all the steps in the subchart are completed, control will automatically return to the next symbol after the Call.

In RAPTOR, each variable declaration uses a separate Assignment symbol. Initializing more than a few variables results in a long list of Assignment boxes that do not have much to do with the logic of the program. Therefore, for convenience, we can call a RAPTOR subchart as soon as the program begins, which will contain all our initial variable declarations. It keeps this long list of Assignment boxes out of the way and allows us to focus on the rest of the program.
You will now see your main work area and a new tab at the top, named Variables. You can click on the Variables tab and begin creating variables.
However, it is not necessary and, if you wish, you can initialize your variables in the main program. Since a variable’s data type in RAPTOR is created when the variable is given a value, we will create most of our number variables by giving them an initial value of 0 and most string variables by giving them an initial value of an empty space (" "). Some variables, our named constants, have predetermined values that will not change as the program runs. We can set these values now.
Testing the program at each submodule makes debugging a great deal easier than waiting for the end when you have many more combinations of tests to run and where it may be difficult to pinpoint the source of a bug. In RAPTOR, as you run your tests, look at the watch window on the left side to be sure that your variables are being assigned the correct values.


Resources

Wednesday, August 19, 2015

The C Language : History and Standards(till C99)

Dennis Ritchie designed the C language at Bell Laboratories  from 1969 to 1973, and its ancestry is traced from
  1. ALGOL 60 (1960)
  2. Cambridge's CPL (1963)
  3. Martin Richards's BCPL (1967)
  4. and Ken Thompson' s B language (1970) at Bell Labs 
 The American National Standards Institute (ANSI) ratified the ANSI C standard in 1989, and this standardization later became the responsibility of the International Standards Organization (ISO).
The standards define the C language and a set of library functions known as the C standard library.
Kernighan and Ritchie describe ANSI C in their classic book, which is known affectionately as “K&R”. In Ritchie’s words ,
C is “quirky, flawed, and an enormous success.” 
So why the success?

  • C was closely tied with the Unix operating system. C was developed from the beginning as the system programming language for Unix. Most of the Unix kernel, and all of its supporting tools and libraries, were written in C. As Unix became popular in universities in the late 1970s and early 1980s, many people were exposed to C and found that they liked it. Since Unix was written almost entirely in C, it could be easily ported to new machines, which created an even wider audience for both C and Unix
  • C is a small, simple language.The design was controlled by a single person, rather than a committee, and the result was a clean, consistent design with little baggage. The K&R book describes the complete language and standard library, with numerous examples and exercises, in only 261 pages.
    The simplicity of C made it relatively easy to learn and to port to different computers.
  • C was designed for a practical purpose. C was designed to implement the Unix operating system. Later, other people found that they could write the programs they wanted, without the language
    getting in the way.


Although C is a general-purpose programming language, it has traditionally been used for (operating) systems programming. In particular, the popular UNIX operating system was originally written in C.
C's popularity is due to many factors. It is a:
  • small
  • efficient, yet powerful programming language 
  • with a rich(in 70's) run-time library
  • It provides precise control over the computer without a lot of hidden mechanisms
  • Since it has been standardized for over 25 years, programmers are comfortable with it. It is generally easy to write C programs that will be portable across different computing systems in different countries with different languages
  • Finally, there is a lot of legacy C code out there that is being modified and extended
Starting in the late 1990s, C's popularity began to be eclipsed by its "big brother," C++. However. there is still a loyal following for the C language, and it continues to be popular where programmers do not need the features in C++ or where the overhead of C++ is not welcome.

C has withstood the test of time. It remains a language in which the experienced programmer can write quickly and well. Millions of lines of code testify to its usefulness.

C is the language of choice for system-level programming, and there is a huge installed base of application-level programs as well.

However, it is not perfect for all programmers and all situations.
  1. C pointers are a common source of confusion and programming errors. 
  2. C also lacks explicit support for useful abstractions such as classes, objects, and exceptions. Newer languages such as C++ and Java address these issues for application-level programs.


THE EVOLUTION OF C

In the mid of 80's , the C language was in widespread use, but there was no official standard or precise description of the language. The de facto standards were the C compilers being used.
C became an international standard in 1989, was revised in 1994, and underwent a major revision in 1999.
Unfortunately simply changing the definition of a language does not automatically alter the hundreds of millions of lines of C program code in the world.

Traditional C

The original C language description is the first edition of the book,
The C Programming Language, by Brian Kernighan and Dennis Ritchie (Prentice-Hall, 1978), usually referred to as "K&R." 
After the book was published, the language continued to evolve in small ways; some features were added and some were dropped.
We refer to the consensus definition of C in the early 1980's as traditional C, the dialect before the standardization process.
Of course, individual C vendors had their own extensions to traditional C, too.

Standard C (1989)

Realizing that standardization of the language would help C become more widespread in commercial programming, the American National Standards Institute (ANSI) formed a committee in 1982 to propose a standard for C and its run-time libraries. That committee X3J11 (now NCITS J11 ), was chaired by Jim Brodie and produced a standard formally adopted in 1989 as American National Standard X3.159-1989, or "ANSI C."

Recognizing that programming is an international activity, an international standardization group was created as ANSI C was being completed. 
ISO/IEC JTCl/SC22/WG14 under by P. J. Plauger turned the ANSI standard into an international standard, lSO/IEC 9899:1990, making only minor editorial changes. The ISO/IEC standard was thereafter adopted by ANSI, and people referred to this common standard as simply "Standard C" Since that standard would eventually be changed, we refer to it as Standard C (1989), or simply "C89".
Some of the changes from traditional C to C89 included:
• The addition of a truly standard library.
• New preprocessor commands and features.
• Function prototypes, which let you specify the argument types in a function declaration.
• Some new keywords, including const, volatile, and signed.
• Wide characters, wide strings, and multibyte characters.
• Many smaller changes and clarifications to conversion rules, declarations, and type checking.

Standard C (1995)

As a normal part of maintaining the C standard , WG14 produced two Technical Corrigenda (bug fixes) and an Amendment (extension) to C89. Taken together, these made a relatively modest change to the Standard mostly by adding new libraries
The result is what we call either "C89 with Amendment I" or "C95." 
The changes to C89 included:
• three new standard library headers: iso646.h, wctype.h, and wchar.h
• several new tokens and macros used as replacements for operators and punctuation characters not found in some countries's character sets
• some new formatting codes for the printf/scanf family of functions, and
• a large number of new functions, plus some types and constants, for multibyte and wide characters.

Standard C (1999)

ISO/IEC standards must be reviewed and updated on a regular basis. In 1995 WGI4 began work on a more extensive revision to the C standard, which was completed and approved in 1999. The new standard, ISO/IEC 9899:1999, or "C99," replaces the previous standard (and all corrigenda and amendments) and has now become the official Standard C.
Vendors are updating their C compilers and libraries to conform to the new standard.
C99 adds many new features to the C89/C95 language and libraries, including:
• complex arithmetic
• extensions to the integer types, including a longer standard type
• variable-length arrays
• a Boolean type
• better support for non-English character sets
• better support for floating-point types, including math functions for all types
• C++ style comments (/ /)
C99 is a much larger changeset than C95 since it includes changes to the language as well as extensions to the libraries. The C99 Standard document is significantly larger than the C89 document. However, the changes are "in the spirit of C," and they do not change the fundamental nature of the language.

Standard C++

C++, designed by Bjarne Stroustrup at AT&T Bell Labs in the early 1980s, has now largely supplanted C for mainstream programming. Most C implementations are actually C/C++ implementations, giving programmers a choice of which language to use.
C++ has itself been standardized, as ISO/lEC 14882:1998, or "Standard C++."
C++ includes many improvements over C that programmers need for large applications. including improved type checking and support for object-oriented programming. However, C++ is also one of the most complex programming languages, with many pitfalls for the unwary.
Standard C++ is nearly- but not exactly- a superset of Standard C. Since the C and C++ standards were developed on different schedules, they could not adapt to each other in a coordinated way.
Furthermore, C has kept itself distinct from C++. For example, there has been no attempt to adopt "simplified" versions of C++'s class types.
It is possible to write C code in the common subset of the Standard C and C++ languages -called Clean C by some- so that the code can be compiled either as a C program or a C++ program (i.e. write Standard C code so that it is acceptable to C++ compilers).
Since C++ generally has stricter rules than Standard C, Clean C tends to be a good, portable subset in which to write.
The major changes you must consider when writing Clean C are:
• Clean C programs must use function prototypes. Old-style declarations are not permitted in C++.
• Clean C programs must avoid using names that are reserved words in C++, like class and virtual.

WHICH DIALECT OF C SHOULD YOU USE?

Which dialect of C you use depends on what implementation(s) of C you have available and on how portable you want your code to be. Your choices are:
1. C99, the current version of Standard C. It has all the latest features, but some implementations may not yet support it. (That will change rapidly anyway.)
2. C89, the previous version of Standard C. Most  C programs and most C implementations are based on this version of C, usually with the Amendment I additions.
3. Traditional C, now encountered mostly when maintaining older C programs.
4. Clean C, compatible with C++.
C99 is generally upward compatible with C89, which is generally upward
compatible with traditional C.
Unfortunately, it is hard to write C code that is backward compatible. Consider function prototypes, for example. They are optional in Standard C, forbidden in traditional C, and required in C++. Fortunately, you can use the C preprocessor to alter your code depending on which implementation is being used-and even on whether your Standard C includes the Amendment 1 extensions-. Therefore, your C programs can remain compatible with all dialects.
If you are not limited by your compiler or an existing body of C code, you should definitely use Standard C as your base language. Standard C compilers are now almost universally available.
e.g. The Free Software Foundation's GNU C (gcc) is a free Standard C implementation (with many extensions).

AN OVERVIEW OF C PROGRAMMING

Let's do a quick overview of C programming.
A C program is composed of one or more source files, or translation units, each of which contains some part of the entire C program -typically some number of external functions-. 
Common declarations are often collected into header files and are included into the source files with a special #include directive/command. 
One external function must be named main(); this function is where your program starts(the entry point).
A C compiler independently processes each source file and translates the C program text into instructions understood by the computer(object code). 
The compiler "understands" the C program and analyses it for correctness. If the programmer has made an error the compiler can detect, then the compiler issues an error message. Otherwise, the output of the compiler is usually called object code or an object module.
When all source files are compiled, the object modules are given to a program called the linker. The linker resolves references between the modules, adds functions from the standard run-time library, and detects some programming errors such as the failure to define a needed function. 
The linker is typically not specific to C; each computer system has a standard linker that is used for programs written in many different (compiled) languages.
The linker produces a single executable program. which can then be invoked to run. Although most computer systems go through these steps, they may appear different to the programmer.
In integrated environments such as Microsoft's Visual Studio, they may be completely hidden.

Example

Suppose we have a program to be named aprogram consisting of the two C source files hello.c and startup.c
The file hello.c might contain these lines:
#include /* defines printf  */
void hello (void)
{
   printf("Hellol\n"};
}
Since hello.c contains facilities (the function void hello (void)) that will be used by other parts of our program, we create a header file hello.h to declare those facilities. It contains the line extern void hello{void};
File startup.c contains the main program, which simply calls function hello:
#include "hello.h"
int main (void)
{
  hello () ;
  return 0;
}
On a UNIX system, compiling, linking, and executing the program takes only two steps in a shell:
user@host:~$ gcc -o aprogram hello.c startup.c
user@host:~$ ./aprogram
The ftrst line(the part after the prompt -in italics- ) compiles and links the two source files, adds any standard library functions needed, and writes the executable program to file aprogram
The second line then executes the program, which prints: Hello!

Other non-UNIX implementations may use different commands. Increasingly, modern programming environments present an integrated, graphical interface to the programmer. Building a C application in such an environment requires only selecting commands from a menu or clicking a graphical button.


CONFORMANCE

Both C programs and C implementations can conform to Standard C. 
A C program is said to be strictly conforming to Standard C if that program uses only the features of the language and library described in the Standard. The program's operation must not depend on any aspect of the C language that the Standard characterizes as unspecified, undefined, or implementation-defined. There are Standard C test suites available from Perennial, Inc. and Plum Hall, Inc. that help establish conformance of implementations to the standard.
There are two kinds of conforming implementations-hosted and freestanding-. 
  • A C implementation is said to be a conforming hosted implementation if it accepts any strictly conforming program. 
  • A conforming freestanding implementation is one that accepts any strictly conforming program that uses no library facilities other than those provided in the header files float.h, iso646.h(C95), limits.h, stdarg.h, stdbool.h(C99), stddef.h , and stdint.h(C99).  
Freestanding conformance is meant to accommodate C implementations for embedded systems or other target environments with minimal run-time support. For example,such systems may have no file system.
A conforming program is one that is accepted by a conforming implementation.
Thus, a conforming program can depend on some non portable, implementation-defined features of a conforming implementation, whereas a strictly conforming program cannot depend on those features (and so is maximally portable).

Conforming implementations may provide extensions that do not change the meaning of any strictly conforming program. This allows implementations to add library routines and define their own #pragma directives, but not to introduce new reserved identifiers or change the operation of standard library functions.
Compiler vendors continue to provide non-conforming extensions to which their customers have grown accustomed. Compilers enable (or disable) these extensions with special switches.


Resources:

C A REFERENCE MANUAL : Samuel P. Harbison III, Guy L. Steele Jr.

Thursday, February 23, 2012

Source Version Control: Git

h

Sistemi di controllo versione

Non ci sono scuse per non utilizzare il controllo di versione dei propri sorgenti. Spesso si sente obiettare che nessuno nel gruppo di sviluppo ha il tempo di configurare i server e gestirli, inoltre gli sviluppatori non hanno il tempo di imparare qualcosa di nuovo perché sono oberati di lavoro.

A queste obiezioni si può rispondere che dovrebbe esserci nel gruppo di lavoro qualcuno dedicato proprio a configurare e gestire i server, perché se tutti i membri di un gruppo di sviluppo sono oberati di lavoro, vuol dire che un gruppo opera in emergenza, senza paracadute e con un piede sull’orlo del disastro. Quando ci sarà un errore o un problema, sarà difficilissimo ricostruire una situazione stabile o annullare una modifica che si è rivelata perniciosa.

In secondo luogo, per fortuna, non è così complicato usare un sistema di controllo delle versioni. Nella normalità giornaliera, infatti, si tratta solo di perdere qualche minuto ogni volta che il progetto ha raggiunto un obiettivo in scaletta e celebrare l’evento con un bel check-in, con la lista delle modifiche e degli obiettivi di business che sono stati raggiunti.

Ci sono circostanze in cui si deve realizzare una versione ad hoc di un programma, per uno specifico cliente, o si deve ricostruire lo stato della release consegnata nel 2007 per risolvere in fretta un problema, o si vuole tentare una strada nuova di sviluppo. Tutte queste domande hanno una risposta da parte di un sistema di controllo delle versioni.

Gli sviluppatori allo stato brado hanno solo la possibilità di conservare varie copie (e copie delle copie) in diversi livelli di aggiornamento e stabilità del software. Di queste copie si perde rapidamente il controllo. Inoltre questo sistema spreca spazio e espone al rischio di perdere dati. La conseguenza è che può diventare talmente complicato fare un piccolo aggiornamento puntuale su una consegna del 2007 che si è costretti ad aggiornare il cliente all’ultima versione,
magari con effetti secondari non proprio marginali, costi di intervento e fermo macchine.


Git
Vediamo una soluzione open source, di notevole versatilità: l’ambiente git. La motivazione per insistere su un software open source sta nel fatto che la  soluzione di minore attrito è certamente in un ambiente gratuito, facile da installare per tutti i sistemi operativi di uso comune, come Windows, Mac OS e Linux. Naturalmente, se si usa un sistema di sviluppo specifico, come Visual Studio, e si opta per la soluzione proprietaria corrispondente, come Visual SourceSafe, ci sono da aspettarsi semplificazioni nell’uso quotidiano e una maggiore integrazione con l’ambiente di lavoro. Comunque ai giorni magri una soluzione a costo nullo è sempre più eloquente al tavolo della direzione, soprattutto in tempi difficili come questi.

Una soluzione open source ha un vantaggio specifico anche quando si opera dal cliente, su macchine che sono responsabilità di terzi. L’installazione di un sistema open source non espone chi è responsabile della conduzione delle macchine a obblighi di licenza.



Un po’ di preistoria
Il moderno capostipite degli ambienti di sviluppo open source è Cvs, un software che nasce sulle ceneri di Rcs, un ambiente di controllo delle versioni del codice nato per lo Unix Bsd, il capostipite degli Unix a sorgente aperto.

Dall’insofferenza per le limitazioni del Cvs è nato il progetto Subversion, il cui nome fa omaggio non solo al controllo delle versioni secondarie ma anche al desiderio di sovversione che ha ispirato lo sviluppo.

Cvs, però, nonostante sia stato per anni il motore di archiviazione dei sorgenti della Apache Software Foundation e di parecchi altri archivi open source, ha sollevato parecchie critiche e, come accade normalmente nella comunità open source, le critiche hanno fatto nascere server alternativi, come Mercurial, un ambiente realizzato in linguaggio Python, e Git, un motore nato dalle esigenze particolari del gruppo di sviluppo kernel di Linux e di Linus Torvalds, persona che si occupa dell’integrazione delle modifiche presentate dai diversi collaboratori.

Un kernel si compone di decine di migliaia di sorgenti, che assommano un numero di righe di codice dell’ordine del milione. Facile convincersi che il compito non è dei più semplici, anche perché i partecipanti al progetto non operano fianco a fianco nello stesso laboratorio, ma sono sparsi per il mondo. Il modello centralizzato di Cvs non si presta facilmente a questa organizzazione, perché può funzionare solo se il repository dei sorgenti è ospitato su Internet e accessibile a tutti i membri, che integrano uno alla volta e aggiornano spesso la propria copia dell’albero.

Più spesso capita che gli sviluppatori non interagiscano così di frequente, ma scarichino una release stabile su cui compiono diversi aggiornamenti fino ad avere un insieme di aggiornamenti che completa una funzionalità applicativa ed è stabile abbastanza da qualificarsi per un’integrazione.

Il modello di Cvs, con un unico albero condiviso, fallisce in questo caso, soprattutto perché chi sviluppa una funzionalità complessa è costretto a decidere fra caricare con frequenza giornaliera modifiche non stabili, o lavorare senza controllo delle versioni su un albero locale, due strade egualmente  problematiche. Il problema si presenta sia che il gruppo di lavoro sia distribuito, sia che gli sviluppatori lavorino tutti nello stesso ufficio. Se si stabilisce la regola di mantenere stabile il repository Cvs per avere sempre una release testabile, si costringono i gruppi che hanno modifiche in sospeso a avere una macchina o un albero di sviluppo separato per ogni fase incompleta di sviluppo di una funzionalità.

Git nasce per risolvere questo e molti altri problemi di Cvs, come anche Mercurial, per questo è sembrato logico metterlo alla prova in un progetto che ha impegnato la maggior parte del secondo semestre del 2010.



Installazione
Git si installa scaricando la distribuzione da git-scm.com, il sito dedicato al programma. Per Windows ci sono due versioni, ma consiglio di scaricare msysgit, la meno invasiva. Ci sono due versioni di Git su Windows perché Git è sviluppato con un approccio tradizionalmente Unix alla costruzione di applicazioni, riciclando cioè il set di comandi di base particolarmente ricco e versato nel trattamento di testi del sistema più amato dai programmatori. Per questa ragione, Git non è un ambiente totalmente entrocontenuto, che realizza tutte le funzioni richieste, ma ha numerose dipendenze su un ambiente Unix esterno, su cui costruisce.

Dato che su Windows manca questo ambiente operativo, la scelta più logica è ricrearlo con una qualche emulazione. Ci sono due approcci al problema, quello dell’ambiente Cygnus, che ricrea la funzionalità di basso livello di un kernel Unix appoggiandosi su Windows e l’ambiente Mingw, che offre sostituti nativi Windows per i comandi Unix più comuni, come sh, vi, awk, wc.

Si tratta di due approcci abbastanza ortogonali: Cygnus mira a permettere di ricompilare senza modifiche sorgenti nati su Unix, Mingw si basa su porting di un set di comandi che permettono agli shell script più comuni di girare senza modifiche. Va da sé che l’ambiente che richiede di meno al sistema operativo e lo appesantisce di meno è il secondo. In più, dato che i comandi di Mingw sono applicativi nativi Windows che eseguono in un comune ambiente Windows, la compatibilità con il sistema operativo è intrinsecamente più a portata di mano.

In diversi mesi di collaudo, l’ambiente Git Mingw non ha perso un colpo. I comandi di Git funzionano correttamente, comprese le interfacce grafiche scritte in Tcl/tk. Si aggiunga che un set di comandi Unix facilmente a disposizione  permette anche di prendersi qualche facile soddisfazione, che con Windows non è a portata di mano. Per esempio il comando per calcolare il numero di righe di codice C#  a cui siamo arrivati, interessante per valutare i progressi del progetto giorno per giorno:
$ find . –name *.cs | xargs wc -l


Iniziare con Git
Per iniziare con il controllo delle versioni, si può aprire la shell di Git nella radice di un progetto Visual Studio e dare il comando:
$ git add .

Questo comando prenota un posto nell’indice locale di Git a tutti i file presenti nella directory corrente e nelle sue subdirectory. Si noti che questo aggiunge al repository tutti, ma proprio tutti, i file che incontra. Mentre noi siamo interessati ad archiviare e tracciare i sorgenti, non siamo, in generale, interessati a archiviare i prodotti di compilazione, come oggetti, eseguibili e file temporanei. Archiviare questi file appesantisce inutilmente il repository, aumentandone le dimensioni e allungando i tempi di lavoro in rete. Per evitare il problema, conviene compilare, prima del primo add, un file di nome .gitignore, che deve contenere su ogni riga le specifiche dei file da ignorare. Ecco un esempio di file .gitignore adatto per un progetto C#:
*.exe
*.pdb
*.baml
*.dll
*.tlog
*.cache
*.g.cs
*.suo
*.g.i.cs
*.lref
*.FileListAbsolute.txt
*.Cache
*.resources
*.lref
*.exe.config
*.trx
*.dat
bin
obj
.trx
*.Designer.vb
*.user
obj
Test References
*.vs10x

Dopo la add, non cambia nulla nel repository:
c’è distinzione fra comunicare l’intenzione di aggiungere un file e aggiungerlo effettivamente.
Per inserire in archivio i file sorgenti usiamo il comando
$ git commit –m "versione iniziale"

la richiesta di commit corrisponde alla memorizzazione definitiva, come in un database. Come in ogni sistema per il controllo dei sorgenti, una commit deve essere accompagnata da un elenco di motivazioni per le modifiche al codice e di risultati raggiunti, che è tanto più di aiuto quanto più è circostanziato e conciso. Un breve messaggio si può passare sulla riga di comando, con l’opzione –m. Se non si usa l’opzione –m si apre una finestra con l’editor configurato, tipicamente vi.

La descrizione di un commit non deve esser un componimento, ma una motivazione per le modifiche di una data giornata di lavoro, che servirà a ricostruire il percorso quando sarà riesaminata. Dopo la commit troveremo nella
cartella di lavoro una directory di nome .git che contiene l’archivio dei sorgenti in un formato codificato e compresso che si rivela piuttosto efficiente, tanto che un archivio di sorgenti con tutta la sua storia può avere la stessa occupazione di disco della versione di lavoro dei sorgenti appena estratti.

Avere un repository locale è utilissimo, perché uno sviluppatore ha sempre a disposizione il paracadute, cioè la possibilità di ritornare a una versione stabile eliminando con sicurezza tutte le modifiche alla base di codice che si fossero rilevate un errore di percorso. È anche molto utile poter ripercorrere la storia di un sorgente per ricostruire il cammino che lo ha portato in un certo stato, esaminando la lista delle modifiche e dei rispettivi artefici.




Una rete flessibile
Una delle particolarità di Git è che l’archivio locale non è un lusso che ci si concede fino a che non si decide di utilizzare un repository centrale condiviso, ma piuttosto un’abitudine che si conserva in qualsiasi configurazione. Ogni sviluppatore, infatti, ha un archivio individuale in cui lavorare fino al compimento di un elemento stabile di funzionalità da propagare nella release. L’archivio locale può essere sincronizzato con un archivio centralizzato quando lo sviluppatore lo ritiene opportuno.

Questa organizzazione ha numerosi effetti benefici sull’organizzazione di un gruppo ed è supportata con molta semplicità attraverso comandi che agiscono sull’archivio locale, come checkout e commit, e comandi che sincronizzano il repository locale con il master: push e pull.

Per esemplificare, partecipare a un progetto già avviato comporta una pull iniziale, un checkout, qualche commit e una push finale.
 Ci sono anche casi in cui un repository centralizzato non si può creare, per la resistenza di un cliente o problemi di rete, per esempio nel caso di un gruppo che lavora in parte dal cliente e in parte in laboratorio.

In questi casi è molto semplice scambiarsi le modifiche: basta fare un archivio dei sorgenti e inviarlo su un server comune o spedirlo tramite email. Per esempio, si può fare fronte a una completa mancanza di infrastruttura da parte di un cliente utilizzando il sistema Dropbox per creare una cartella condivisa in rete e replicata su diversi sistemi. Ecco un semplice esempio di shell script, compatibile con il sistema Mingw installato insieme a Git, per archiviare il repository Git in una cartella condivisa con Dropbox
$ tar cvf ../../../My\ Dropbox/archivio-git.tar .git

Osserviamo anche che non c’è solo la riga di comando per operare con Git, anche se l’uso della riga di comando è alla portata di qualsiasi sviluppatore. Git è corredato da due strumenti con interfaccia grafica: gitgui e gitk. Questi strumenti possono essere lanciati da riga di comando, o dal menu contestuale di Gestione Risorse, attraverso un’estensione della shell caricata dall’installazione.

Nonostante la grafica spartana, si può navigare la storia di un albero di sorgenti rispondendo a diverse domande come:
  • quali differenze ci sono fra l’archivio di sorgenti e i sorgenti estratti
  • quali file sono stati modificati a settembre
  • che aspetto aveva un dato file nella release 1.3 del 15 ottobre
  • chi ha inserito un if nella riga 300 e in quale occasione. 
Se pure la grafica non è delle più curate e l’interazione non sembra stata pensata in Apple, dobbiamo ammettere che gli strumenti visuali sono efficaci. Parte della colpa di un aspetto grafico sottotono va data al fatto che i tool sono realizzati in Tcl/Tk, un sistema piuttosto spartano, che però ha il pregio della portabilità, quindi l’aspetto degli strumenti è lo stesso su Windows, MacOS e Unix.

In conclusione, fatto salvo Mercurial, su cui non abbiamo ancora indagato, mi sento di raccomandare Git come un deciso passo avanti rispetto ad altre soluzioni open source, oramai limitate.


Uso
Git è un gestore di sorgenti, un oggetto simile a SourceSafe o Cvs, e che i suoi punti di forza sono:
  1. un repository per ogni sviluppatore
  2. un’operatività che si adatta a singoli, gruppi coesi e gruppi sparpagliati geograficamente
  3. la disponibilità del sistema su Windows, Linux e Mac OS
  4. una licenza open source, che toglie il peso dei costi di licenza dall’uso quotidiano
Useremo riga di comando, ma questo non significa che sia l’unico modo.  L’installazione base di Git crea estensioni della shell, che aggiungono voci al menu contestuale di esplora risorse, e installa due strumenti visuali per lavorare con il
repository.

In Windows la finestra di comando di Git si può aprire con un clic destro del mouse su Esplora risorse o lanciare dall’icona nel menu di avvio. Il primo metodo è migliore perché ci porta subito nella cartella di lavoro.

Si noti che Git, nella versione con MinGW quella che racomando di installare, è accompagnato da un ambiente di lavoro simile a Unix, anche se nativamente Windows. Tutti i comandi che mostro in questi esempi, quindi, possono essere eseguiti indifferentemente su Windows, Linux e Mac OS.


Come creare un repository vuoto
Questo è ovviamente il primo step, l’atto di nascita di un archivio locale. Questo archivio può diventare condiviso e migrare su un server in rete locale o Internet in un momento qualsiasi. Ecco come si crea un repository vuoto dalla riga di comando:
$ git init

Possiamo usare anche una delle estensioni della shell installate con Git per eseguire il compito direttamente da Esplora risorse. Conviene creare fin da subito un file .gitignore in cui specificare i file che non devono essere archiviati,
perché sono prodotti di compilazione e non sorgenti, quindi archiviarli e tracciarne le modifiche serve solo a sprecare spazio su disco e banda in rete. Ecco un gile .gitignore adatto per Visual Studio 2010
# oggetti e eseguibili
*.exe
*.pdb
*.baml
*.dll
*.tlog
*.cache
*.suo
# sorgenti creati dinamicamente
*.g.cs
*.g.i.cs
*.lref
*.FileListAbsolute.txt
*.Cache
*.resources
*.lref
*.trx
*.dat
*.trx
*.Designer.vb
*.user
*.vs10x
# cartelle create dalla compilazione
bin
obj
# cartelle create da nunit
Test References
TestResults


Aggiungere file all’archivio
Se interroghiamo Git sullo stato delle cose, con il comando git status otterremo una lista dei file nella cartella in cui abbiamo creato l’archivio, che per Git saranno tutti file di nuova creazione, dato che non sono in archivio. Ecco un esempio:
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use “git add ...” to include in what
will be committed)
##
.DS_Store
# build/
# images/
# pt.bat
Macintosh:PlayTune mico$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use “git add ...” to include in what
will be committed)
##
.DS_Store
# build/
# images/
# pt.bat

La pagina di messaggi di stato è abbastanza verbosa e ricca di suggerimenti, osserviamo da vicino alcuni messaggi.
  • On branch master sta a significare che l’archivio è posizionato sul ramo master, cioè il principale. Potremmo creare rami paralleli,per esempio per la versione lite del nostro prodotto o una edizione su misura per un cliente. In questo caso Git segnalerebbe quale ramo è quello su cui operiamo.
  • La lista di Untracked files è la lista di file che non sono in archivio. A regime, questa lista potrebbe essere vuota, quando tutti i file presenti sono menzionati nel .gitignore o sono parte dell’archivio. Si può anche decidere di aggiungere manualmente i soli file da tracciare, ma non è il modo da raccomandare, anche perché si perde il piacere di fare git add di una directory con la sicurezza che Git ignorerà i file già tracciati e i prodotti di compilazione, per aggiungere tutti e soli i sorgenti nuovi.
  • Nel caso di questo progetto, che è un’applicazione Java, c’è un unico sorgente, che si trova nella cartella src. La cartella build è una cartella dedicata alla compilazione, come è d’abitudine quando si usa ant come motore di compilazione. 
Ci sono anche altre cartelle che hanno a che fare con l’ambiente di sviluppo su Mac OS . Ecco il nostro .gitignore: 
$ cat .gitignore
PlayTune.app
PlayTune.icns
PlayTune.xcodeproj
build
untitled.xcclassmodel

ed ecco il risultato dell’aggiunta di tutto il contenuto della cartella all’archivio
Git:
$ git add .Macintosh:PlayTune mico$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm —cached ...” to unstage)
##
new file: .DS_Store
# new file: .gitignore
# new file: images/Ship01.pct
# new file: pt.bat
# new file: sin440.aif
# new file: src/PlayTune.java
#

Dalla lista dei file si vede che abbiamo un solo sorgente java, un immagine, un file audio e un batch file.


Aggiungere davvero i file all’archivio
Il commento Changes to be committed ci dice che questi sono i file che sarebbero messi in archivio se facessimo un commit, ma i file non sono ancora in cassaforte.

Git ci dà anche un altro consiglio: possiamo usare il comando:
$ git rm --cached  

per togliere file dall’elenco dei file da aggiungere.

Proviamo a rimuovere .DS_Store, un file di sistema di MacOS che archivia le personalizzazioni della visualizzazione della cartella in cui si trova, per esempio colore e posizione delle icone. Togliamo questo file dallo stage, cioè dal palco in cui si trova in attesa di fare la sua parte. Verifichiamo di nuovo la situazione
con il comando git status:
$ git status# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm —cached ...” to unstage)
##
new file: .gitignore
# new file: images/Ship01.pct
# new file: pt.bat
# new file: sin440.aif
# new file: src/PlayTune.java
#
# Untracked files:
# (use “git add ...” to include in what
will be committed)
##
.DS_Store

Il file .DS_Store non è più nell’elenco dei cambiamenti in attesa, ma nella lista dei file non tracciati. Un inserimento nel .gitignore ci leverà il pensiero di questo file.
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use “git rm —cached ...” to unstage)
##
new file: .gitignore
# new file: images/Ship01.pct
# new file: pt.bat
# new file: sin440.aif
# new file: src/PlayTune.java
#
# Changed but not updated:
# (use “git add ...” to update what
will be committed)
# (use “git checkout — ...” to discard
changes in working directory)
##
modified: .gitignore

Il file .DS_Store è sparito e il file .gitignore risulta modificato rispetto allo stage. Se usiamo, come suggerito, il comando:
$ git checkout — .gitignore

possiamo tornare alla situazione precedente.



Proviamo la gui
Lanciamo l’interfaccia visuale di Git dalla riga di comando, con
$ git gui

Oppure eseguiamola dal menu contestuale della cartella in cui abbiamo inizializzato l’archivio Git.
Notiamo che alcuni file sono preparati per la nuova revisione, sono elencati nella parte bassa della barra laterale sinistra e nella parte centrale della finestra. Osserviamo anche che il file .gitignore, che abbiamo modificato di recente, è segnalato fra le modifiche non preparate nella Gui, mentre appare nella lista Changed but not updated nell’output del comando status.

La ragione è che il file non corrisponde a quello che risulta in archivio, perché è stato modificato. Quindi occorre manifestare la volontà di sostituire la copia corrente con un comando:
$ git add .gitignore

oppure con un clic sul pulsante Prepara modificati della Gui. Adesso, il
nostro insieme di modifiche comprende tutti i file del progetto, nella sua versione iniziale. Possiamo inserire un messaggio nel campo di testo in basso e spedire la release nell’archivio.

Se non avessimo aggiunto anche il file .gitignore alla lista dei file preparati, avremmo conservato la versione precedente. Ci sono spesso buone ragioni per non consegnare tutto all’archivio. A volte abbiamo modifiche definitive e stabili da archiviare insieme a file in rapida evoluzione che preferiamo tenere fuori dall’archivio, almeno fino a sera. Con Git è semplice farlo. Naturalmente, conviene fare un checkin dei sorgenti modificati piuttosto spesso, in modo da non affastellare insieme una giornata di lavoro spesa in dieci compiti diversi in una sola transazione.


Esercizi di stile
Conviene anche fare un checkin separato per ogni singola funzionalità, senza affastellare insieme tre modifiche diverse. Bisogna pensare il log dell’archivio di sorgenti come un giustificativo delle spese per il tempo:
modificato questo e questo sorgente per questa funzionalità. Può darsi che in alcuni contesti l’archivio dei sorgenti e il suo log siano usati per giustificare il tempo speso dal gruppo o aiutare a compilare i cartellini, ma anche nel caso del singolo sviluppatore hobbista, il log è un modo di ricostruire i propri passi.

Se si vuole vedere un uso creativo del log dell’archivio dei sorgenti c’è chi si è preso la briga di creare animazioni fantastiche della crescita di un progetto, il risultato è il progetto gource su Google code. Il messaggio di checkin deve essere chiaro e sintetico:
la regola dovrebbe essere che ogni gradino compiuto di funzionalità dovrebbe essere un checkin a sé e avere un titolo esplicativo, per esempio “spostamento dei pulsanti nella toolbar”. Rispettando questa regola diventa semplice tracciare l’impatto di una singola modifica e, eventualmente, disfare una singola fase di lavoro in caso di pentimento. Naturalmente è inutile descrivere cosa è stato cambiato, dato gli strumenti permettono di vedere molto chiaramente tutte le righe di codice associate a un determinato checkin e lo stato prima e dopo di ogni sorgente.

Quello che è importante spiegare è perché si è fatto quel determinato intervento. Quindi non dovremo scrivere “spostato initdevice() da start() a init()” ma piuttosto qualcosa tipo “risolto il problema dell’inizializzazione del lettore di smartcard al
primo uso”.


La storia siamo noi
La storia di un file è molto utile e può essere usata in diversi modi, per esempio ci si può domandare in che situazione si trovava un dato file il venti settembre, il giorno di una demo di successo, cosa è cambiato da allora, chi ha modificato il file e in che occasione.

La funzione che permette di esaminare un file insieme alla storia delle modifiche è chiamata blame, che sta per biasimare o, meglio, dare la colpa a qualcuno. In effetti lo scopo primario è trovare chi ha scritto la riga di codice in cui il programma si è schiantato nell’ultimo test, ma naturalmente trovare il colpevole non è l’approccio giusto in un gruppo ben pilotato. Per entrare in questa funzione
si deve:
  1. lanciare l’interfaccia visuale di git, con il comando git gui dalla shell di Git, oppure il menu contestuale associato a una cartella in Windows. 
  2. Scegliendo Archivio e quindi Esplora i file di master, si apre il ramo principale dell’archivio di sorgenti, di cui ci viene mostrata la radice con le cartelle di livello più elevato. Navigando fra le cartelle possiamo aprire il file che ci interessa elaborare. Il sorgente sotto analisi appare con una lista di annotazioni che fanno riferimento alle diverse revisioni a cui è stato sottoposto.
  3. Passando col mouse sopra una determinata revisione, appare il messaggio di log, la data e l’autore. Facendo un clic sopra una revisione si naviga nel  sorgente visualizzando lo stato del file prima delle modifiche.
  4. Nella barra superiore appare una freccia che permette di navigare all’ indietro, come in un browser. La navigazione può proseguire a diversi livelli, fino alla prima stesura del file.
Le prestazioni di Git in questa analisi sono eccellenti: un file di 3500 righe di codice, con un paio di centinaia di revisioni si apre in un paio secondi e si naviga senza pause. Git si dimostra superiore ai sistemi che lo hanno preceduto in questo genere di analisi.

Esiste un altro modo di tracciare la storia di un progetto,
lanciando gitk dalla riga di comando, o scegliendo Visualizza la cronologia di master dal menu Archivio. Questo strumento mostra il log delle revisioni, insieme alla lista dei file modificati in ciascuna revisione, ma lo si può anche usare per osservare un insieme di file.

Bisogna schiacciare il radio button directory per abilitare la visualizzazione di tutti i file e quindi scegliere dal menu contestuale associato alle foglie dell’albero, cioè ai singoli file, la voce Evidenzia solo questo o Evidenzia anche questo. I tasti prec e succ permettono di navigare fra le revisioni che contengono modifiche ai file evidenziati mostrando il messaggio di checkin e le variazioni subite dai file evidenziati.


Conclusioni
L’elenco di comandi di Git è notevolmente lungo e le pagine di manuale sono parecchie, ma gli strumenti che abbiamo descritto in questa analisi sono sufficienti per analisi approfondite e il controllo fine di un piccolo progetto gestito su un singolo computer.

Naturalmente, si può andare molto oltre installando Git in rete, o aprendo un  account su github.com, il sito che ospita archivi Git gratuitamente per i progetti open source e a pagamento per i progetti a sorgente chiuso. Chi vuol seguire questa strada, naturalmente, farà bene a leggere più documentazione di quella che possiamo presentare in queste pagine.

La qualità del controllo e le prestazioni di Git ci hanno dato parecchie soddisfazioni nell’uso quotidiano. Certamente l’interfaccia è spartana e non all’altezza delle applicazioni native più sofisticate, ma stiamo parlando di applicazioni a pagamento. Esiste anche un’interfaccia integrata con Esplora risorse di Windows, che non abbiamo descritto qui, che deriva da un progetto sviluppato per Cvs di nome Tortoise-SVN. La versione per Git di Tortoise è certamente più gradevole da usare, ma abbiamo preferito ometterla per due ragioni:
  1. La prima è che è meglio avere un’idea dei concetti di base prima di usare un’interfaccia che sparpaglia i comandi in posti diversi con una logica coerente, ma che richiede di avere in testa il modello di come funziona il controllo delle revisioni. 
  2. La seconda ragione è che il progetto non è ancora molto maturo, anche se la revisione disponibile è stabile. Git nudo e crudo si è dimostrato perfettamente usabile, sempre molto veloce e all’altezza delle aspettative. 
Va senz’altro considerato in un piano di migrazione da Cvs e in una nuova installazione.

Monday, May 9, 2011

HSQLDB a DBMS written in Java. Install it and do it working in Linux

  • ...
  • Original code, based on in-depth study of database theory and the SQL Standard
  • Ahead of other open-source solutions in supported SQL features
  • The fastest overall open-source SQL implementation for small and medium sized databases
  • Three transaction control models, including lock based and MVCC models
  • Fully multithreaded
  • Compact code footprint
  • ...

"Install" HSQLDB(ever the latest release) in Linux

HSQLDB (also known as HyperStructuredSQL or HyperSQL ---its old name was Hypersonic or HSQL---) it's a portable RDBMS writting 100% in Java. It can be embedded with your application as well as can be used separately(offer Embedded and server modes).

So as i just say HSQLDB can also run as a database server, handling connections from different JVMs, and also as a purely in-memory engine. It has a JDBC driver and supports a large subset of SQL-92 and SQL:2008 standards.[1]
It is a a fast,[2]  and very small (around 1100 kilobytes in version 2.0) database engine that supports almost all features of a standard database system(offers both in-memory and disk-based tables). 
It comes with a small jar file hsqldb.jar (This includes the JDBC driver and the database engine) that can be found in:
hsqldb_x_y_z/hsqldb/lib 
folder. The hsqldb.jar  file must be put on the application classpath.

Installation
  1. Start by downloading the latest stable release, from SourceForge. The file to look for is in a directory called hsqldb_x_y_z and is named hsqldb-x.y.z.zip (Actually it's hsqldb-2.1.0.zip .  Possibly in future you can find it with a higher version number).
  2. Unzip the archive in your home directory
  3. You now have a directory called hsqldb-2.1.0 containing a directory hsqldb containing all files related to the DBMS. You will see the following contents as in Fig. above
  4.  Here "bin" directory contains some Windows(only) batch files(*.bat). 
Now we must "translate" Windows batch files(*.bat) in hsqldb_x_y_z/hsqldb/bin into the corresponding Linux shell scripts(for parallels between *.bat and *.sh  take a look in Advanced Bash-Scripting Guide). Let's go open our editor(i.e Geany) and do the following substitutions in the Windows batch files:
  • *.bat -->  *.sh
  • "\"      -->  "/"
  • "%"    -->  "$"
  • "@"    -->  "set +v" 
  • don't forget to control the correct conversion of line endings "CR/LF" --> "LF"  (in Geany go to Document > Set line endings > click on Convert and set to LF(Unix) )
  • rename the file filename.bat  -->  filename.sh
Let's look in the content of the runManagerSwing.sh  file (-- a Swing based GUI client(tool). For now the only one of interest for us) and control if all goes well:

runManagerSwing.sh(Notice that runManager(AWT based) do the same work although is weirdly to view)
cd ../data
set +v
java -classpath ../lib/hsqldb.jar org.hsqldb.util.DatabaseManagerSwing $1 $2 $3 $4 $5 $6 $7 $8 $9

Now i will  describe how got HSQLDB working:

How to run a standalone HyperSQL (hsqldb) Server

The most common use of HyperSQL is for in-memory operations, but could happen that persistent standalone server is required. Exist three ways (But here i examine two of them) to start the HSQLDB as a standalone server:
  1. Starting standalone HyperSQL with command line arguments: That's the best and fastest way of running a standalone hsqldb server:
    harrykar@harrysas:~/Activities/DBMS/hsqldb-2.1.0/hsqldb$ java -classpath lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:hsqldb/hemrajdb --dbname.0 testdb
  2. Starting standalone HyperSQL with configuration file:
    1. hsqldb.jar ( The most important file of the hsqldb RDBMS system ) in hsqldb_x_y_z/hsqldb/lib must be in our classpath
    2. Now check whether java in the (execution command) path or not. Just execute javac(included in the Java Development Kit (JDK) ) command and wait. If path has been set to java, then it will display some textual output showing command options.
    3. Now (in hsqldb directory) prepare a file named server.properties like this(Note that is only an example). We want create our DB in hsqldb directory that will contain four hemrajdb.* files after server execution:
      server.database.0=file:hsqldb/hemrajdb
      server.dbname.0=testdb
      1. Start the server. As below command executes you will see some output and a new directory will be created into current path named hsqldb in which you will find the following contents: hemrajdb.lck, hemrajdb.log, hemrajdb.tmp, hemrajdb.script   hemrajdb.properties
        harrykar@harrysas:~/Activities/DBMS/hsqldb-2.1.0/hsqldb$ java -classpath lib/hsqldb.jar org.hsqldb.server.Server
        [Server@1c691f36]: [Thread[main,5,main]]: checkRunning(false) entered
        [Server@1c691f36]: [Thread[main,5,main]]: checkRunning(false) exited
        [Server@1c691f36]: Startup sequence initiated from main() method
        [Server@1c691f36]: Loaded properties from [/home/harrykar/Activities/DBMS/hsqldb-2.1.0/hsqldb/server.properties]
        [Server@1c691f36]: Initiating startup sequence...
        [Server@1c691f36]: Server socket opened successfully in 8 ms.
        [Server@1c691f36]: Database [index=0, id=0, db=file:hsqldb/hemrajdb, alias=testdb] opened sucessfully in 589 ms.
        [Server@1c691f36]: Startup sequence completed in 598 ms.
        [Server@1c691f36]: 2011-05-08 22:19:06.930 HSQLDB server 2.1.0 is online on port 9001
        [Server@1c691f36]: To close normally, connect and execute SHUTDOWN SQL
        [Server@1c691f36]: From command line, use [Ctrl]+[C] to abort abruptly
      2. Once you created the database then you have to run the command in the same way as before with some extra arguments to connect with existing database e.g.
        harrykar@harrysas:~/Activities/DBMS/hsqldb-2.1.0/hsqldb$ java -classpath lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:hsqldb/hemrajdb --dbname.0 testdb
        [Server@6ef0eed6]: [Thread[main,5,main]]: checkRunning(false) entered
        [Server@6ef0eed6]: [Thread[main,5,main]]: checkRunning(false) exited
        [Server@6ef0eed6]: Startup sequence initiated from main() method
        [Server@6ef0eed6]: Loaded properties from [/home/harrykar/Activities/DBMS/hsqldb-2.1.0/hsqldb/server.properties]
        [Server@6ef0eed6]: Initiating startup sequence...
        [Server@6ef0eed6]: Server socket opened successfully in 3 ms.
        [Server@6ef0eed6]: Database [index=0, id=0, db=file:hsqldb/hemrajdb, alias=testdb] opened sucessfully in 583 ms.
        [Server@6ef0eed6]: Startup sequence completed in 587 ms.
        [Server@6ef0eed6]: 2011-05-09 00:17:54.641 HSQLDB server 2.1.0 is online on port 9001
        [Server@6ef0eed6]: To close normally, connect and execute SHUTDOWN SQL
        [Server@6ef0eed6]: From command line, use [Ctrl]+[C] to abort abruptly
  3. Starting standalone HyperSQL with Java Code: I refer the thrid way of starting a standalone HyperSQL server through java code here only for completeness sake.
    HsqlProperties p = new HsqlProperties();
    p.setProperty("server.database.0","file:/opt/db/accounts");
    p.setProperty("server.dbname.0","an_alias");
    // set up the rest of properties
    Server server = new Server();
    server.setProperties(p);
    server.setLogWriter(null); // can use custom writer
    server.setErrWriter(null); // can use custom writer
    server.start();

Access the Database trough a GUI client

  1. Now  you need to run ./runManagerSwing.sh file from /bin directory. Before start you have to enter some connection configurations and then press ok button to connect to the graphical user interface to database.
    1. You can enter also the following:
      Type: HSQL Database Engine Standalone
      Driver: org.hsqldb.jdbcDriver
      URL: jdbc:hsqldb:file:/path/to/your/app/demobase
      User: SA
  2. Now create a table and put some data into it (click Execute-button after copying the following to the text field):
    CREATE TABLE Bookmarks (title VARCHAR(50), url VARCHAR(255));
    INSERT INTO Bookmarks (title, url) VALUES ('Java Technology', 'http://java.sun.com/');
    INSERT INTO Bookmarks (title, url) VALUES ('HSQLDB 100% Java Database', 'http://hsqldb.sourceforge.net/');
    INSERT INTO Bookmarks (title, url) VALUES ('Apache Jakarta Tomcat', 'http://jakarta.apache.org/tomcat/');
    CHECKPOINT
  3. The first four lines are standard SQL. The final line is HSQLDB specific. To persist changes to your file after modifications, use the CHECKPOINT command.
  4. You can test that it worked, by executing this(you must get the Bookmarks table ordinated by title column as you can see below in the screenshot):
    SELECT * FROM Bookmarks ORDER BY title;
  5. Exit the manager.
Now you have almost four files /path/to/your/app (that represent our DB):
  • demobase.log, 
  • demobase.properties and 
  • demobase.script (and if you didn't exit the manager, you'll also have a demobase.lck file). 


How-to: changing user password on HSQL

In order to connect to any database you need to provide four properties:
  1. driver class
  2. URL to database
  3. user name
  4. user password
For HSQL it might look something similar to this:
driver=org.hsqldb.jdbcDriver
url=jdbc:hsqldb:file:app.db;shutdown=true
username=sa
password=
The default user ‘sa’ has empty password. This works fine as long as you don’t need to change the password for the default user.  But there are times when you need to change it. For instance Glassfish Application Server won’t let you create a data source with empty password. So the question remains – how to change the password of embedded database?
You have to log to the database as “SA” user and run below SQL script:
ALTER USER sa SET PASSWORD ''put-here-your-password';

There are many ways to do it. I will show you one of them:
  • Open your command line, go to folder where you keep your hsql.jar and run:
    java -jar url=jdbc:hsqldb:file:app.db;shutdown=true -sql “ALTER USER sa SET PASSWORD ‘put-here-your-password’;”
  • This yet still won’t work as system will inform you that you have not entered credentials needed for database manipulation.
    Failed to retrieve connection info for database ‘jdbc.hsqldb:file:app.db’: Please set up authentication file ‘sqltool.rc’
  • You need to create file sqltool.rc in the same folder where you keep your hsql.jar. This file will keep entry configuration for your database. Insert text below to your sqltool.rc file:
    urlid conn1
    url jdbc:hsqldb:file:C:/hsqldbs/app.db;shutdown=true
    username sa
    password 
  • Note that we gave this entry an id (urlid) called conn1. Now we can execute our SQL once again this time adding entry point urlid at the end:
    java -jar url=jdbc:hsqldb:file:app.db;shutdown=true -sql “ALTER USER sa SET PASSWORD ‘put-here-your-password’;” conn1
  • This time the connection will succeed and password of the SA user will be change.

A bit of details 

HSQLDB does not support full ACID transactions;

JDBC URLs

JDBC URLs for HSQLDB look like the following:
  • jdbc:hsqldb:file:filepathname : File-persistence
  • jdbc:hsqldb:hsql:DB_NAME: database server
  • jdbc:hsqldb:mem:DBname: in-memory only
By default, for file-persistence, the user name is "sa" and the password is "". See the HSQLDB documentation for further details.The database JDBC driver is class org.hsqldb.jdbcDriver
--------------------------------------------------
Todo: SqlTool HSQLDB's  CLI


Resources