In order to deliver significantly more reliable software to our clients, we have developed an integral approach to software development.

Minimize the Amount of Code

The larger your source code is, the higher the chance of bugs. We work hard to minimize the size of our code in order to ensure that your software has the highest level of reliability and performance.

  • Minimal Viable Product. During development, we identify your core requirements for our custom software. By focusing our development exclusively on necessary features that fulfill your requirements, the size of our source code is greatly reduced. As an added benefit, this allows us to deliver a finished product in a quick, efficient manner.

  • Functional Programming Language. Our use of the functional programming language Haskell results in concise code. Functional programming also has the benefit of easy reuse throughout our software, further minimizing the size of our code.

Design for Failure

All software, no matter how well it is designed, will eventual experience a failure of some sort. We take this fact into account when designing your software, incorporating measures to reduce software downtime and minimize impact of failures.

  • Anticipate failure. Our software architecture is designed to handle common failures as part of its normal flow. This ensures that most errors are automatically detected and resolved.

  • Crash early. When exceptional failures do arise, our software is designed to crash early. Dead programs normally do significantly less damage than crippled ones. Designing our software to crash early limits the impact of exceptional failures.

  • Always recover. Since crashes are an inevitable part of every piece of software, the ability to recover quickly is mandatory. Our software is designed to handle recovery procedures using the same code used for starting after a normal shutdown, ensuring that recovery will always work.

Compile-Time Checking

In compiled languages, the compiler translates program code into machine code. During this translation, the compiler will fail on logical errors and typos, preventing them from occurring at runtime.

  • Strong typed language. We use a strong typed language that can perform more checks during compilation. By assigning types to all data, our code is being validated for accuracy. For example, these checks can ensure that addition can only be performed on two numbers, and not with a number and a string.

  • Leverage typing. By extending basic data types with custom data types, we can detect a greater number of errors, ensuring that illegal business states will be compilation errors. For example, we can catch the mix-up of ISBN and quantity, which are both numeric data types, but very different things, during compilation.

Avoid Error-Prone Techniques

Some programming techniques are more prone to error than others. By using proven programming best-practices, we ensure that our software code is of the highest quality.

  • Avoid locking. When multiple concurrent computations need access to shared data, their access needs to be regulated, often through the use of locking. Unfortunately, this is hard to get right and mistakes can result in random failures. We avoid these issues by using Software Transactional Memory or the Actor model.

  • Avoid manual memory management. Software uses memory to keep track of the data it is working with. In many programming languages, the memory must be managed by the programmer. However, it is easy to make mistakes that result in crashes or data corruption. We use languages that have built-in memory management capabilities, circumventing programmer-related memory management problems.