
Un identificador fuertemente tipado es un tipo de datos definido por el usuario que sirve como un identificador o clave fuertemente tipado . Esta es una solución al problema del código "obsesión primitiva" mencionado por Martin Fowler . El tipo de datos debería ser preferiblemente inmutable si es posible. Es común que las implementaciones manejen pruebas de igualdad, serialización y vinculación de modelos.
El identificador fuertemente tipado comúnmente envuelve el tipo de datos utilizado como clave principal en la base de datos, como una cadena, un entero o un identificador único universal (UUID).
Los marcos web se pueden configurar a menudo para modelar propiedades de enlace en modelos de vista que son identificadores fuertemente tipados. Los mapeadores relacionales de objetos se pueden configurar a menudo con convertidores de valores para mapear datos entre las propiedades de un modelo utilizando tipos de datos de identificadores fuertemente tipados y columnas de base de datos.
Ejemplos
Pasar un identificador fuertemente tipado a lo largo de las capas de una aplicación de ejemplo.
DO#
C# tiene registros que proporcionan inmutabilidad y pruebas de igualdad. [1] El registro está sellado para evitar la herencia . [2] Anula el método integrado ToString(). [3]
Esta implementación de ejemplo incluye un método estático que se puede utilizar para inicializar una nueva instancia con un identificador único global (GUID) generado aleatoriamente.
/// <summary>
/// Representa un identificador de usuario.
/// </summary>
/// <param name="Id">El identificador de usuario.</param>
public sealed record UserId ( Guid Id ) { /// <summary> /// Inicializa una nueva instancia del registro <see cref="UserId" />. /// </summary> /// <returns>Un nuevo objeto UserId.</returns> public static UserId New () => new ( Guid . NewGuid ());
cadena pública de anulación ToString ( ) = > Id.ToString (); }
C++
C++ tiene estructuras pero no inmutabilidad, por lo que aquí el campo id está marcado como privado con un método nombrado value()para obtener el valor.
estructura UserId { UserId ( cadena constante _id ) { id = _id ; }
valor de cadena () const { return id ; }
operador bool == ( const UserId & rhs ) const { valor de retorno () == rhs . valor (); }
privado :
cadena id ; };
ostream & operador << ( ostream & os , const UserId & id ) { return os << id . valor () << std :: endl ; }
Cristal
La biblioteca estándar de Crystal proporciona la macro de registro para crear registros que son estructuras inmutables y le permite crear o anular el método incorporado to_s. [4]
requiere "uuid"
# Representa un identificador de usuario.
record UserId , id : String do def initialize () @id = UUID . v4 . to_s end
def to_s ( io ) io << id fin
def self . empty self . new ( UUID . empty . to_s ) fin fin
D
D tiene estructuras inmutables. [5]
importar std ;
/** Representa un identificador de usuario. */
immutable struct UserId { immutable UUID id ;
/** Inicializa una nueva instancia de la estructura UserId. */
this ( cadena inmutable id ) { this . id = UUID ( id ); }
público estático UserId crear () { devolver UserId ( randomUUID.toString ( ) ); }
cadena toString () { devuelve este .id .toString ( ) ; } }
Dardo
Dart tiene clases con sobrecarga de operadores.
importar 'paquete:meta/meta.dart' ;
/// Representa un identificador de usuario.
@immutable
final class UserId { final String id ;
/// Inicializa una nueva instancia de la estructura UserId. const UserId ( this.id ) ;
@override
operador == ( otro ) => otro es UserId && otro . id == id ; @override int obtener hashCode => id . hashCode ; @override String toString () => id ; }
F#
F# le permite crear y anular los métodos Equals, GetHashCodey ToString.
Sistema abierto
/// <summary> /// Representa un identificador de usuario.
/// </summary> /// <
param name="id">El identificador de
usuario . </param> 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 ( )
Ir
Go tiene estructuras que permiten realizar pruebas de igualdad, pero no ofrece inmutabilidad.
// Representa un identificador de usuario.
tipo UserId struct { id string }
// Crea un nuevo identificador de usuario.
func NewUserId ( id string ) UserId { return UserId { id : id } }
func ( x UserId ) String () cadena { devolver x . id }
Genial
Groovy tiene clases de registros que proporcionan inmutabilidad y pruebas de igualdad. [6]
/**
* Representa un identificador de usuario.
*
* @param id El identificador de usuario.
*/
record UserId ( String id ) { String toString () { id } }
Haskell
Haskell puede crear tipos de datos personalizados definidos por el usuario utilizando la newtypepalabra clave. [7] Proporciona pruebas de igualdad utilizando la Eqclase estándar e impresión utilizando las clases estándar Ready Show.
-- Representa un identificador de usuario.
newtype UserId = UserId String deriving ( Eq , Read , Show )
Java
Java tiene registros que permiten realizar pruebas de igualdad. [8]
El registro se declara utilizando la palabra clave modificadora para evitar la herencia. Anula el método
finalincorporado .toString()
importar java.util.UUID ;
/**
* Representa un identificador de usuario.
* @param id El identificador de usuario.
*/
public final record UserId ( UUID id ) { /** * Inicializa una nueva instancia del registro UserId. * @return Un nuevo objeto UserId. */ public static UserId newId () { return new UserId ( UUID . randomUUID ()); }
público String toString () { devolver id . toString (); } }
JavaScript
Esta implementación de ejemplo de JavaScript proporciona el toJSONmétodo utilizado por la función JSON.stringify()[9] para serializar la clase en una cadena simple en lugar de un tipo de datos compuesto . Llama Object.freeze()para hacer que la instancia sea inmutable. [10]toString() Anula el método
incorporado [11] y el valueOf()método. [12]
clase UserId { # id ;
constructor ( id ) { if ( id == undefined ) { throw new TypeError ( "El argumento es nulo o indefinido." ); } this . # id = id ; Object . freeze ( this ); }
static empty = new this . prototipo . constructor ( "00000000-0000-0000-0000-000000000000" );
static new ( ) { devolver nuevo this.prototype.constructor ( crypto.randomUUID ( ) ) ; }
es igual a ( id ) { devolver id instanciade este . constructor && este . # id === id . valorDe (); }
toJSON () { devuelve este . # id ; }
toString () { devuelve este . # id ; }
valueOf () { devuelve este . # id ; } }
Julia
Julia tiene tipos de datos compuestos inmutables. [13]
utilizando UUID
"Representa un identificador de usuario".
struct UserId
id :: UUID end
Base . cadena ( userId :: UserId ) = userId . id
Kotlin
Kotlin tiene "clases en línea". [14]
/**
* Representa un identificador de usuario.
*
* @property id El identificador de usuario.
* @constructor Crea un identificador de usuario.
*/
@JvmInline
public value class UserId ( public val id : String ) { override fun toString () = id }
Nim
Los nim tienen "tipos distintos". [15] [16]
## Representa un identificador de usuario.
tipo UserId * = cadena distinta
PHP
Esta implementación de ejemplo de PHP implementa el __toString()método mágico. [17]
Además, implementa la JsonSerializableinterfaz que utiliza la función incorporada json_encodepara serializar la clase en una cadena simple en lugar de un tipo de datos compuesto . [18]
La clase se declara utilizando la finalpalabra clave modificadora para evitar la herencia. [19]
PHP tiene rasgos como una forma de reutilizar el código. [20]
/**
* Representa un identificador de usuario.
*/
final class UserId implements JsonSerializable
{
use StronglyTypedIdentifier ;
}
/**
* Proporciona métodos para usar con identificadores fuertemente tipados.
*/
trace StronglyTypedIdentifier
{
/**
* Inicializa una nueva instancia del objeto UserId.
* @param string $id El identificador del usuario.
*/
public function __construct ( public readonly string $id ) {}
/**
* Crea un nuevo identificador de usuario.
*/
public static function new () : self
{
return new self ( bin2hex ( random_bytes ( 16 )));
}
función pública jsonSerialize () : cadena
{
return $this -> id ;
}
función pública __toString () : cadena
{
return $this -> id ;
}
}
Pitón
Python tiene clases de datos que proporcionan pruebas de igualdad y pueden hacerse inmutables usando el frozenparámetro. [21] Anula el __str__método dunder. [22]
Esta implementación de ejemplo incluye un método estático que se puede utilizar para inicializar una nueva instancia con un identificador único universal (UUID) generado aleatoriamente.
desde dataclasses importar dataclass
importar uuid
@dataclass ( frozen = True )
clase UserId :
"""Representa un identificador de usuario."""
Identificación : UUID . UUID
@staticmethod
def new () -> Self :
"""Crear un nuevo identificador de usuario.""" return __class__ ( uuid . uuid4 ())
def __str __ ( self )
: devuelve str ( self.id )
Python también tiene NewTypela función que se puede utilizar para crear nuevos tipos de datos. [23]
desde la escritura importar NewType
UserId = NewType ( 'UserId' , int )
Rubí
Ruby tiene clases de datos que proporcionan pruebas de igualdad y son inmutables. [24] Anula el método incorporado to_s.
Esta implementación de ejemplo incluye un método estático que se puede utilizar para inicializar una nueva instancia con un identificador único universal (UUID) generado aleatoriamente.
requiere 'securerandom'
# Representa un identificador de usuario.
UserId = Data . define ( :id ) do # Crea un nuevo identificador de usuario. def self . create self . new ( SecureRandom . uuid ) end
def self . vacío self . nuevo ( '00000000-0000-0000-0000-000000000000' ) fin
def to_s id fin fin
Óxido
En Rust, esto se puede hacer usando una estructura de tupla que contiene un único valor. [25] Esta implementación de ejemplo implementa los rasgos Debug[26] y PartialEq[27] . El rasgo proporciona pruebas de igualdad.
PartialEq
// Representa un identificador de usuario.
#[derive(Debug, PartialEq)]
pub struct UserId ( String );
Escala
Scala tiene clases de caso que proporcionan inmutabilidad y pruebas de igualdad. [28] La clase de caso está sellada para evitar la herencia.
importar java .util .UUID
/** Representa un identificador de usuario.
*
* @constructor
* Crea un nuevo identificador de usuario.
* @param id
* El identificador de usuario.
*/
sealed case class UserId ( id : UUID )
object UserId : /** Inicializa una nueva instancia de la clase UserId. */ def create (): UserId = UserId ( UUID . randomUUID ())
Rápido
Swift tiene el CustomStringConvertibleprotocolo que se puede utilizar para proporcionar su propia representación para ser utilizada al convertir una instancia en una cadena, [29] y el Equatableprotocolo que proporciona pruebas de igualdad. [30]
Fundación de importación
/// Representa un identificador de usuario.
struct UserId : CustomStringConvertible , Equatable {
private let id : UUID
init ( _id : UUID ) { self.id = id }
var description : String {
return id . uuidString . lowercased
}
/// Crea un nuevo identificador de usuario.
static func new () -> Self {
return Self ( UUID ())
}
}
Zig
Zig tiene estructuras [31] con constantes pero por diseño no tiene sobrecarga de operadores [32] ni anulación de métodos.
/// Representa un identificador de usuario.
const UserId = struct { value : i32 ,
/// Inicializa una nueva instancia de la estructura UserId.
pub fn init ( value : i32 ) UserId { return UserId { . value = value }; } };
Véase también
Referencias
- ^ "Registros - Referencia de C#". learn.microsoft.com . Consultado el 23 de enero de 2023 .
- ^ "Modificador sellado - Referencia de C#". learn.microsoft.com . Consultado el 23 de enero de 2023 .
- ^ "Método Object.ToString (sistema)". learn.microsoft.com . Consultado el 14 de junio de 2023 .
- ^ "Estructuras - Crystal". crystal-lang.org . Consultado el 21 de febrero de 2024 .
- ^ "Estructuras, uniones - Lenguaje de programación D". dlang.org . Consultado el 30 de mayo de 2023 .
- ^ "El lenguaje de programación Apache Groovy - Orientación a objetos". groovy-lang.org . Consultado el 24 de diciembre de 2023 .
- ^ "Newtype - HaskellWiki". wiki.haskell.org . Consultado el 18 de junio de 2023 .
- ^ "Clases de registro". Centro de ayuda de Oracle . Consultado el 24 de enero de 2023 .
- ^ "JSON.stringify() - JavaScript | MDN". developer.mozilla.org . Consultado el 23 de enero de 2023 .
- ^ "Object.freeze() - JavaScript | MDN". developer.mozilla.org . Consultado el 23 de enero de 2023 .
- ^ "Object.prototype.toString() - JavaScript | MDN". developer.mozilla.org . Consultado el 23 de enero de 2023 .
- ^ "Object.prototype.valueOf() - JavaScript | MDN". developer.mozilla.org . Consultado el 23 de enero de 2023 .
- ^ "Tipos · El lenguaje Julia". docs.julialang.org . Consultado el 30 de mayo de 2023 .
- ^ "Clases en línea | Kotlin". Ayuda de Kotlin . Consultado el 23 de enero de 2023 .
- ^ "Manual de Nim". nim-lang.org . Consultado el 4 de agosto de 2023 .
- ^ "Nim by Example - Tipos distintos". nim-by-example.github.io . Consultado el 4 de agosto de 2023 .
- ^ "PHP: Métodos mágicos - Manual" www.php.net . Consultado el 23 de enero de 2023 .
- ^ "PHP: JsonSerializable::jsonSerialize - Manual" www.php.net . Consultado el 23 de enero de 2023 .
- ^ "PHP: Palabra clave final - Manual" www.php.net . Consultado el 23 de enero de 2023 .
- ^ "PHP: Traits - Manual" www.php.net . Consultado el 2 de mayo de 2023 .
- ^ "dataclasses — Clases de datos". Documentación de Python . Python Software Foundation . Consultado el 23 de enero de 2023 .
- ^ "3. Modelo de datos". Documentación de Python . Python Software Foundation . Consultado el 12 de junio de 2023 .
- ^ "Tiping — Soporte para sugerencias de tipos". Documentación de Python . Python Software Foundation . Consultado el 17 de junio de 2023 .
- ^ "Datos de clase - Documentación para Ruby 3.3". docs.ruby-lang.org . Consultado el 6 de febrero de 2023 .
- ^ "Nuevo tipo de expresión idiomática: Rust con ejemplos". doc.rust-lang.org . Consultado el 18 de junio de 2023 .
- ^ "Depuración en std::fmt - Rust". doc.rust-lang.org . Consultado el 23 de enero de 2023 .
- ^ "PartialEq en std::cmp - Rust". doc.rust-lang.org . Consultado el 23 de enero de 2023 .
- ^ "Clases de casos". Documentación de Scala . Consultado el 15 de mayo de 2023 .
- ^ "CustomStringConvertible". Documentación para desarrolladores de Apple . Consultado el 5 de mayo de 2023 .
- ^ "Documentación". docs.swift.org . Consultado el 4 de mayo de 2023 .
- ^ "Estructuras | zig.guide". zig.guide . 20 de abril de 2024 . Consultado el 15 de octubre de 2024 .
- ^ "Documentación - El lenguaje de programación Zig" . Consultado el 15 de octubre de 2024 .
Enlaces externos
- https://wiki.c2.com/?PrimitiveObsession