Visual Programming Language, Take Three

Over the last year, I’ve written two pieces reflecting my thoughts on the programming language I’d like to see. This third piece reflects my evolving views on how I’d approach it.

Why This Visual Programming Language

There’s no shortage of excellent programming languages out there, and there’s no point to adding another one to the mix if it doesn’t add anything. To that end, there are some short-comings that I’ve encountered that this fictitious language would address.

Existing Languages Are Inaccessible

Lots of people today use tools like Excel or Access without even thinking about it. We’re talking about specialized programs that through intuitive design put very complex operations at the disposal of a user. It enables people to do things that were previously the domain of experts.

Excel hasn’t displaced the need for statisticians and graphic artists, but it has empowered users to capture some of their domain for their own work. Programming languages don’t have a widely accepted analogue. For kids, you have cool application-specific projects like Lego Mindstorms  and Alice, but there’s nothing really quite as accessible for general purpose use.

This fictional language seeks to address that gap. To make programming as accessible and as painless as any modern spreadsheet program. This is why it’s visual, to avoid reliance on memorization and to provide an intuitive graphical cues. So when I say existing languages are inaccessible, I don’t mean to those that have a personal interest in programming. I mean to those that don’t have an interest but would benefit from its use were it easy enough.

Modern Computers Discourage Writing

Computer usage has shifted from mainframes, to minicomputers, to microcomputers, to tablets and smartphones. Programming languages are rooted in having access to a keyboard, but that’s no longer true with many computers in use today.

This language caters to those new platforms by greatly reducing how much text needs to be inserted to dictate logic. Instead, it’s very much grounded in having a pointer or touch screen.

Getting The Big Picture

A big part of my time as a programmer is devoted to maintaining software. When I do that, most of my time isn’t actually spent writing new code. It’s spent looking through thousands of lines of jargon to understand what’s already there.

Programmers can structure their code to ease that burden, but many do not. That results in loads of wasted effort for whoever inherits that code. Programming languages can go some way into enforcing a structure, like Python’s use of indentation to define code blocks. I believe that a visual programming language could further enforce clarity by way of a flow chart representation.

The trick then is to keep the flow chart simple, and unencumbered by details irrelevant to the scope you’re interested in. This is where this fictitious language would distinguish itself from existing visual programming languages, such as LabView’s G. It would do so by using a tile-based environment, by making use of an infinite canvas with stepped zoom levels, by having the presentation of connectors take a page from the likes of SimCity’s roads, by automatically hiding details irrelevant to the presented scope.

Concurrency Should Be A Language Feature

All of the programs you’re running on your computer right now are doing more than one thing at the same time. Yet none of the big programming languages today have support for running many things at once built-in, Google’s Go aside. Instead, you have to invoke libraries and do a whole bunch of legwork.

We’ve reached a point where this micro-management should be invisible for those using a high-level programming language. A flow chart based programming language makes that implicit. Any set of interconnected blocks can run in its own lightweight thread. Channels can be the connections between these sets of blocks. Any split, where the output of one block goes into two separate blocks, could launch new lightweight threads. Wait conditions are where the output from two separate threads are likewise coerced back into a single block. You get the idea.

Don’t Forget Existing Languages

I think that a short-coming of existing visual programming languages is that it’s seen as all or nothing. It either has to be all visual, or it’s all text. Yet there are things for which presenting everything as a series of visual elements impedes clarity.

For instance, I once saw an undecipherable diagram in LabView’s G, that was more or less just a few multiplications. A single line of Python would have been far less opaque. I think there has to be a place for a text-based programming language in a visual environment.

The blocks in this fictitious language would therefore be made up of more blocks, or the code of a text-based programming language. That brings me to the next distinguishing characteristic of this made-up language.

Piggy Back on Success

A programming language is only as good as the libraries written for it. That’s a big reason why I suspect Python has been such a success in the research domain over Ruby and why C++ is still favoured despite the rise of Go.

That also speaks to a problem with many fancy new programming languages. It’s all great to have easily understood code, but if there’s nothing for that code to do, then it’s not much use beyond a learning exercise.

Thus not only is it important for this fictitious language to have a text-based programming language to back it (see previous point), but it has to be one that’s well supported. To that end, this project would be built around Python. Each of the visual elements on screen would in fact correspond to a Python object, and it would be Python objects that’s passed around by the connectors.

This also has the effect of reducing how much work has to be done to make this language useful, because implementing a standard library is no longer a requirement. Instead, Python’s existing libraries can be used, and wrappers around them can be added over time.

High-Level Standard Library

Computers do so much more now than they used to, yet today’s programming languages are still rooted in a period where the most complicated thing someone did was read files and talk to a device. There’s some good reasons for that, like retaining a standard library that can be fully implemented irrespective of target.

However, this language is for a use case where the user just wants to play a sound without having to figure out the logistics of how to make that happen. It’s a language for people who just want to pull data from a web page. That’s at a far higher level than current standard libraries, and this programming language should  facilitate that.

However, this is an unachievable goal – since computers do so much more, so much more code is required to let them do that. So you have to pick and choose. Perhaps taking cues from what the Qt and Python folks have implemented in their respective libraries would be a good starting point. That and looking at the now defunct Yahoo Pipes and the Tasker mobile app. The end goal nonetheless is to reduce modern activities to a handful of blocks chained together in the IDE. Like automatically uploading GPS coordinates to Twitter.

Implementation Concepts

In the last section I talked about what needs were unmet that this visual programming language would address. In this section, I’ll cover how a bit about the internals.

Blocks And Connectors

The basic visual experience for the programmer would be to grab blocks from a pool, and to connect them together to define how the application would behave. Like a flow chart. So one block might be to read a file, which would output the contents of that file. That would then be chained to a block that parses the contents of that file and spits out text, etc.

There could be many independent sets of blocks visible, which would execute concurrently. When the last block would execute, the program would exit. Blocks could have multiple connectors in, the equivalent of multiple function arguments, and would only execute once all of the input connectors would have furnished a value.

Tile-Based

The IDE for this language would be tile based, with a block taking up a full tile. The connectors would also consume a tile, though you could have multiple connectors sharing a tile. This is to prevent messy diagrams that inhibit clarity when things are all at random offsets from each other.

Blocks Are Monochrome Symbols On Top Of A Base User-Defined Colour

The blocks show up in a tile as having a background, which defaults to a given colour but can be changed to anything the programmer wants. On top is a symbol that represents the functionality of the block, so like a plus symbol for a block that adds numbers. This symbol would be monochromatic, and would change colours automatically to contrast that of the user-chosen background.

The purpose of letting the programmer change the background colour is so that they can group blocks visually according to some logic that makes sense to them.

Zooming Into Blocks

Blocks can be made up of more blocks. The programmer can group blocks together this way to simplify their diagram. That way, the entire logic flow of the program doesn’t have to exposed at once. The programmer can have a few blocks representing the general functioning at a high level, and can drill down to blocks to expose more specific logic.

In the IDE, the blocks and connectors are laid out in an infinite canvas. The blocks would appear as tiles. You could then zoom into a block, which would expand from being a tile to taking up the entire screen. The contents would then either be code, or more tiles.

There is only one zoom level, in the sense that the tiles would always be the same size when presented to the user. But you could zoom into or out of levels of tiles an infinite amount.

Blocks are Saved As Files

Blocks, irrespective of whether they are made up of code or other blocks, are stored to a file. So each programmer-defined block in a project would be saved to a separate file. Which means that the main program itself is a block too.

This would be seamless in the IDE. The data from all these disparate files would be loaded at once, and saved accordingly, so that the programmer would just be able to zoom into any block and do edits without having to concern themselves about files.

If the programmer chose to do so, they could save the contents of a given user-defined block to a named file. Otherwise, these would be considered unnamed files, meaning that the IDE would choose a name for it. Doing it this way means that blocks could be imported into other projects and re-used.

Python

Python is at the core of this fictitious language. For the programmer, they’re chaining together blocks to define the behaviour of their application. These blocks are either made up of other blocks or Python code. Which means that all the blocks are actually just Python code at their root.

This language would have a run-time entirely written in Python that would itself run in the Python interpreter. The reason for this run-time is to handle the event loop, the passing of objects between blocks, handling malformed code, launching and managing threads, and also to provide real-time debugging facilities for the IDE.

Connectors as Roads

As the language of implementation is Python, the connectors between blocks would be passing Python objects. The connector would look like a road or thick wire, the representation of which would change depending on whether the object was a Python NoneType (very thin road), an iterable/generator (multiple roads together), or any other object (regular road.)

The presentation of the roads would take a page from SimCity. Crossing ‘roads’ would have one form a little bridge over another, ‘roads’ could be side-by-side, etc.

Blocks can Output Multiple Times

When a block is executed in this fictitious language, it doesn’t have to output just the once. If the block is an iterable/generator, it will output many times as it iterates through. A progress bar overlaying the block will indicate how far it’s progressing through the iterable.

Or if the block represents some I/O interface, it can output many times corresponding to the related input.

Event Driven

Needless to say, the language is event driven. Blocks are called when its input requirements, which may be asynchronous, are fulfilled. Likewise, blocks are triggered on I/O, such as a GUI event or incoming network packet.

Block Inputs / Output Specifics Hidden

The IDE presents blocks as having connectors going in and out. There is no labels to these connections to the block. Hovering over the block with a mouse blows it up in the IDE, such that the inputs and outputs are all shown and labeled. The user can then use their pointer to modify the arrangement of connectors or create a new one.

Constants Are Hidden

Constants that serve as inputs to blocks are only indicated as a little bump that comes out of a block where a connector would be. Blowing up the block would reveal what constant is there as a block input. Constants can be created and modified in the same way as connectors are handled.

Minimum Information Displayed

The idea is that you want the IDE to display the least amount of information. This is why there are multiple levels of blocks (in addition to code re-use), this is why blocks don’t show labels, this is why constants are hidden until explicitly queried. Simplicity is key.

That simplicity is also why the IDE tiles blocks and connectors are also tiled. This enforces a granularity in the presentation and leaves more control to the IDE to naturally simplify the ‘flow chart’, rather than leaving it up to the user. Let the user handle the logic, and the program enforce presentation.

Documentation

Visual elements assisting in documenting the blocks and connectors can be added to the code. These are in the form of strings that can be associated with any block, connector, or groups of the above.

The IDE handles its presentation. A second visual layer can be invoked, in which groups are treated as territories on the world map that is the program, with clearly defined borders. This map is faintly visible regularly and come into view depending on where the pointer is situated.

Flow Control

Flow handling in this fictitious visual language are handled the same as any block. Nothing stops a user from defining a block with multiple inputs that would act as an if statement, for loop, etc. You can loop by having the output of one block be the input to a block further back in the chain.

For clarity, However, a magic function is set in these Python objects that identifies their role in flow handling, and alters their appearance.

Animated

When running code in the IDE, the presentation would be animated. Blocks would go from partially transparent to opaque when called, connectors would animate showing data passing through, etc. The type of connector animation would reflect the data (eg. NoneType, iterator, or any other object.) Deleting a block would show an animation with its attached connectors also disappearing.

This seems so shallow, but having this emphasis on almost video-game like presentation makes the whole thing much more easily to mentally parse than to default to very utilitarian designs. This is especially key with programming newcomers.

Touch Is The Future

The IDE would need to be functional with a finger as it is a mouse. The future is going to the finger as an input device. While serious programmers may always use a text-based programming language and a pointer device, we have to envision a world where there are programmers that do their work on a tablet. That do their work in a purely graphical environment.

This fictitious language doesn’t need to be used for systems design. But the visual format lends itself well to touch. Hold your finger down (or mouse button) to pop up a radial menu with blocks, which can then be dragged to the appropriate tile. Likewise for dragging connectors. It’s there.

Slow Motion and Debugging

For debugging, the run-time would allow users to set breakpoints and put probes at any connector. The run-time could also put delays at each connector, creating the illusion of slow-motion and displaying where data is being passed around. This would facilitate debugging.

Branched Time Machine

The IDE would create a time line of the changes made by the user, which could be invoked by the user. The “time” is not based on real-world time, but relative to the changesets. The programmer could then rewind or go back to any past state, and start making changes from there. This would create a new branch in the timeline.

There are no explicit commits, every change is tracked. The user could switch back to other branches by clicking their visual representation in the IDE. I don’t know how I would go about  multi-user content revisioning and merging independent work.

Block Limit

The IDE would have a block limit and produce a warning when it was exceeded. Perhaps 32 blocks, though each block can be made up of an infinite number of sub-blocks (all with that same limit.) This is going back to the idea of enforcing structure. It would force developers to componentize associated blocks, making the overall structure simpler.

GUI Driven Development

Ask a non-programmer to design an application on a sheet of paper. What you’ll often get is that they start drawing the GUI, and then note things like “when they press this button, the program does X.”

That’s probably the reverse of how most programmers think, yet it’s the most intuitive way for non-professionals. That should be captured. Ideally, if the fictional IDE for this language ever took off, you’d be able to design your GUI first without needed to put any code down.

GUI elements would appear as blocks in the flow chart to which inputs and outputs could wired. This is similar to LabView. However, there would only be a single window for both GUI and logic, separated instead by layers. Switching from the GUI layer to the logic layer would cause the UI elements to blow out and turn into blocks.

Summary

So to summarize, the language I envision is a general-purpose visual programming language. Its graphical representation is intended to make it accessible to non-programmers and lessen the dependence on programmers to make clean code. The interpreter would be no more than a run-time written in Python running Python code, so that the language could interface with Python code as easily as visual elements. There would be a focus on making the IDE as usable on touch-screen devices as those equipped with a mouse and keyboard.