Строго типизированный идентификатор
Строго типизированный идентификатор — это определяемый пользователем тип данных , который служит идентификатором или строго типизированным ключом . Это решение проблемы запаха кода «примитивной одержимости» , упомянутого Мартином Фаулером . По возможности тип данных должен быть неизменяемым . Реализации обычно выполняют тестирование на равенство, сериализацию и привязку модели.
Строго типизированный идентификатор обычно оборачивает тип данных, используемый в качестве первичного ключа в базе данных, например строку, целое число или универсальный уникальный идентификатор (UUID).
Веб-платформы часто можно настроить для моделирования свойств привязки в моделях представлений, которые являются строго типизированными идентификаторами. Объектно-реляционные преобразователи часто можно настроить с помощью преобразователей значений для сопоставления данных между свойствами модели с использованием строго типизированных типов данных идентификаторов и столбцов базы данных.
Примеры
[ редактировать ]С#
[ редактировать ]В C# есть записи, которые обеспечивают проверку неизменяемости и равенства. [1] Запись запечатывается во избежание наследования . [2] Он переопределяет встроенный ToString()
метод. [3]
Этот пример реализации включает статический метод, который можно использовать для инициализации нового экземпляра случайно сгенерированным глобальным уникальным идентификатором (GUID).
/// <summary>
/// Represents a user identifier.
/// </summary>
/// <param name="Id">The user identifier.</param>
public sealed record UserId(Guid Id)
{
/// <summary>
/// Initializes a new instance of the <see cref="UserId" /> record.
/// </summary>
/// <returns>A new UserId object.</returns>
public static UserId New() => new(Guid.NewGuid());
public override string ToString() => Id.ToString();
}
С++
[ редактировать ]В C++ есть структуры, но нет неизменяемости, поэтому здесь поле id помечено как частное с помощью метода с именем value()
чтобы получить значение.
struct UserId {
UserId(const string _id)
{
id = _id;
}
string value() const
{
return id;
}
bool operator==(const UserId& rhs) const
{
return value() == rhs.value();
}
private:
string id;
};
ostream& operator << (ostream &os, const UserId &id)
{
return os << id.value() << std::endl;
}
Кристалл
[ редактировать ]Стандартная библиотека Crystal предоставляет макрос записи для создания записей, которые являются неизменяемыми структурами, и позволяет переопределять встроенные структуры. to_s
метод. [4]
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 имеют неизменяемые структуры. [5]
import std;
/** Represents a user identifier. */
immutable struct UserId
{
immutable UUID id;
/** Initializes a new instance of the UserId struct. */
this(immutable string id)
{
this.id = UUID(id);
}
public static UserId create()
{
return UserId(randomUUID.toString());
}
string toString()
{
return this.id.toString();
}
}
Дарт
[ редактировать ]В Dart есть классы с перегрузкой операторов.
import 'package:meta/meta.dart';
/// Represents a user identifier.
@immutable
final class UserId {
final String id;
/// Initializes a new instance of the UserId struct.
const UserId(this.id);
@override
operator ==(other) => other is UserId && other.id == id;
@override
int get hashCode => id.hashCode;
@override
String toString() => id;
}
Ф#
[ редактировать ]F# позволяет вам переопределить Equals
, GetHashCode
и ToString
методы.
open System
/// <summary>
/// Represents a user identifier.
/// </summary>
/// <param name="id">The user identifier.</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()
Идти
[ редактировать ]У Go есть структуры, обеспечивающие проверку равенства. Однако Go не обеспечивает неизменность.
// Represents a user identifier.
type UserId struct{ id string }
// Creates a new user identifier.
func NewUserId(id string) UserId { return UserId{id: id} }
func (x UserId) String() string { return x.id }
классный
[ редактировать ]В Groovy есть классы записей, которые обеспечивают проверку неизменяемости и равенства. [6]
/**
* Represents a user identifier.
*
* @param id The user identifier.
*/
record Message(String id) {
String toString() { id }
}
Хаскелл
[ редактировать ]Haskell может создавать пользовательские типы данных, используя newtype
ключевое слово. [7] Он обеспечивает проверку равенства с использованием Eq
стандартный класс и печать с использованием Read
и Show
стандартные занятия.
-- Represents a user identifier.
newtype UserId = UserId String deriving (Eq, Read, Show)
Ява
[ редактировать ]В Java есть записи, обеспечивающие проверку равенства. [8]
Запись объявляется с использованием final
Ключевое слово-модификатор для предотвращения наследования. Он переопределяет встроенный toString()
метод.
import java.util.UUID;
/**
* Represents a user identifier.
* @param id The user identifier.
*/
public final record UserId(UUID id) {
/**
* Initializes a new instance of the UserId record.
* @return A new UserId object.
*/
public static UserId newId() {
return new UserId(UUID.randomUUID());
}
public String toString() {
return id.toString();
}
}
JavaScript
[ редактировать ]Этот пример реализации JavaScript предоставляет toJSON
метод, используемый JSON.stringify()
[9] функция для сериализации класса в простую строку вместо составного типа данных .
Он вызывает Object.freeze()
чтобы сделать экземпляр неизменяемым. [10]
Он переопределяет встроенный toString()
метод [11] и valueOf()
метод. [12]
class UserId {
#id;
constructor(id) {
if (id == undefined) {
throw new TypeError("Argument is null or undefined.");
}
this.#id = id;
Object.freeze(this);
}
static empty = new this.prototype.constructor("00000000-0000-0000-0000-000000000000");
static new() {
return new this.prototype.constructor(crypto.randomUUID());
}
equals(id) {
return id instanceof this.constructor && this.#id === id.valueOf();
}
toJSON() {
return this.#id;
}
toString() {
return this.#id;
}
valueOf() {
return this.#id;
}
}
Юлия
[ редактировать ]У Джулии есть неизменяемые составные типы данных. [13]
using UUIDs
"Represents a user identifier."
struct UserId
id::UUID
end
Base.string(userId::UserId) = userId.id
Котлин
[ редактировать ]В Котлине есть «встроенные классы». [14]
/**
* Represents a user identifier.
*
* @property id The user identifier.
* @constructor Creates a user identifier.
*/
@JvmInline
public value class UserId(public val id: String) {
override fun toString() = id
}
Nim
[ редактировать ]У Ним есть «отдельные типы». [15] [16]
## Represents a user identifier.
type UserId* = distinct string
PHP
[ редактировать ]Этот пример реализации PHP реализует __toString()
магический метод. [17]
Кроме того, он реализует JsonSerializable
интерфейс, который используется встроенным json_encode
функция для сериализации класса в простую строку вместо составного типа данных . [18]
Класс объявляется с использованием final
Ключевое слово-модификатор для предотвращения наследования. [19]
В PHP есть особенности, позволяющие повторно использовать код. [20]
/**
* Represents a user identifier.
*/
final class UserId implements JsonSerializable
{
use StronglyTypedIdentifier;
}
/**
* Provides methods for use with strongly typed identifiers.
*/
trait StronglyTypedIdentifier
{
/**
* Initializes a new instance of the UserId object.
* @param string $id The user identifier.
*/
public function __construct(public readonly string $id) {}
/**
* Creates a new user identifier.
*/
public static function new(): self
{
return new self(bin2hex(random_bytes(16)));
}
public function jsonSerialize(): string
{
return $this->id;
}
public function __toString(): string
{
return $this->id;
}
}
Питон
[ редактировать ]В Python есть классы данных, которые обеспечивают проверку на равенство и могут быть сделаны неизменяемыми с помощью frozen
параметр. [21] Это отменяет __str__
метод грома. [22]
Этот пример реализации включает статический метод, который можно использовать для инициализации нового экземпляра с помощью случайно сгенерированного универсального уникального идентификатора (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 также есть NewType
который можно использовать для создания новых типов данных. [23]
from typing import NewType
UserId = NewType('UserId', int)
Руби
[ редактировать ]В Ruby есть классы данных, которые обеспечивают проверку на равенство и являются неизменяемыми. [24] Он переопределяет встроенный to_s
метод.
Этот пример реализации включает статический метод, который можно использовать для инициализации нового экземпляра с помощью случайно сгенерированного универсального уникального идентификатора (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 это можно сделать с помощью структуры кортежа, содержащей одно значение. [25] Этот пример реализации реализует Debug
[26] и PartialEq
[27] черты . PartialEq
черта обеспечивает проверку равенства.
// Represents a user identifier.
#[derive(Debug, PartialEq)]
pub struct UserId(String);
Скала
[ редактировать ]В Scala есть тематические классы, которые обеспечивают проверку неизменяемости и равенства. [28] Класс Case запечатан для предотвращения наследования.
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())
Быстрый
[ редактировать ]У Свифта есть CustomStringConvertible
протокол, который можно использовать для предоставления собственного представления, которое будет использоваться при преобразовании экземпляра в строку, [29] и Equatable
протокол, который обеспечивает проверку равенства. [30]
import Foundation
/// Represents a user identifier.
struct UserId: CustomStringConvertible, Equatable {
private let id: UUID
init(_ id: UUID) {
self.id = id
}
var description: String {
return id.uuidString.lowercased
}
/// Creates a new user identifier.
static func new() -> Self {
return Self(UUID())
}
}
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ «Записи — справочник по C#» . Learn.microsoft.com . Проверено 23 января 2023 г.
- ^ «модификатор sealed — Справочник по C#» . Learn.microsoft.com . Проверено 23 января 2023 г.
- ^ «Метод Object.ToString (система)» . Learn.microsoft.com . Проверено 14 июня 2023 г.
- ^ «Структуры – Кристалл» . Crystal-lang.org . Проверено 21 февраля 2024 г.
- ^ «Структуры, объединения — язык программирования D» . dlang.org . Проверено 30 мая 2023 г.
- ^ «Язык программирования Apache Groovy — Объектная ориентация» . groovy-lang.org . Проверено 24 декабря 2023 г.
- ^ «Ньютайп — HaskellWiki» . wiki.haskell.org . Проверено 18 июня 2023 г.
- ^ «Рекордные занятия» . Справочный центр Oracle . Проверено 24 января 2023 г.
- ^ «JSON.stringify() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
- ^ «Object.freeze() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
- ^ «Object.prototype.toString() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
- ^ «Object.prototype.valueOf() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
- ^ «Типы · Язык Джулии» . docs.julialang.org . Проверено 30 мая 2023 г.
- ^ «Встроенные классы | Котлин» . Котлин в помощь . Проверено 23 января 2023 г.
- ^ «Руководство Нима» . nim-lang.org . Проверено 4 августа 2023 г.
- ^ «Ним на примере – различные типы» . nim-by-example.github.io . Проверено 4 августа 2023 г.
- ^ «PHP: Магические методы — Руководство» . www.php.net . Проверено 23 января 2023 г.
- ^ «PHP: JsonSerializable::jsonSerialize — Руководство» . www.php.net . Проверено 23 января 2023 г.
- ^ «PHP: последнее ключевое слово — руководство» . www.php.net . Проверено 23 января 2023 г.
- ^ «PHP: Черты — Руководство» . www.php.net . Проверено 2 мая 2023 г.
- ^ «классы данных — классы данных» . Документация Python . Фонд программного обеспечения Python . Проверено 23 января 2023 г.
- ^ «3. Модель данных» . Документация Python . Фонд программного обеспечения Python . Проверено 12 июня 2023 г.
- ^ «печать — Поддержка подсказок по типу» . Документация Python . Фонд программного обеспечения Python . Проверено 17 июня 2023 г.
- ^ «Данные класса — Документация для Ruby 3.3» . docs.ruby-lang.org . Проверено 6 февраля 2023 г.
- ^ «Идиома нового типа — пример Rust» . doc.rust-lang.org . Проверено 18 июня 2023 г.
- ^ «Отладка в std::fmt — Rust» . doc.rust-lang.org . Проверено 23 января 2023 г.
- ^ «PartialEq в std::cmp — Rust» . doc.rust-lang.org . Проверено 23 января 2023 г.
- ^ «Случайные классы» . Документация Скала . Проверено 15 мая 2023 г.
- ^ «ПользовательскаяСтрокаКонвертируемый» . Документация разработчика Apple . Проверено 5 мая 2023 г.
- ^ «Документация» . docs.swift.org . Проверено 4 мая 2023 г.