As a software developer, I have observed various methodologies for choosing the primary key of a table. Some programmers exhibit proclivity for purposefully creating new columns to serve as the aforementioned key, while the others usually look for a solution that involves the already-existing columns. I would like to approach the said problem from an engineering perspective, taking into account available theories and common experiences, especially in the distributed-systems department.

Candidate Keys

When designing a table, database designers should ask themselves the following question — how to identity a particular row inside? The process of finding an answer might in turn reveal…

Even though the notion of intrinsic types might baffle the reader, I will not define them right away, as I want to introduce the concept using a practical example. I would love to start the article with the following question, something I have asked myself in various forms over the years:

In an ideal, statically-typed language, how could one define the string capitalisation type, using the properties of its type system?

I could substitute string capitalisation with string permutation and the issue still remains valid, as long as it touches not the abstraction of types, but their intrinsic properties.

Solving the Assignment


In my previous article, I wrote about a selection of runtime operators in TypeScript. In this very article, I would like to discuss the most relevant compile-time operators, based on my experience as a software developer. These operators enrich the type system by providing a grammar layer for manipulating type information and they leave no runtime trace.

Image for post
Image for post
All the compile-time TS operators I could think of. Have I included all of them?

Compile-time Operators

The typeof operator

TypeScript supports structural typing, which allows software developers to declare variables without specifying the exact nominal type. One variable (type) can implement multiple nominal types as only property names and their structural types, applied recursively, a matter for the implementation-matching algorithm. …

As TypeScript enhanced the dynamic type system of JavaScript with a static one, certain language elements became more sophisticated. One of the fundamental constructs that were altered are operators, a core feature of presumably every high-level programming language. A handful of them got augmented due to the availability of type information, some of them became virtually deprecated and a whole new set of operators came to be.

I would like to introduce the reader to a curated list of the most important operators in use in production-grade TypeScript projects. …

Over the years, I have successfully applied a lot of diverse design patterns using different technology stacks. As the idea of writing them down came in the 1990s and was largely based upon the object-oriented intrinsics of the most popular programming languages at the time, I needed to make certain concessions as well as specific enhancements when porting the patterns to languages and frameworks of my choice. This article sums up all my ideas about modifying the creational design patterns.


  • by an abstract class I essentially mean a template for creation of derived classes (there cannot exist a direct instance…

In the second part of this series, I wrote about the high-level design of Data Access Layers, taking into account the perspective of its consumers. Today, I am going to expand on this topic to include the low-level design principles, focusing on the variety of choices a team of developers needs to make during the design process.

ORM vs DB Driver

Establishing a low-level connection to the database from a backend service is achievable with a driver, which is able to send meaningful packets to the specific database server over TCP/IP (or UDP/IP in some cases). The API of the driver itself is expected…

In the first part of this article series, I pondered on the way product requirements, database schemas and technology stacks influence the shape of data access layers. Today, I am going to discuss how their APIs could be designed, gathering all the necessary requirements first. The first step is to find out the consumers of the aforementioned APIs.


Commonly, a DAL is going to be used in two places within a codebase: the source code and tests. This dichotomy of usage might require accounting for different database engines in each case. If they are indeed disparate, the engine in the…

The Data Access Layer is a layer that establishes communication between a database (SQL or NoSQL) and a backend service (factoring in multiple instances if applicable). Even though the term itself does not speak much about its intrinsic properties, there are certain architectural patterns commonly leveraged when designing DALs. Some frameworks use different terminology, calling it the Data Access Object but for the purpose of this article I find it best to agree that these names are synonymous.

Before I start delving into this topic, please note that the article is highly opinionated, taking into account variety of my experiences…

Over the past couple of years during which I have been writing software utilising microservices, I found out that writing code that just works is simple. Writing maintainable and testable code, on the other hand, has never been trivial. End-to-end tests, especially, have always been a maintenance nightmare due to potential changes in all dependencies which cannot be tracked down using conventional methods (e.g. by using static type checks).

What if there was a way to decrease the level of dependencies between tested microservices so we are able to write E2E tests efficiently?

Using one programming language for projects

Despite the fact that is not always…

Introduction to TypeScript classes

I believe most JavaScript and TypeScript developers are quite familiar with the syntax required for defining and using classes:

class RegularClass {}

Even though ourRegularClass might look boring, there is more to it than meets the eye. The identifier RegularClass is used in two distinct contexts:

  • as the class identifier (during the class definition and usages of static properties),
  • as the type of the instance of the class (the instance is understood as an object that is returned by the constructor).

Realising this dichotomy allows us to see that the meaning of the aforementioned identifier is based on the context…

Gregory Pabian

Full-stack Software Developer that loves building products.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store