Jump to content

Строго типизированный идентификатор

Диаграмма классов UML для строго типизированного идентификатора.
A UML class diagram for a strongly typed identifier.

Строго типизированный идентификатор — это определяемый пользователем тип данных , который служит идентификатором или строго типизированным ключом . Это решение проблемы запаха кода «примитивной одержимости» , упомянутого Мартином Фаулером . По возможности тип данных должен быть неизменяемым . Реализации обычно выполняют тестирование на равенство, сериализацию и привязку модели.

Строго типизированный идентификатор обычно оборачивает тип данных, используемый в качестве первичного ключа в базе данных, например строку, целое число или универсальный уникальный идентификатор (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 предоставляет 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
}

У Ним есть «отдельные типы». [15] [16]

## Represents a user identifier.
type UserId* = distinct string

Этот пример реализации 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())
    }
}

См. также

[ редактировать ]
  1. ^ «Записи — справочник по C#» . Learn.microsoft.com . Проверено 23 января 2023 г.
  2. ^ «модификатор sealed — Справочник по C#» . Learn.microsoft.com . Проверено 23 января 2023 г.
  3. ^ «Метод Object.ToString (система)» . Learn.microsoft.com . Проверено 14 июня 2023 г.
  4. ^ «Структуры – Кристалл» . Crystal-lang.org . Проверено 21 февраля 2024 г.
  5. ^ «Структуры, объединения — язык программирования D» . dlang.org . Проверено 30 мая 2023 г.
  6. ^ «Язык программирования Apache Groovy — Объектная ориентация» . groovy-lang.org . Проверено 24 декабря 2023 г.
  7. ^ «Ньютайп — HaskellWiki» . wiki.haskell.org . Проверено 18 июня 2023 г.
  8. ^ «Рекордные занятия» . Справочный центр Oracle . Проверено 24 января 2023 г.
  9. ^ «JSON.stringify() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
  10. ^ «Object.freeze() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
  11. ^ «Object.prototype.toString() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
  12. ^ «Object.prototype.valueOf() — JavaScript | MDN» . http://developer.mozilla.org . Проверено 23 января 2023 г.
  13. ^ «Типы · Язык Джулии» . docs.julialang.org . Проверено 30 мая 2023 г.
  14. ^ «Встроенные классы | Котлин» . Котлин в помощь . Проверено 23 января 2023 г.
  15. ^ «Руководство Нима» . nim-lang.org . Проверено 4 августа 2023 г.
  16. ^ «Ним на примере – различные типы» . nim-by-example.github.io . Проверено 4 августа 2023 г.
  17. ^ «PHP: Магические методы — Руководство» . www.php.net . Проверено 23 января 2023 г.
  18. ^ «PHP: JsonSerializable::jsonSerialize — Руководство» . www.php.net . Проверено 23 января 2023 г.
  19. ^ «PHP: последнее ключевое слово — руководство» . www.php.net . Проверено 23 января 2023 г.
  20. ^ «PHP: Черты — Руководство» . www.php.net . Проверено 2 мая 2023 г.
  21. ^ «классы данных — классы данных» . Документация Python . Фонд программного обеспечения Python . Проверено 23 января 2023 г.
  22. ^ «3. Модель данных» . Документация Python . Фонд программного обеспечения Python . Проверено 12 июня 2023 г.
  23. ^ «печать — Поддержка подсказок по типу» . Документация Python . Фонд программного обеспечения Python . Проверено 17 июня 2023 г.
  24. ^ «Данные класса — Документация для Ruby 3.3» . docs.ruby-lang.org . Проверено 6 февраля 2023 г.
  25. ^ «Идиома нового типа — пример Rust» . doc.rust-lang.org . Проверено 18 июня 2023 г.
  26. ^ «Отладка в std::fmt — Rust» . doc.rust-lang.org . Проверено 23 января 2023 г.
  27. ^ «PartialEq в std::cmp — Rust» . doc.rust-lang.org . Проверено 23 января 2023 г.
  28. ^ «Случайные классы» . Документация Скала . Проверено 15 мая 2023 г.
  29. ^ «ПользовательскаяСтрокаКонвертируемый» . Документация разработчика Apple . Проверено 5 мая 2023 г.
  30. ^ «Документация» . docs.swift.org . Проверено 4 мая 2023 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 752f80f18bb696164192304ef9dafbd4__1721113920
URL1:https://arc.ask3.ru/arc/aa/75/d4/752f80f18bb696164192304ef9dafbd4.html
Заголовок, (Title) документа по адресу, URL1:
Strongly typed identifier - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)