Code Templates

Published:

This article is about code templates, in JetBrains IDEs they are called Live Templates. You write a keyword, and the IDE outputs code associated with it. It can speed up code writing if you have well-defined templates that are easy to remember between multiple languages.

For example, you may define a keyword fori . To write a loop, one only types:

fori TAB 20 TAB

If the language is Python, it will output

for i in range(20):
  $END$

and if it is in C#, the result is

for (int i = 0; i < 20; i++) {
  $END$
}

This article describes the shortcuts I use, and it targets TypeScript, C# and Haskell. I recommend you design a system that suits you, it will help in learning a new language.

When defining the templates, refer to your IDE's documentation e.g. in JetBrains IDEs they should be $TEMPLATE_ARG$. Below examples, I prefix the variables with t_ to ensure that syntax highlighting works as expected.

Basic types

You may also define syntax for basic types, but I myself find it easier to just type them out. Some types could be

TypeAbbreviationExample template
integertintint t_NAME = t_END;
decimaltdecdecimal t_NAME = t_END;
booleantboolbool T_NAME = t_END;

A more complex data structures are usually suggested by intellisense and named similarly (e.g. Stack is Stack, and Tree is Tree) so there shouldn't be difficulty in finding them.

Loops

The loops are commonly using a keyword for. In functional languages, it may not exist and loops are typically constructed by recursion.

Iterate with index fori

tfori $VAR$ TAB $MAX$ TAB

Iterate all fore

It is also common to iterate all items in a collection such as lists, commonly denoted with foreach.

tfore $ITEM$ TAB $COLLECTION$ TAB

Mappings map

Mapping is commonly used in functional languages, and the syntax is typically so.

tmap $COLLECTION$ TAB $ITEM$ TAB

Control Structures

Common control structures are if and switch, some languages such as Haskell supports a guard -syntax.

If conditions

This is usually predefined and looks almost same, also else statements.

if $CONDITION$ TAB
if (t_CONDITION)
{
  t_END
}

Switches and guards switch

A common C-like switch case is used on object-oriented languages. However, C# also support a guard-like syntax for switch.

tswitch $VARIABLE$ TAB $DEFAULT_CASE$ TAB

Functions

The kind of functions used in everyday programming are usually generic functions, lambda functions, extension functions, and class methods. The function templates shouldn't include documentation since, there are separate templates for them.

The normal methods have a predefined templates and lambdas are usually trivial so we only need to define templates for generic functions. Template functions, if the language supports it

Generic fng

With generics, the less types the better. So this, thing defaults to one argument and following the naming conventions it is a single letter T.

MODIFIERS tfng $RETURN_TYPE$ TAB $NAME$ TAB $ARGUMENTS$

Extension method fne

As far as I know C# and Java has extension methods

tfne $RETURN_TYPE$ $NAME$ TAB $EXTENDS_TYPE$ TAB $ARGUMENTS$
public static t_RETURN_TYPE t_NAME(this t_EXTENDS_TYPE instance, t_ARGUMENTS) {
  t_END
}

Type definitions

The class itself, enum, and type aliases are usually used as type. They are conviently defined as File Templates where are bare definition is added when file is created.

Since, the "best practice" is to put class per file, there is no need to define abbreviations for them.

Web Development

Some in online communities describe web development being similar and "just CRUD". In some ways, it is true since most applications have same features e.g. email authentication, subscriptions, etc.

Most importantly a boilerplate need to be define every time an endpoint is defined!

Since they vary wildly by web framework in use, you should prefix them with the name of framework e.g. djcreate for Django abbreviation for apicreate. Because it would conflict if you define them in Python and also use FastAPI.

API operations

Similarly as this create, you can define them for other CRUD operations list, delete, and update.

tapicreate $RESPONSE$ TAB $REQUEST$ TAB

Testing

I think the values comes with assertions e.g. the object comparison need to be deep comparison which compares the attributes. For example, Chai would assert it as expect(a).deep.equal(b) but jest does it by default expect(a).toEqual(b).

By defining common assertions as templates, you don't need to memorize the backend framework assertion and different frontend assertions. There is potentially three different ways: end-to-end (Puppeteer, Cypress), unit (Jest, Mocha-Chai), and backend tests (XUnit).