Skip to content
Paolo Angeli edited this page Oct 6, 2019 · 21 revisions

Behind and Beyond Jai

Friction in modern OOP C++

Modern C++ is the "de facto" standard for many of the most complex software like videogames. But it is cumbersome, heavy and overcomplicated. It is a "big agenda" language that evolved in many years stratifying decisions taken to mitigate problems that game developers don't have (cit.). Using this language for big complex tasks becomes rapidly a stressful and tedious activity. The coders have to express themselves in terms forced by the language and so even simple tasks become boring error-prone activities.

The tools involved in modern C++ programming has a tremendous lack of effectiveness: compilers sometimes give obscure messages, compilation time on serious programs becomes rapidly an issue, debugging can be very hard on complex problems, build process involves several connected tools, etc..

All of these problems can be expressed in terms of friction: the difficulty to get a constant fluid flow of improvement in the code till the scheduled release. Having deadlines and a list of todos that shrink slowly is stressful and painful. Moreover, friction limits the coder in terms of the exploration of alternatives and new ideas because of their time cost. This reduces the effectiveness, performance, and security of the code.

In the end, friction not only reduces enthusiasm, and freedom of the coding teams but also heavily reduces the quality of life of the programmers so their productivity. It wipes away the joy from the creation process and makes the programmers feel like living a miserable life (cit.). All of these are very big problems for the software industry. Imagine if it would be possible to gain only 20% in friction reduction, this could lead to an enormous amount of overall improvement. And this possibility alone justifies the idea of the creation of a new language.

Machines that fill the memory

The original designer said that "video games are machines that fill memory". The majority of the time, game programmers are thinking about how to fill memory with huge reams of data in ways that allow the data to be efficiently accessed and processed. Hundreds of megabytes of memory must be moved from the hard disk into the main memory, and from there into the video card or the processor cache to be processed and returned to the main memory. Because video game players don’t like to wait, all this must be done as fast as is allowable by laws of our universe. The primary purpose of a programming language is to allow the specification of algorithms to manage data. Language features like garbage collection and templated data streams and dynamic string classes may help the programmer write code faster, but they don’t help the programmer write faster code.

FRICTION REDUCTION

Another major design goal of Jai is to reduce friction when programming. Friction happens when the syntax of a language interferes with the programmer’s workflow. For example:

  • Java requires that all objects be classes, forcing programmers to put the global variables they need into global classes.
  • Haskell requires that all procedures be functions and have no side effects.
  • C++’s lambda function syntax is different from its class method syntax, which is itself different from its global function syntax.

Java, Haskell, and C++ are examples of what could be called “big agenda” languages, where the languages' idealism (and in C++’s case, its lack of a consistent vision) gets in the programmer’s way. Jai is being designed with a low tolerance for friction, especially when it is unnecessary.

DESIGN FOR GOOD PROGRAMMERS

Jai is a language designed for good programmers, not against bad programmers. Languages like Java were marketed as idiot-proof, in that it’s much more difficult for programmers to write code that can hurt them. The Jai philosophy is: "if you don’t want idiots writing bad code for your project, then don’t hire any idiots". Jai allows programmers direct access to the sharp tools that can get the job done. Game programmers are not afraid of pointers and manual memory management. Programmers do make mistakes and cause crashes, perhaps even serious ones, but the argument is that the increase in productivity and reduction of friction when memory-safe mechanisms are absent more than make up for the time lost in tracking down errors, especially when good programmers tend to produce relatively few errors.

PERFORMANCE AND DATA-ORIENTED PROGRAMMING

If as a programmer you care about user experience (which you should), then you should care about the performance of your program. You should reason about your code’s behavior on the range of machines that you’re shipping on, and design your data and control structures to use that hardware’s capability most efficiently. (Here I’m describing Mike Acton’s “Data-Oriented Design” methodology.) Programmers who care about the performance of their software on their target hardware are inhibited by programming languages that sit between them and the hardware.

In the years the academic culture about software development has moved away from the real Information Technology concerns (the data) toward the tools used by the programmers (the software). The attention was driven toward code, algorithms, and patterns instead than on the matter of fact of the problems: how to transform data effectively, that should be the true purpose of the software. This is nothing new, instead was really clear years ago. Fred Books stated a famous phrase cit. resembled in this brief intervention.

Mechanisms like virtual machines and automatic memory management interfere with the programmer’s ability to reason about the program’s performance on the target hardware. Abstractions like RAII, constructors and destructors, polymorphism, and exceptions were invented to solve problems that game programmers don’t have, and with the result of interfering with the solutions to problems that game programmers do have. Jai jettisons these abstractions so that programmers can think more about their actual problems—the data and their algorithms.


Navigate

Types, constants and variables

  • Variables and assignments
  • Language data types
  • Simple user-defined data types
  • Expressions and operators
  • Type-casting
  • Pointers

Flow control

Procedures and functions

  • Declarations
  • Arguments / Parameters
  • Return values
  • Overloading / Polymorhism
  • Advanced features
  • Lambdas

Aggregated data types

  • Arrays
  • Strings
  • Composition of Structs

Advanced features

Clone this wiki locally