
A strongly typed identifier is user-defined
data type
In computer science and computer programming, a data type (or simply type) is a collection or grouping of data values, usually specified by a set of possible values, a set of allowed operations on these values, and/or a representation of these ...
which serves as an identifier or key that is
strongly typed. This is a solution to the "primitive obsession"
code smell
In computer programming, a code smell is any characteristic in the source code of a program that possibly indicates a deeper problem. Determining what is and is not a code smell is subjective, and varies by language, developer, and development met ...
as mentioned by
Martin Fowler. The data type should preferably be
immutable if possible. It is common for implementations to handle equality testing,
serialization
In computing, serialization (or serialisation, also referred to as pickling in Python (programming language), Python) is the process of translating a data structure or object (computer science), object state into a format that can be stored (e. ...
and model binding.
The strongly typed identifier commonly wraps the data type used as the
primary key
In the relational model of databases, a primary key is a designated attribute (column) that can reliably identify and distinguish between each individual record in a table. The database creator can choose an existing unique attribute or combinati ...
in the database, such as a string, an integer or
universally unique identifier
A Universally Unique Identifier (UUID) is a 128-bit label used to uniquely identify objects in computer systems. The term Globally Unique Identifier (GUID) is also used, mostly in Microsoft systems.
When generated according to the standard methods ...
(UUID).
Web framework
A web framework (WF) or web application framework (WAF) is a software framework that is designed to support the development of web applications including web services, web resources, and web APIs. Web frameworks provide a standard way to build a ...
s can often be configured to model bind properties on view models that are strongly typed identifiers.
Object–relational mappers can often be configured with value converters to map data between the properties on a model using strongly typed identifier data types and database columns.
Examples
Passing a strongly typed identifier throughout the layers of an example application.
C#
C# have records which provide immutability and equality testing. The record is sealed to prevent
inheritance
Inheritance is the practice of receiving private property, titles, debts, entitlements, privileges, rights, and obligations upon the death of an individual. The rules of inheritance differ among societies and have changed over time. Offi ...
. It overrides the built-in
ToString()
method.
This example implementation includes a static method which can be used to initialize a new instance with a randomly generated
globally unique identifier
A Universally Unique Identifier (UUID) is a 128-bit label used to uniquely identify objects in computer systems. The term Globally Unique Identifier (GUID) is also used, mostly in Microsoft systems.
When generated according to the standard methods ...
(GUID).
///
/// Represents a user identifier.
///
/// The user identifier.
public sealed record UserId(Guid Id)
C++
C++ have structs but not immutability so here the id field is marked as private with a method named
value()
to get the value.
struct UserId ;
ostream& operator << (ostream &os, const UserId &id)
Crystal
Crystal
A crystal or crystalline solid is a solid material whose constituents (such as atoms, molecules, or ions) are arranged in a highly ordered microscopic structure, forming a crystal lattice that extends in all directions. In addition, macros ...
's standard library provides the record macro for creating records which are immutable structs and lets you create override the built-in
to_s
method.
require "uuid"
# Represents a user identifier.
record UserId, id : String do
def initialize()
@id = UUID.v4.to_s
end
def to_s(io)
io << id
end
def self.empty
self.new(UUID.empty.to_s)
end
end
D
D have immutable structs.
import std;
/** Represents a user identifier. */
immutable struct UserId
Dart
Dart have classes with operator overloading.
import 'package:meta/meta.dart';
/// Represents a user identifier.
@immutable
final class UserId
F#
F# lets you create override the
Equals
,
GetHashCode
and
ToString
methods.
open System
///
/// Represents a user identifier.
///
/// The user identifier.
type UserId(id: Guid) =
member x.id = id
static member New() = Guid.NewGuid()
static member Empty = Guid.Empty
override x.Equals(b) =
match b with
, :? UserId as p -> id = p.id
, _ -> false
override x.GetHashCode() = hash id
override x.ToString() = id.ToString()
Go
Go have structs which provide equality testing. Go however does not provide immutability.
// Represents a user identifier.
type UserId struct
// Creates a new user identifier.
func NewUserId(id string) UserId
func (x UserId) String() string
Groovy
Groovy
''Groovy'' (or, less commonly, ''groovie'' or ''groovey'') is a slang colloquialism popular during the 1960s and 1970s. It is roughly synonymous with words such as "excellent", "fashionable", or "amazing", depending on context.
History
The word ...
have record classes which provide immutability and equality testing.
/**
* Represents a user identifier.
*
* @param id The user identifier.
*/
record UserId(String id)
Haskell
Haskell
Haskell () is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research, and industrial applications, Haskell pioneered several programming language ...
can create user-defined custom data types using the
newtype
keyword. It provides equality testing using the
Eq
standard class and printing using the
Read
and
Show
standard classes.
-- Represents a user identifier.
newtype UserId = UserId String deriving (Eq, Read, Show)
Java
Java
Java is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea (a part of Pacific Ocean) to the north. With a population of 156.9 million people (including Madura) in mid 2024, proje ...
have records which provide equality testing.
The record is declared using the
final
modifier keyword to prevent inheritance. It overrides the built-in
toString()
method.
import java.util.UUID;
/**
* Represents a user identifier.
* @param id The user identifier.
*/
public final record UserId(UUID id)
JavaScript
This
JavaScript
JavaScript (), often abbreviated as JS, is a programming language and core technology of the World Wide Web, alongside HTML and CSS. Ninety-nine percent of websites use JavaScript on the client side for webpage behavior.
Web browsers have ...
example implementation provides the
toJSON
method used by the
JSON.stringify()
function to serialize the class into a simple string instead of a
composite data type
In computer science, a composite data type or compound data type is a data type that consists of programming language scalar data types and other composite types that may be heterogeneous and hierarchical in nature. It is sometimes called a struct ...
.
It calls
Object.freeze()
to make the instance immutable.
It overrides the built-in
toString()
method and the
valueOf()
method.
class UserId
Julia
Julia have immutable composite data types.
using UUIDs
"Represents a user identifier."
struct UserId
id::UUID
end
Base.string(userId::UserId) = userId.id
Kotlin
Kotlin have "inline classes".
/**
* Represents a user identifier.
*
* @property id The user identifier.
* @constructor Creates a user identifier.
*/
@JvmInline
public value class UserId(public val id: String)
Nim
Nim have "distinct types".
## Represents a user identifier.
type UserId* = distinct string
PHP
This
PHP
PHP is a general-purpose scripting language geared towards web development. It was originally created by Danish-Canadian programmer Rasmus Lerdorf in 1993 and released in 1995. The PHP reference implementation is now produced by the PHP Group. ...
example implementation implements the
__toString()
magic method.
Furthermore, it implements the
JsonSerializable
interface which is used by the built-in
json_encode
function to serialize the class into a simple string instead of a
composite data type
In computer science, a composite data type or compound data type is a data type that consists of programming language scalar data types and other composite types that may be heterogeneous and hierarchical in nature. It is sometimes called a struct ...
.
The class is declared using the
final
modifier keyword to prevent inheritance.
PHP has traits as a way to re-use code.
/**
* Represents a user identifier.
*/
final class UserId implements JsonSerializable
/**
* Provides methods for use with strongly typed identifiers.
*/
trait StronglyTypedIdentifier
Python
Python has data classes which provides equality testing and can be made immutable using the
frozen
parameter. It overrides the
__str__
dunder method.
This example implementation includes a static method which can be used to initialize a new instance with a randomly generated
universally unique identifier
A Universally Unique Identifier (UUID) is a 128-bit label used to uniquely identify objects in computer systems. The term Globally Unique Identifier (GUID) is also used, mostly in Microsoft systems.
When generated according to the standard methods ...
(UUID).
from dataclasses import dataclass
import uuid
@dataclass(frozen=True)
class UserId:
"""Represents a user identifier."""
id: uuid.UUID
@staticmethod
def new() -> Self:
"""Create a new user identifier."""
return __class__(uuid.uuid4())
def __str__(self):
return str(self.id)
Python also has
NewType
which can be used to create new data types.
from typing import NewType
UserId = NewType('UserId', int)
Ruby
Ruby
Ruby is a pinkish-red-to-blood-red-colored gemstone, a variety of the mineral corundum ( aluminium oxide). Ruby is one of the most popular traditional jewelry gems and is very durable. Other varieties of gem-quality corundum are called sapph ...
have data classes which provides equality testing and are immutable. It overrides the built-in
to_s
method.
This example implementation includes a static method which can be used to initialize a new instance with a randomly generated
universally unique identifier
A Universally Unique Identifier (UUID) is a 128-bit label used to uniquely identify objects in computer systems. The term Globally Unique Identifier (GUID) is also used, mostly in Microsoft systems.
When generated according to the standard methods ...
(UUID).
require 'securerandom'
# Represents a user identifier.
UserId = Data.define(:id) do
# Create a new user identifier.
def self.create
self.new(SecureRandom.uuid)
end
def self.empty
self.new('00000000-0000-0000-0000-000000000000')
end
def to_s
id
end
end
Rust
In
Rust
Rust is an iron oxide, a usually reddish-brown oxide formed by the reaction of iron and oxygen in the catalytic presence of water or air moisture. Rust consists of hydrous iron(III) oxides (Fe2O3·nH2O) and iron(III) oxide-hydroxide (FeO(OH) ...
this can be done using a
tuple
In mathematics, a tuple is a finite sequence or ''ordered list'' of numbers or, more generally, mathematical objects, which are called the ''elements'' of the tuple. An -tuple is a tuple of elements, where is a non-negative integer. There is o ...
struct containing a single value. This example implementation implements the
Debug
and the
PartialEq
traits. The
PartialEq
trait provides equality testing.
// Represents a user identifier.
# erive(Debug, PartialEq)pub struct UserId(String);
Scala
Scala have case classes which provide immutability and equality testing. The case class is sealed to prevent inheritance.
import java.util.UUID
/** Represents a user identifier.
*
* @constructor
* Create a new user identifier.
* @param id
* The user identifier.
*/
sealed case class UserId(id: UUID)
object UserId:
/** Initializes a new instance of the UserId class. */
def create(): UserId = UserId(UUID.randomUUID())
Swift
Swift
Swift or SWIFT most commonly refers to:
* SWIFT, an international organization facilitating transactions between banks
** SWIFT code
* Swift (programming language)
* Swift (bird), a family of birds
It may also refer to:
Organizations
* SWIF ...
have the
CustomStringConvertible
protocol which can be used to provide its own representation to be used when converting an instance to a string, and the
Equatable
protocol which provides equality testing.
import Foundation
/// Represents a user identifier.
struct UserId: CustomStringConvertible, Equatable
Zig
Zig have structs with constants but by design does not have operator overloading
and method overriding.
/// Represents a user identifier.
const UserId = struct ;
See also
*
Domain-driven design
Domain-driven design (DDD) is a major software design approach, focusing on modeling software to match a domain according to input from that domain's experts. DDD is against the idea of having a single unified model; instead it divides a large s ...
*
Type safety
In computer science, type safety and type soundness are the extent to which a programming language discourages or prevents type errors. Type safety is sometimes alternatively considered to be a property of facilities of a computer language; that ...
*
Value object
References
External links
* https://wiki.c2.com/?PrimitiveObsession
{{Design Patterns patterns
Articles with example C Sharp code
Articles with example C++ code
Articles with example D code
Articles with example Haskell code
Articles with example Java code
Articles with example JavaScript code
Articles with example Julia code
Articles with example PHP code
Articles with example Python (programming language) code
Articles with example Ruby code
Articles with example Rust code
Articles with example Scala code
Articles with example Swift code
Data types
Software design patterns