That's a pretty strong title. And of course it is mostly hype. But I am strongly against many of Picaxe (Revolution Education) and Parallax products. The Parallax Basic Stamp products, and the copy-cat products like Pic Basic and Rev Ed's Picaxe products, are doing as much harm as good for the future of society. Let me explain why.
Our modern society is completely dependent on computer technology. The existence of this document and the fact you have access to it is a testament to that. Almost all of our communications, our finances, our education, our transportation, all depend heavily on computer technology. The computer hardware has advanced drastically in the last 30 years or so. The power and ubiquity are simply amazing. When I was a kid, a common dream was to have, in some far away time and fictional place, something like a Dick Tracy phone. Now, we have far surpassed that. There are two main technological fields driving these advances: computer hardware and software.
Hardware and software are closely related, but different enough to be separate branches of science and technology in daily work. The hardware continues to advance more or less as Moore's Law predicted 50 years ago. From a dozen or so transistors on a chip (integrated circuit) 60 years ago, to a billion or more now, the march of technology in the hardware field is almost unbelievable. It is huge and complex, but mostly straightforward to design. There are many tools that will take a collection of building blocks, put them together as the engineer desires, and make larger building blocks out of them. There are standards that make this simpler than it otherwise would be. It certainly isn't easy, but mostly it is manageable. When the inevitable bugs creep in, it makes headlines. Hardware is expensive. To make a new chip requires often millions of dollars in Research and Development, and then the use of a multi-billion dollar plant to actually manufacture. The companies making them take great pains, using simulations and other tools, to make sure the design is as close to right as possible before commiting to have it manufactured. The cost of mistakes is enormous, especially if they ship in a product. The Pentium bug of the mid 90s was a prime example.
Software, on the other hand, seems to be very simple. It is certainly cheap and easy to produce. That's a big part of the problem. Any kid with a PC and an Internet connection can download Visual Studio Express or Eclipse and start writing software. There are hundreds, probably thousands, of tutorials on the web to teach programming. Modern tools, like Visual Studio, will create a good portion of the application for you. (With really crappy code, by the way). It isn't hard to learn the basics of programming. And in a short time they can have their programs on the web, maybe on the Android application site. All at zero cost. The web is full of stuff like that. No engineering, no knowledge of software engineering best practices. Just hack away until it seems to work. Most of the time. Or some of the time. And release it into the wild. The demand for software has created a rich environment for that sort of activity, and overall the quality of software is rather poor.
None of that is to slight anyone (kid or adult) that learns to
program that
way. Even if they release the programs into the wild of the
Internet. I
think it is great. Programming is important to our future. The
hardware is
great, but it really doesn't do much without some software. And
many of those
people, especially the kids, will end up as the software engineers
that create
our future. That is how I first learned to program. And I am in
good company.
People like Bill Gates did much the same. Programming is fun. It's
addictive.
It's satisfying making a machine do your bidding. And it is
important for our
future. Unless you've been living on Jupiter the last ten years
(Mars has
probably heard, thanks to the rovers), you have seen the push on
STEM education.
There is a shortage of engineers in the US and many other places.
Especially
software engineers. And many of the ones that exist are, uh, less
than stellar.
I have interviewed some that amazed me they had finished school. And
these
were the ones that made it through the resume cull and phone
interviews.
Companies are being forced to do all sorts of things to attract the
talented
ones. Take a look at what
Google
and other similar companies offer their
employees. Microsoft
hires some of the best, too. But take a look at the
products from these big companies who go the extra mile to get the
best talent:
So what happens to those less than stellar software engineers? Well, there is a shortage, so they get hired by someone. If Google and Microsoft are churning out bugs with the best talent, what do you think these other companies are producing? What companies write your (and your bank's!) financial applications? Who are they hiring? What quality is their software? How many big companies have had their customer databases compromised? Apple. Sony. Home Depot. Target. That's just a few I can think of off the top of my head. Software is hard.
Having said that, I feel it is important to teach programming as
best we know
how. Fifty years ago computer scientists started pushing for better
programming practices.
Fortran
was recognized as bad, and new languages were
created to help with "structured" programming practices. New ways
to program
better are being created all the time. We should pay attention and
teach
new programmers the best ways we know, and encourage them
When the discussion of programming comes up, people often tend to
demonstrate
their programming ability by telling all the programming languages
they use.
Unfortunately, that says very little about their programming ability.
Programming is about problem solving. There are different paradigms,
or
approaches, to solving most any problem. One's ability to program is
shown by how well they solve problems. A program to solve any
particular
problem can be written in any language, using any paradigm. However,
different languages are more suited to certain paradigms. Using a
language
for a paradigm it isn't designed or suited for can be extremely
painful, but
it can be done. It is actually rather common to use some
object-oriented
techniques with
C,
which is
So why does the language matter? Because to effectively use the language as it was intended and be productive, you have to follow the paradigm it was designed for. Each individual language will support certain features that are designed for the paradigm it is intended for. To be effective, you have to place your mind into the mindset of that paradigm. The language "guides" your thought process to some extent. Forcing a language to another paradigm can be done, but it is not easy or natural. Think of running a marathon in work boots. In short, if all you have is a hammer, everything looks like a nail.
In the early 50s, computers were still quite new and rare. Programming techniques were still being figured out, but the future held great promise. All programming was done in machine language. Assemblers were just being developed. Some programmers realized they kept writing the same program pieces over and over. So they created a way of putting those pieces into libraries for reuse in many programs. The next step was to write another program that would allow you to "program" with "formulas" as they would be written, and translate that into a program that used those library routines. Then, since computers are useless without being able to make decisions and change the flow of control, various means of "branching" were added. Before long, they had created a "high level language" that "compiled" formulas into machine code. They called it "Formula Translation," or just FORTRAN for short.
By the early 60s FORTRAN reigned supreme in science and engineering. Computers were more common and many universities were teaching science and engineering students how to use them, which at the time meant how to program them. But Kemeny and Kurtz decided Fortran was more complicated than necessary, and decided to create a new language, based on Fortran but simpler, to teach introductory progamming.
The new langauge was stripped down. It was made as simple as possible. Now, take this in perspective. Fortran of the early 60s was a VERY simple language compared to modern languages, and this new language was made even simpler. But it still had much of the flavor of its inspiration Fortran. Fortran was one of the first high level languages, and it was created before good programming practices had been devised. By the early and mid 60s many computer scientists were realizing the dangers of the Fortran programming model. But users were high on the power of the computer, and too inexperienced to know better, so they kept using it more and more. It didn't help that Fortran was the "standard" language and often the only one available on the computers they had access to. The new beginners' language brought along most of the bad parts of Fortan and to some degree made things even worse. But it worked, and was popular, and most important to our story, was simple. The new language was named, in the style of the time, "Beginners' All Purpose Symbolic Instruction Code," or BASIC.
Over the next ten years or so, BASIC became very popular. It was extended in all sorts of directions by many companies for their own computers and uses. There was no real standard. Everyone did things differently. But it had a few traits that were very common. Most implementations were interpreted (see below), used GOSUB and GOTO instead of proper procedures/functions/subroutines, required line numbers on ever line, had only global variables (no local variables), and had minimal support for "structured" programming that was becoming the paradigm of choice.
Knowing how a typical implementation of BASIC works, and why it is built that way, will be helpful in understanding the rest of this discussion. Now, it must be said that there are literally hundreds (thousands?) of implementations of BASIC, and they are done in lots of different ways. The ones we are interested in fall into a certain category, which was made popular in the mid 70s when personal computers appeared. The new personal computers were very simple and had minimal resources, so they were very constrained in what they could support. It was something of a miracle that they could run any type of high level language, and I hold nothing against Microsoft or the other companies and individuals for producing the type of BASICs they did: it was really all that was reasonable at the time.
A computer can only execute programs in "machine language." The machine language is specific to a certain (type of) processor and is different on different machines. It is very low-level, and typically has very simple "instructions" that do very basic things like move a value from one place to another, add two values, "and" one value with another, and transfer control to a different place in the program, possibly based on some condition, like a certain value being present. Machine language is rather tedious and time consuming, so we use "high-level languages, like BASIC, C, or Python. But the computer doesn't "know" how to run programs in those languages: they must somehow be translated to machine language.
There are two basic methods of translating:
interpreting
and compiling.
A compiler goes through the entire program in the high-level language
and converts all of it to machine language at once. After all of it
has been converted, it can be run directly. Compiling only has to be
done once, unless changes are made to the program. From then on it
can be run as many times as needed, directly executed on the
processor, without any conversion steps. Often, with a good quality
compiler, the resulting program will be faster even than the
equivalent
program written in assembly (machine) language by a human. The other
method, interpreting, "converts" the program to machine language as it
is running. Usually, it never actually produces any machine language
program, but instead has a "library" of machine language programs
built in. As the interpreter scans through the program "running" it,
it looks up each command of the high-level language and runs the
appropriate library routine to perform that action. The process is
normally
Almost any language can be either interpreted or compiled, but often any one language is most often done one way or the other. C, C++, Ada, and others are almost always compiled. BASIC is most often interpreted. In some cases, arguments arise about whether a language is interpreted or compiled, ie Java. Why? Typically because the language is compiled to a machine language for a machine that doesn't really exist (sometimes called bytecode), then the resulting program is interpreted, much as a simulator for one computer running on another. There are more variations, but these three cases cover most of what's important. If you are in the mood for a fight, tell a Java programmer you don't like Java because it is interpreted.
As I mentioned, BASIC is most often interpreted. The ones we are focused on (BASIC Stamps, Picaxe, early Microsoft and other personal computer versions, and similar) are. But if interpreting is so slow, why do we use them at all? It turns out there are some very good reasons, and some not so good reasons.
To quote
David Gries in the classic but dated
"Compiler Construction For
Digital Computers,": "Interpretation lends itself to an
educational
environment, where most of the time is spent debugging source
programs."
The process of compiling usually throws away a lot of information that
is useful when debugging. An interpreter necessarily keeps most of
that
information (ie variable names, the source code, etc) and has easy
access to it while running, since it needs it to interpret the
program.
So ease of debugging is a big plus for an interpreter.
When using a compiler, one must go through the edit, compile, link, and maybe some other steps, then run. The compile and link steps may be time consuming and may work for a while then produce a cryptic error message. With most interpreters, especially BASIC, you simply edit and run. Typically, the editor will not allow some syntax errors, and others will be much easier to find at runtime. The development process is speeded greatly. Interpreters are much easier to develop with.
Another reason is space. The process of compiling takes a lot of memory in one form or another. There must be room for the source code, the compiled program, and various versions of an "internal form" of the program, all at the same time. On computers of the late 70s, there often simply wasn't enough memory available to run a compiler. The interpreters used then (Microsoft BASIC and similar) simply converted each line as it was typed in to a "tokenized" form, with each word (ie "IF", "GOTO", "GOSUB", "THEN", etc) represented by a single byte. There was no input held in memory, the "tokenized" form was all that needed to be stored. That made them very space efficient. The tokenized form also made the code that scanned and interpreted it much simpler, since it only had to recognize a single byte instead of a variable length string of characters. That again saved space (and time), and was a huge advantage on those computers. It may be an advantage on some of the microcontrollers with BASIC today. Then again, it may not.
Another reason to use an interpreter is that it is easier to write
and get working than a compiler. That may have been an advantage to
someone trying to create
So, let's walk through the process of interpreting a BASIC program. First, the user types in the code. In old personal computer BASICs each line would be tokenized when [ENTER] was pressed, and syntax errors on that line reported. With most newer versions, the entire program will be tokenized and checked after it is complete and the programmer tries to run it.
Once a syntactically correct program is tokenized and stored, the actual interpreter portion begins scanning at the first token. The token is examined and looked up in a table. The table points to a subroutine to run to handle that token. If any math expressions are expected, the subroutine for that token extracts the operands and operators from the list of tokens and performs the indicated operations. The results are stored or compared as needed, then the next token is scanned and interpreted. If a branch (GOTO, GOSUB, IF, THEN, etc) needs to change the current location of the program, that is done as well. The fetch token, interpret, repeat cycle goes on until the program completes or encounters an error. All in all it is pretty simple and relatively efficient, especially with space. Small and simple were the necessity in 1977. With many small microcontrollers today, like a PIC, it would seem to be the rule now. But we will come back to that.
We have looked a little at how and why early microcomputer
BASICS worked.
Microsoft BASIC was by far the most common,
but there were others that were quite popular. Almost all of
them worked as I described above, for the reasons I listed. It
was, to some extent, almost a miracle that
Those early micro BASICs were very limited by necessity. They had much less capability than most of the minicomputer and mainframe BASICs of the same time period. But they worked, and were often the only alternative to machine/assembly language on the small computers of the day. The language was terrible looking back, but we didn't know any better and were glad it existed.
Around the same time, in the late 70s, the microcontroller as it currently exists began to appear. These were small and simple microprocessors intended to be used for controlling devices rather than as the CPU of a computer. They had part numbers like 8048, 8051, 8073, and others. They typically had a CPU, I/O, some peripherals, some RAM (64 to 256 bytes), and often ROM (not flash or EEPROM, and usually not even EPROM) on board. They were billed as single chip solutions and were very popular. But generally they had to be programmed in assembly language. And since the processors were so simple, that was often rathe difficult. The popularity and ease of use of BASIC made it attractive for use on these small processors when being used for simple control functions. And some of these chips with very simple BASIC interpreters programmed into their ROM began to appear. The two biggest were the 8073 SC/MP from National Semiconductor and the 8052-Basic From Intel.
These chips, especially the 8052 were rather popular. The 8052
continues to be, even though I believe it is out of production.
You can download the binary file for the BASIC in the 8052,
buy a modern version of the 8052 with flash memory, and program
the interpreter into it. These solutions were rather unique
and mostly unmatched in today's market. They had the
Now that we have escaped the 70s, let's move to the Basic Stamps.
It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.
Before I start bashing the Picaxe and friends too bad, let me say that I think the BASIC Stamp, the Picaxe, and the other similar hobby-oriented development systems have done a lot of good. They have made it possible for people to do things they likely would not have been able to do otherwise. Many people have created some really nice projects with them. I am sure they have brought people into careers they would not have gone into without an introduction to these products. And, of course, they are fun! OK. Nice time is over. Let the bashing commence!
Around 1959 or so, a new programming language very different from Fortran was invented. Instead of being designed ad-hoc as features were deemed to be needed, it was designed from the ground up to make programs better. Why? It had already, by 1959, been realized that the way Fortran encouraged (and demanded!) programs to be written was bad. A few of the characteristics that made Fortran bad:
Fortran (and COBOL, but that's another story) was the enemy, ALGOL the up and rising star with structured programming as the battle cry, and when BASIC appeared in 1964 it was considered a toy. BASIC was based on Fortran and had almost all the same problems and limitations, but was less powerful. For the next 20+ years it was hard to find any writing on programming that didn't include the term "structured programming."
It is quite likely you have never heard of ALGOL and never heard
the term structured programming? Why is that if they were so
great? Well, ALGOL itself mostly faded away, but is still
available. More interestingly,
Why is structured programming a "Good Thing?" The short answer
is that it breaks a program into small, individual pieces that
are more manageable than a single large chunk. Large computer
programs are by far the most complex artifacts of the human race.
One measure of the complexity of a program is "execution paths."
Any time a program runs, it will follow some path through the
code. That path will likely change depending on the input to
the program. That is what makes computers useful. The program
makes "decisions" using flow control statemens like "IF" to
decide which path to take. With every decision statement that
can have two different choices, you
BASIC, the bastard child of Fortran, normally doesn't provide facilities for structured programming. Global variables and incomplete subroutine structure make it possible to access any part of the program from anywhere else, and impossible to guarantee a module's isolation from other modules. Get ready to test a few million execution paths if you write more than 100 lines of BASIC
Enter, around 1991 or so, Parallax and the BASIC Stamp. Parallax was a producer of PIC development tools in the 80s and early 90s. Somewhere along the line they came up with the idea (not really original, see above) of putting a BASIC interpreter on a small PIC chip. Thus was born the BASIC Stamp.
The PIC chip used was very small, simple, and cheap. It had very limited resources. The ROM (or eeprom or whatever) wasn't large enough to hold an entire BASIC language system. But it could hold the part that interprets the tokenized language. So Parallax put the rest of the interpreter, the part that checks syntax and tokenizes the code, into a program that runs on the PC and downloads the tokenized version to the BASIC Stamp. There also was no room on the chip to hold the tokenized BASIC program, so an external eeprom chip was added to hold that. Even with these concessions the BASIC language was extremely limited and simple. Even by the standards of early PC BASICs. But it was quite popular and spawned many copycats. It made microcontrollers easy to get started with and opened many doors. It introduced a couple of generations of new hackers to the wonders of microcontroller powered projects. But it also introduced them to programming using techniques known to be bad forty to fifty years earlier!
There were various versions of the BASIC Stamp released over the years, and they are still in production and being sold. To their credit, Parallax has moved on to better and more powerful solutions like the Java version of the stamp and the Propeller with it's spin language. But the damage is done.
Fast forward a few more years and Revolution Education introduces
the Picaxe. It is essentially a copy of the BASIC Stamp all on
one chip. It simplifies some things by using a more powerful
PIC chip. There are various versions, from 8 pins to 40 pins.
They store the tokenized program in on-board flash memory,
removing the need for an external eeprom. The interpreter is
still on-board and still requires a PC program to tokenize the
source code and download it. But the language is almost a
direct copy of the older BASIC Stamp! Here we are, fully fifty
years after ALGOL was created, and 20 years after structured
programming became so accepted as to not require mention,
introducing a product to teach kids (upcoming programmers!)
methods
"Well, the PIC chip is limited and can't support a better
language. You said so yourself." I can hear you saying that
now. It can't support a better
The first "large" program I ever wrote was an assembler for the Intel 8080 processor. I wrote it in Microsoft BASIC running on a 2.5 MHz Zilog Z80 with 64K of RAM split between the programs and use as a disk drive. The BASIC had required line numbers. It was painful. The second large program I wrote was a "preprocessor" that allowed me to do away with the line numbers and use "labels" only where I needed them in the program instead of the line numbers. That was a big improvement. The point is, with a modern PC with Gigabytes of memory and billions of operations per second, a preprocessor/compiler can convert almost any language we want to use into the tokens the Picaxe can interpret. A compiler doesn't have to compile to machine language: there are numerous compilers that convert from one high-level language to another. Since preprocessing (tokenizing) is already being done by the Picaxe "editor," it could just as well do more work and convert a much more modern and more structured language to the language the Picaxe can understand. Better yet, either create a more appropriate interpreter on-board the Picaxe or simply compile to machine language. Although in the latter case we would lose some debugging. But the PC can hold on to the data that the compiler doesn't include in the downloaded code, as is done with most embedded development systems. But instead, Rev Ed chooses to continue pushing and teaching harmful practices. I don't fully agree with Dijkstra's comment about BASIC programmers, but I certainly agree in principal: it is much harder to teach someone proper programming after they have learned on BASIC. I know that from my own experience. Is this what we should be teaching the next generation of programmers who will create the next phase of our electronic society?
What alternative(s) are there? That's a very good question. Unfortunately I don't have a really good answer. But here are some thoughts.
The biggest draw of the Picaxe (and relatives) is ease of use. That's a seductive drug. But like other drugs, it has long-term effects that are bad. We need an introductory language and system that is nearly as easy to use, but without teaching bad habits. There has been some work done along those lines, but nothing has caught on that is really suitable.
Some might say Arduino. That's better, but it isn't the answer. C, and C++, or the bastard combination of the two that is Arduino, isn't right for beginners. Although C is the standard language for embedded work among pros, it is full of traps and difficulties for beginners. My thoughts on Ardunio are here.
Netduino is another option. It (and similar dot net embedded solutions) bring much of the power of the .NET framework to embedded programming. But it is large, slow, full of many of the traps of C, and still rather complicated.
Forth is another option that was used quite a bit in the 70s
and 80s. It is
still somewhat of a cult language, and very powerful. It is
FBasic was a competitor to the BASIC Stamp in the early 90s. It used somewhat "better" version of BASIC with some functional programming ideas added. It is now gone.
emBasic is a language I am developing that is intended to be a structured and compiled version of BASIC. The idea is to keep the "flavor" of BASIC and the ease of use, but make it more modern. It is a long-term and ongoing project. Even when (if?) I complete it, it is unlikely to catch on. I don't have the resources of Revolution Education, Arduino, or Parallax to make it succesful.
There are other options, most of which are even more obscure than the ones I have listed. For now, my recommendation would be to learn C as used on embedded systems. Not Arduino, with it's contrived and bastardized version. But real, honest to goodness C. Atmel Studio is a good way to do that. And you can use it on Arduino (compatible) hardware. At least there is a lot of help available on the web. The situation is bad, but it will get better. Someone's good idea will eventually catch on. For now, we use what we have.
The future is a connected computerized one. In my lifetime I have seen the computer go from a crude, expensive, large device that was only seen in movies or referred to with amazement my some TV reporter, to being ubiquitious in almost every trinket we buy for three dollars or more. We can reach in our pocket and carry on a video call with nearly anyone in the world at any time. But it isn't all roses. Almost daily there are news stories of how some bug or vulnerability in some software has caused people to lose their money, their privacy, or even their lives. Expensive rockets and spacecraft have been lost because of poor programming. People have even lost their lives in cars controlled by poorly programmed computers. As society becomes even more computerized, what's next? It is important that the next generation of software engineers are taught best practices from the start. It's time to quit teaching them the methods that we knew were dangerous fifty years ago. Let's put forth the effort needed to make the introductory products what they should be: good, sound, educational and productive tools using modern software engineering techniques. Let's get rid of the Picaxe.