Друкарня від WE.UA

Паттерн “Специфікація“ в JS чи потрібен він?

Одним з найскладніших для розуміня в мене був паттерн специфікація. Саме через те що не дуже зрозуміло як його використовувати і навіщо. Сьогодні я спробую вам пояснити для чого він. І запропонувати свою версію реалізації цього паттерну, яку як на мене можно доволі ефективно використовувати

Що це таке?

Специфікація - це патерн проектування який дозволяє комбінувати бізнес-правила за допомогою булевої логіки. Складно? От і мені так здалось на перший погляд. Насправді найпростіша реалізація цього патерну виглядає ось так

class ByIdSpecification {
  constructor(private id: string) {}

  isSatisfiedBy(candidate: any): boolean {
    return candidate.id === this.id
  }

}

Як це використовувати?

const array = [{ id: 1, name: "Viktor" }, {id: 2, name: "Oleg"}]

const specification = new ByIdSpecification(1)

const result = array.find(specification.isSatisfiedBy)

Тепер виглядає простіше. Але для чого це? Виглядає як оверінженірінг. Бо цю саму задачу можно зробити за допомогою набагато меншого коду.

Що ж подивимось туди де це використовується найчастіше С#. Тут цей паттерн використовують для того щоб уніфікувати запити до бази данних. Так як фреймворк Entity спілкується з базою за допомогою функцій подібно функції filter або find в JS

Але в JS а конкретно в Node.js коли мі спілкуємось с базою за допомогою query обєктів. Наприклад в одній з найпопулярніших баз данний MongoDB звичайний запит до моделі виглядає от так

model.find({ something: 2 })

Я пропоную свою реалізацію

Я не претендую на безальтернативний варіант, але в мене є одна реалізація яка допомагає використовувати цей паттерн навіть в наших умовах

class ByIdSpecification {
  constructor(private id: string) {}

  isSatisfiedBy() {
    return {
      id: this.id
    }
  }

}

model.find(new ByIdSpecification(1).isSatisfiedBy())

Розумію що все ще виглядає як оверінженірінг. Але навіть зараз ми вже маємо 2 переваги.

  1. Збільшена читаємість

  2. Можливість перевикористання

Тобто купка незрозумілих параметрів в квері стають осмисленими данними. Наприклад от так можно зробити специфікацію для пошука географічних данних

class GeoSpecification {
  constructor(private lat: number, private lng: number){}

  isSatisfiedBy() {
    return {
      lat: this.lat,
      lng: this.lng
    }
  }

}

Але головна фішка ціього паттерну попереду.

Булева логіка в кущах

Доки я повністю не зрозумів цю частину, я не бу наскільки закоханим у цей паттерн. Специфікації можно комбінувати. В визначенні патерна фігурує фраза про булеву логіку. Це найголовніша перевага цього патерну. Подивимось на реалізацію цього в JS. На прикладі одніє булевої функції AND

interface ISpecification {
  isSatifiedBy()
  and(specification: ISpecification): ISpecification
}

class CompositeSpecification implements ISpecification {
  
  isSatisfiedBy() {
    throw NotImplementError()
  }

  and(specification: ISpecification): ISpecification {
    return new AndSpecification(this, specification)
  }

}


class AndSpecification extends CompositeSpecification {
  constructor(left: ISpecification, right specification) {
    super()
    this.left = left;
    this.right = right;
  }

  isSatisfiedBy(): {
    return this.left.isSatisfiedBy() && this.right.isSatifiedBy()
  
  }

}


class ByIdSpecification extends CompositeSpecification {
  constructor(private id: string) {}
  
  isSatisfiedBy() {
    return {
      id: this.id
  } 
}

class GeoSpecification extends CompositeSpecification {
  constructor(private lat: number, private lng: number) {}
  
  isSatisfiedBy() {
    return {
      lat: this.lat,
      lng: this.lng
    }
  }

}

const query = new ByIdSpecification(1)
  .and(new GeoSpecification(123, 321))
  .isSatisfiedBy()

model.find(query)

Тепер ми можемо використовувати комбінації цих специфікації що дозволить нам покращити перевикористовування. Та зменшити повторення. Також можно реалізовувати і інші булеві функції наприклад or але є одне обмеження. Туди пролазять деталі реалізації бази. Наприклад

class OrSpecification extends CompositeSpecification {
  constructor(left: ISpecification, right: ISpecificaition) {
    super()
    this.left = left;
    this.reight = right
  }

  isSatisfiedBy() {
    return {
      $or: [this.left.isSatifiedBy(), this.right.isSatifiedBy()]
    }
  }

}

Але є і хороша частина в цьому. Якщо вам захочеться змінити базу посеред проекту(це буває рідко, а ле хто вас бешкетників знає). То ви зможете змінити спосіб комбінації лише в одному місці

Висновки

Стандартну реалізацію цього патерно можно використовувати наприклад для фронтенда з редаксом. Або будь де де в нас є масив inmemory який ми можемо перебирати за допомогою функцій filter або find. Мою реалізацію можно використовувати на повну силу для того щоб робити пошук по базі. Як це наприклад робиться в С#. Буду радий почути коментарі або критику такого підходу.

Статті про вітчизняний бізнес та цікавих людей:

  • Як обрати конструктор сайтів для товарного бізнесу

    Дізнайтесь, як обрати конструктор сайтів для товарного бізнесу. Практичні поради: готові шаблони, модульність, інтеграції, аналітика, безкоштовний тариф та масштабування для ефективного запуску та контролю заявок.

    Теми цього довгочиту:

    Конструктор Сайтів
  • Як модні бренди формують культуру та впливають на глобальні fashion-тренди

    Модні бренди часто стають символами ідентичності. Вони впливають на вибір способу життя не тільки в одязі — розкішні годинники, парфуми, товари для дому та враження підкріплюють культурні наративи успіху, смаку та вишуканості.

    Теми цього довгочиту:

    Мода
  • Створити блог на Друкарні - швидко, легко та безкоштовно

    Друкарня - це зручне та безкоштовне середовище для ведення власного блогу. В даній статті ми розповідаємо про основні переваги та функціональні можливості для того, щоб зацікавити нових авторів створити власний блог на Друкарні. Будь ласка, поширте цю інформацію.

    Теми цього довгочиту:

    Друкарня
  • Чому Google Merchant Center може заблокувати обліковий запис?

    Одним з найбільш ефективних каналів продажів є система Google Merchant Center. Правда, акаунт в ній може бути несподівано заблокований, якщо при його налаштуванні були порушені правила системи. У статті розглянемо підводні камені і дамо відповідь як уникнути блокування

    Теми цього довгочиту:

    Google Merchant Center
  • Бухгалтерський супровід ФОП: сучасний підхід до обліку

    Завдяки розвитку інформаційних технологій, впровадженню сучасних рішень і сервісів процес ведення бухобліку бізнесу став значно простішим і зручним. З іншого боку, ті ж технології додали бухгалтерам роботи – з обліком онлайн-продажів і надходжень у валюті, CRM-системами та ін.

    Теми цього довгочиту:

    Бухгалтерський Облік Фоп
Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Владислав Лєсной
Владислав Лєсной@unnsin we.ua/unnsin

5Довгочити
726Прочитання
17Підписники
На Друкарні з 15 квітня

Більше від автора

  • Clear Architecture для бекенда на JS

    Кожен хто займається розробкою певний час приходить до слова архітектура. Сьогодні ми подивимось на одну з парадигм проектування архітектури через призму типового JS бекенду.

    Теми цього довгочиту:

    Clean Architecture
  • Паттерн “Репозиторій“ в JS

    В попередній статті ми розібрались з паттерном Специфікація Сьогодні ми поговоримо про логічне продовження паттерн репозиторій.

    Теми цього довгочиту:

    Js

Це також може зацікавити:

  • Google Таблиці та Телеграм бот(ч.1)

    Теорія про створення Телеграм ботів сумісно з Google Таблицями. Аналіз інструментів, короткі відомості та загальна інформація.

    Теми цього довгочиту:

    It
  • Які книги з JavaScript слід читати у 2024 році?

    Чому варто вивчати JavaScript у 2024 році? Які книги обрати для вивчення цієї мови програмування? У цій статті ми розглядаємо ключові аргументи на користь вивчення JavaScript у 2024 році та поділимося переліком ресурсів, які допоможуть вам у цьому.

    Теми цього довгочиту:

    Javascript
  • λanguage: Неформальний опис мови

    Автор пояснює, як написати парсер, інтерпретатор, компілятор, та інші складові власної мови програмування. Описується синтаксис мови, особливості реалізації функцій, умовних конструкцій та інших елементів мови.

    Теми цього довгочиту:

    Js

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Це також може зацікавити:

  • Google Таблиці та Телеграм бот(ч.1)

    Теорія про створення Телеграм ботів сумісно з Google Таблицями. Аналіз інструментів, короткі відомості та загальна інформація.

    Теми цього довгочиту:

    It
  • Які книги з JavaScript слід читати у 2024 році?

    Чому варто вивчати JavaScript у 2024 році? Які книги обрати для вивчення цієї мови програмування? У цій статті ми розглядаємо ключові аргументи на користь вивчення JavaScript у 2024 році та поділимося переліком ресурсів, які допоможуть вам у цьому.

    Теми цього довгочиту:

    Javascript
  • λanguage: Неформальний опис мови

    Автор пояснює, як написати парсер, інтерпретатор, компілятор, та інші складові власної мови програмування. Описується синтаксис мови, особливості реалізації функцій, умовних конструкцій та інших елементів мови.

    Теми цього довгочиту:

    Js