This section describes the differences in philosophy and flavour
between SparForte and PHP.
A Smart Development System
First off, the SparForte is
more than just a programming language. With PHP, if you want documentation
generation tools or a debugger, these are all separate add-on packages. With
the SparForte, documentation management and debugging help are functions
of the interpreter itself.
Second, the SparForte is an ensamble tool designed to
work as part of a solution with a team of other development tools throughout
a business. That's what I refer to as ABEE and I've gone to great efforts
to keep the shell compatible with these tools and the international standards
they are based on. PHP stands alone and has many features that are incompatible
with other development standards.
So now let's look at a simple CGI program written in PHP
and the SparForte and compare basic features. This is a script written
in PHP and SparForte that returns a list of users from a MySQL database table.
Documentation by Design
Documentation. In the SparForte, documentation
is a part of the language by design. In PHP, documentation can only be typed in comments.
#!/usr/local/bin/spar
pragma annotate( "File: example.spar" );
pragma annotate( "Author: Ken O. Burtch" );
pragma debug;
pragma ada_95;
pragma restriction( no_external_commands );
procedure example is
REMOTE_ADDR : constant string := "";
pragma import( shell, REMOTE_ADDR );
begin
pragma debug( `put_line( standard_error,
source_info.source_location & ": started" );` );
cgi.put_cgi_header( "Content-type: text/plain" );
-- Database query
mysql.connect( "test", "dbuser", "xyz123" );
mysql.prepare( "SELECT username FROM users" );
mysql.execute;
pragma assert( mysql.end_of_query = false );
-- Return the data
put_line( "usermachine: " & REMOTE_ADDR );
while not mysql.end_of_query loop
mysql.fetch;
put_line( "username: " & mysql.value(1) );
end loop;
mysql.clear;
end example;
Figure 3: Documentation
Standards Compliance
In the SparForte, coding
standards can be specified as a part of the language. These provide guarantees
that a script meets certain conditions. With the restriction pragma, for example,
SparForte guarantees that there are no calls to operating system commands, meaning the
script is portable across operating systems. In PHP, standards can
only be enforced through peer review and there's no guarantees except my manually
examining the program.
#!/usr/local/bin/spar
pragma annotate( "File: example.spar" );
pragma annotate( "Author: Ken O. Burtch" );
pragma debug;
pragma ada_95;
pragma restriction( no_external_commands );
procedure example is
REMOTE_ADDR : constant string := "";
pragma import( shell, REMOTE_ADDR );
begin
pragma debug( `put_line( standard_error,
source_info.source_location & ": started" );` );
cgi.put_cgi_header( "Content-type: text/plain" );
-- Database query
mysql.connect( "test", "dbuser", "xyz123" );
mysql.prepare( "SELECT username FROM users" );
mysql.execute;
pragma assert( mysql.end_of_query = false );
-- Return the data
put_line( "usermachine: " & REMOTE_ADDR );
while not mysql.end_of_query loop
mysql.fetch;
put_line( "username: " & mysql.value(1) );
end loop;
mysql.clear;
end example;
Figure 4: Standards Compliance
Debugging Statements
In the SparForte, debugging
statements are a part of the language. They can be isolated and can be enabled
or disabled without editing the source
code. (Though in the case of a CGI script where command line options are not
configurable in the web browser, you may have to edit a single "pragma debug"
for a move to production.) In PHP, debugging statements must be controlled with
multi-line if's or deleted manually, both dangerous practices: the programmer runs
the risks of deleting the wrong lines, missing lines or adding typos to the source
code during moves to production.
In this example, removing "pragma debug" immediately hides all
debugging statements and asserts without further editing the source code.
[June 17/08: KB: Actually, since SparForte is a shell, you can probably
put the pragma debug in your .profile startup file on your development environment.]
#!/usr/local/bin/spar
pragma annotate( "File: example.spar" );
pragma annotate( "Author: Ken O. Burtch" );
pragma debug;
pragma ada_95;
pragma restriction( no_external_commands );
procedure example is
REMOTE_ADDR : constant string := "";
pragma import( shell, REMOTE_ADDR );
begin
pragma debug( `put_line( standard_error,
source_info.source_location & ": started" );` );
cgi.put_cgi_header( "Content-type: text/plain" );
-- Database query
mysql.connect( "test", "dbuser", "xyz123" );
mysql.prepare( "SELECT username FROM users" );
mysql.execute;
pragma assert( mysql.end_of_query = false );
-- Return the data
put_line( "usermachine: " & REMOTE_ADDR );
while not mysql.end_of_query loop
mysql.fetch;
put_line( "username: " & mysql.value(1) );
end loop;
mysql.clear;
end example;
Figure 5: Debugging
Variables and Types
In the SparForte, all variables
are declared and have a specific type (unless you explicitly use the universal
types, but these are intended for the command line). In PHP, with no declarations
and variables with constantly changing types, when you read a script you can never be sure if a variable
is spelled correctly or what type of data it contains. The widespread use of
associative arrays, which are accessed with string values, makes debugging even worse.
In this example, SparForte guarantees that REMOTE_ADDR exists, is a string,
and has a value in the environment or the script will not run.
#!/usr/local/bin/spar
pragma annotate( "File: example.spar" );
pragma annotate( "Author: Ken O. Burtch" );
pragma debug;
pragma ada_95;
pragma restriction( no_external_commands );
procedure example is
REMOTE_ADDR : constant string := "";
pragma import( shell, REMOTE_ADDR );
begin
pragma debug( `put_line( standard_error,
source_info.source_location & ": started" );` );
cgi.put_cgi_header( "Content-type: text/plain" );
-- Database query
mysql.connect( "test", "dbuser", "xyz123" );
mysql.prepare( "SELECT username FROM users" );
mysql.execute;
pragma assert( mysql.end_of_query = false );
-- Return the data
put_line( "usermachine: " & REMOTE_ADDR );
while not mysql.end_of_query loop
mysql.fetch;
put_line( "username: " & mysql.value(1) );
end loop;
mysql.clear;
end example;
Figure 6: Variables
The Small Stuff
The things everyone takes for granted
as evils we have to live with in contemporary programming:
Slash-Star Comments. Known for being un-nestable. Removed from SparForte by design.
Curly Braces. Known for being hard to read and debug. SparForte uses keywords for blocks.
Optional Blocks. Known for making code maintenance difficult. SparForte requires blocks for all compound statements.
Single and Double Quotes. In PHP, they're interchangeable and lead to many arguments on how to use them. In SparForte, each type of quote has a unique purpose and properties.
Readability. PHP relies heavily on punctuation symbols and shifted keyboard characters. SparForte favours simple English words for basic constructs (though it also has some common short-cuts if they are enabled, especially for working on the command line). Great for those 2 am debugging sessions.
Namespaces. PHP has thousands of global functions. SparForte divides standard functions into packages.
These scripts are roughly the same size. But are they truly
of equivalent value to a business?
The example used here was very short: there are many more
features in the SparForte to handle reuse, maintenance and correctness.
And many of these choices I cannot take credit for as they are based on the
software engineering language standard that SparForte is using. As programs
become larger, these features have an increasingly important role in keeping
down development costs and programming time.
Ken Burtch
extract from "The Lone Coder: Doing it Right with the Business Shell"
June 15, 2008
http://www.pegasoft.ca/coder_june_2008.html