Beginners Always Start In Confusion
I’ve been meaning to write a post on LinkedIn, so it’s only fitting that #MyFirstPost is about #MyFirstProgram. I wrote my first “real” program as part of a Computer Programming course I took in 10th grade. This was also when I discovered I had a knack for programming. In fact, I picked it up so well that I decided not to study Computer Science in college because I thought I already knew all about programming.
This was the final course project that we had to do all on our own and turn it in the few week before final exams. We could implement whatever we thought we could pull off, as long as it featured several of the key concepts we had covered, such as basic data insertion and retrieval, file management, error handling and interactive user interfaces. Suggested examples were things like programs for managing employee records, libraries, video rental stores or other inventory control.
As I could not imagine anything outside these examples, I chose a library management system. I had been to libraries, I knew how they worked -- how hard could it be? Libraries have books, you pick the ones you like, check them out, and return them when you’re done. Simple!
And so I started on my library management system. Today I’d put it in the cloud and call it bibl.io, but those were proto-Internet times, so it ended up being a desktop application that, in a fit of creativity, I called Library Management System?. I’m still not sure if I had fallen victim to or cleverly sidestepped one of the two hardest things in Computer Science.
Now here is where I date myself: I wrote this code in GW-BASIC. I chose GW-BASIC simply because that’s what we were taught in class. It wasn’t the latest programming fad (I’m not that old), but I suppose since we were beginners and the B in BASIC stands for “Beginner's”, the school board thought it was the right language for us. However a lot of applications written in the language had been shipped by then and it was still pretty widely used, as all legacy systems are. After all, it’s the same language that Bill Gates wrote DONKEY.BAS in. (Ignore those who deride the game; it was the great-granddaddy of the Temple Run and Subway Surfers.)
DONKEY.BAS gameplay preview, courtesy Jeff Atwood
One distinctive thing about GW-BASIC is that it used line numbers for flow control. No labels for your GOTOs and no names for your subroutines, only numbers. At least you could say naming is not a hard problem in GW-BASIC. Line numbers were typically incremented by 10s. This was so that if you needed to insert new statements between existing statements on say lines 30 and 40, you would add the new lines at 31, 32, 33 and so on instead of manually renumbering all subsequent lines. You could then run the “renum” command so all lines got renumbered to be increments of 10s again.
Of course, there were no functions, only subroutines. Also there was no way to pass arguments to subroutines, so guess what you ended up with.
Anyway, I created a file called LIBRARY.BAS and got coding. Like all novices, I started by copy-pasting snippets of code from examples and previous course exercises and plugging them together like Lego blocks. And then tweaking them iteratively to get things running. And then tweaking them some more to do things I wanted. Without really understanding what I was doing.
BASIC stands for Beginner's All-purpose Symbolic Instruction Code, but the “jokronym” then was Beginners Always Start In Confusion. We used to think it was a silly little joke, but it’s funnier in retrospect because it’s so true.
I had a simple UI and file management done soon enough since we’d covered those in exercises. But now I needed to figure out the data management to handle the library inventory. I used a sequential file to store the book records. I knew about databases (dB III+ baby!) but I had no idea how to use one programmatically.
I wanted users to find books by ID or name, but I certainly didn’t know about indexes then, so I guess I iterated over records in the file looking for exact matches. And when a copy was lent out, I updated the record and wrote the whole file out again. Performance is not an issue when you don’t know performance is a thing. And when your library has only 10 books.
I breathed a sigh of relief when I got that working. But wait! I can’t just give out books willy-nilly to random people. They need to be members! And don’t I need to know which member has which books? And can’t members have a limited amount of books? And don’t they need to return books by certain dates? And can’t they borrow different books on different dates, resulting in different return dates? And how do I know which members are returning books late? How do I calculate late fees? And wait, how about membership fees? I had more time, I should probably handle those...
I had discovered Scope Creep.
I think I managed to get barebones membership management working, but I gave up on date handling. GW-BASIC didn't provide any date handling support, naturally. And remember this was during the stone ages of the Internet, so no StackOverflow, or heaven forbid, even ExpertsExchange to copy-paste code from. The simplest tasks, like calculating a return date, confounded me. Turns out that date handling is not easy.
I am most proud of the UI aspect, though. GUIs were around, but only for expensive PCs, not the decrepit 286s at school, so we had to work with text-based displays. Hence those days GUIs were simulated by creative arrangement of special ASCII characters to form lines for borders and tables around text. If you've ever wondered why ASCII codes beyond 127 like║, ═, ╝or ╠ existed, this is why.
GUIs then looked like something like this, except without mouse input support.
The usual UI loop was to print out a menu with all the lines and text in the right places, accept user input, clear the whole screen, print out the new menu from scratch and wait for user input again. Aside from the tediousness of having to programmatically place each and every character on the screen, it was simple. But it was not very pretty as the whole screen blinked when this happened.
I wondered if there was another way and started experimenting… and this is where I made my first big discovery -- or maybe it was #MyFirstHack -- I realized that instead of using the CLS command that only let you clear the whole screen, I could print over only sections of the screen with spaces and thus clear specific parts of it. It seemed counter-intuitive that a command used to print text could be used to instead clear a screen, but it worked. I could hence keep some parts of the UI static and dynamically render others. I used this to maintain a static “main menu” in a “frame” on the left side of the screen and change the right side to display a different sub-menu based on whichever option the user selected.
I was thrilled! No annoying flashes and blinks! The user could always jump from one menu option to the main menu very quickly! My UI was sophisticated! It was non-glitchy and smooth! It was modern! It was cool!
And it was very wasteful of screen real estate.
The left frame was so wide that the right frame only got half the screen space. I discovered this when I tried to check out “The Lord of the Rings: The Fellowship of the Ring” from my library management system with its fancy UI and only got “The Lord of the Rings: The Fellowship of the R”. The “ing” was lost somewhere off the right edge of the screen. And it overwrote part of my right border as it did so. And when I cleared the right frame that border stayed broken. Argh!
Turns out that UI design is not all that easy.
I tried to solve that problem by word wrapping onto the next line, but it would then print over my pretty main menu in the left frame. Trying to fix that quickly devolved into an overly complex problem that would require overhauling all display logic. Turns out word-wrapping is not all that easy either.
I finally solved this the way we solve all such problems: I rigged the demo. I only populated by data files with book names shorter than 45 letters. I was hoping the graders weren’t going to test it with book names that long, and after many years of testing all kinds of UIs with inputs like “asdfasdfasdf”, I guess that was a pretty reasonable bet.
I barely turned in my assignment on time because I underestimated how much my scope creep would cost me. If I was a wiser person, I'd have learned two more lessons right there: a) features may increase linearly but complexity increases geometrically, and b) software project estimation is hard. I got a pretty decent grade, though I thought it deserved better just for the sheer coolness of my UI. I must have been upstaged those darned kids who programmed in fancy new languages like QBasic with newfangled things like functions and syntax highlighting and indentation. Pffft. Real Programmers use line numbers for flow control.
Unfortunately, that source code is lost to time, but to get a sense of what it was like you can check out the original source code for DONKEY.BAS. Coding horror indeed.
Still, looking back, I had great fun even if it was GW-BASIC. Mostly because I didn’t know any better. But today it gives me a sense of perspective; I can now appreciate how much easier software development is, these days. Not all things are better, though. There are technologies I'd rather not work with again and GW-BASIC is not highest on that list. Heck, I’ve coded in assembly and even that may not be at the top of the list (I'm looking at you, HTML/CSS/JavaScript.) GW-BASIC was good enough to teach me the basics (see what they did there?) of software development like Boolean logic, data management, cargo-cult programming and sweeping bugs under the rug.
Also, it helped me really appreciate this joke:
Futurama asserts its geek cred.
So yes, I wrote my first program in high school and I used BASIC. Despite Dijkstra’s dire misgivings, I think I turned out OK.
----------------
In response to: "Tell us about your first program" #MyFirstProgram
Head of Sales and Marketing Department
6 个月Kunal, thanks for sharing!
Lightbulb moments ?? - helping you explore what you really want and need in your life and work | LinkedIn | Career & Leadership Coaching | Networking | Redundancy | Climate Conversation | FRESK Facilitation | Vegan ??
7 年Great story, thanks for sharing!
操盘手 - 万科企业股份有限公司
8 年No
Servant Leader. Mother. Runner. Chief Data Officer at Genesco.
8 年Such a nostalgic reading! Reminds me of the good ol' days of 8086 programming when I thought that it was the most powerful thing on earth because it worked better than calculator memory with its sequential programming. Thanks for sharing!
.NET Contractor at Wood Group
8 年You are a natural story teller :)