Контрактные библиотеки JavaScript Code? - PullRequest
14 голосов
/ 15 декабря 2010

Я только запускаю новое веб-приложение и хочу реализовать некоторую форму проверки стиля контракта в моем JavaScript. Я быстро прогуглил и наткнулся на JsContact , но синтаксис не совсем то, что я имел в виду. Кто-нибудь знает о других библиотеках?

Я думаю, я хочу, чтобы синтаксис был что-то вроде

String.prototype.padLeft = function(c, width) {
  Verify.value(c).isRequired().isNotNull().isChar();
  Verify.value(width).isRequired().isNotNull().isNumber().greaterThan(0);

  ...

  Verify.value(result).isNotNull();

  return result;
};

Хотя сборка моей собственной библиотеки с синтаксисом / методами, которые мне нужны, не займет много времени, если кто-то уже выполнил эту работу и она достаточно близка, это сэкономит мне время. Заранее спасибо.

UPDATE

У меня не будет времени работать над этим до сегодняшнего дня, поэтому я дам ему еще несколько часов, чтобы посмотреть, есть ли у кого-нибудь какие-либо рекомендации. Если нет, то я опубликую то, что создаю где-нибудь, в качестве ответа ниже, чтобы другие люди могли ссылаться на него, если они захотят.

Я также немного подумал об API, который имел бы смысл, и сейчас я думаю о чем-то вроде (надуманные примеры):

 function searchUser(firstName, middleInit, lastName) {
   Verify.value(firstName).isString().matching(/\w+/);       // Must have value
   Verify.value(middleInit).whenNotNull().isChar();          // May be null, but not undefined
   Verify.value(lastName).isString().withMinimumLengthOf(2); // Must have value

   ...
 }

 function syncTime(serverTime, now) {
   Verify.value(serverTime).isDate();         // Must have value.
   Verify.value(now).whenDefined().isDate();  // May be undefined, but not null.

 }

Моя текущая мысль заключается в том, что допуск значений NULL или UNDEFINED является нетипичным (по крайней мере, для меня?) Как таковым, вместо того, чтобы явно указывать, что для значения .isNotNull () вы фактически отключите правило для .whenDefined () или. whenNotNull (), как показано выше. Я могу сделать .whenNotNull () не ошибкой для UNDEFINED, но я вижу NULL против UNDEFINED как важное различие; посмотрим ... все остальные методы будут довольно типичными ... мысли? комментарии?

Ответы [ 4 ]

5 голосов
/ 16 декабря 2010

Учитывая, что никто не рекомендовал какие-либо существующие библиотеки, или что я схожу с ума от мысли, что это хорошая идея, я выбрал базовую библиотеку.Код не причудливый, но он делает то, что я хочу, и он достаточно быстрый для запуска (около 40 цепных проверок в мс в IE).

Я остановился на последнем синтаксисе, таком как:

function syncTime(serverTime, now) {
  Verify.value(serverTime).always().isDate();   // Cannot be undefined or null.
  Verify.value(now).whenDefined().isDate();     // Cannot be null, but must be date when defined.

  //Code
}

function searchForUser(firstName, middleInit, lastName) {
  Verify.value(firstName).always().isString().withMinimumLengthOf(2);  // Cannot be undefined or null.
  Verify.value(lastName).always().isString().withMinimumLengthOf(2);   // Cannot be undefined or null.
  Verify.value(middleInit).whenNotNull().isChar().between('A', 'Z');   // Cannot be undefined, but must be single char string when not null.

  //Code
}

Я выбрал явное «Должно иметь значение» с помощью проверки .always (), лично я нашел, что читать лучше;но я мог видеть, что некоторые идут другим путем.

Учитывая, что источник больше, чем я хочу опубликовать в этом ответе, пожалуйста, перейдите на CodePlex Wiki Page , если вы заинтересованы в источнике.Я предполагаю, что это превратилось в более свободную библиотеку утверждений;но он делает то, что мне нужно.

Обновление

Я обновил источник на связанной странице CodePlex выше.В частности, я реструктурировал класс Verify, чтобы использовать «контекст значения», а не всегда создавать новые объекты Verifier;значительно улучшена производительность IE (никогда не было проблем с FireFox или Chrome) ... теперь обрабатывает около 100 связанных проверок за мс в IE.

1 голос
/ 02 ноября 2017

Я могу предложить вам следующую библиотеку контрактов на код: код-контракты dbc .


NPM: https://www.npmjs.com/package/dbc-code-contracts

GitLab repo (home): https://gitlab.com/o.oleg/orbios.dbc#README

CI-сборки с юнит-тестами: https://gitlab.com/o.oleg/orbios.dbc/-/jobs/


Пример кода:

Dbc.Contract.throwException = true;

const domId = "my-div";
const div   = document.createElement("div");
div.id .    = domId;
document.body.appendChild(div);

const state = Dbc.Dom.removeById(domId);
Dbc.Contract.isTrue(state);
Dbc.Contract.isNull(document.getElementById(domId));

Поддерживаются следующие контракты (2-йНоябрь, 2017):

  1. isFunction
  2. isObject
  3. isSymbol
  4. isBoolean
  5. isTrue
  6. isFalse
  7. isString
  8. isEmptyString
  9. isNotEmptyString
  10. areStringsEqual
  11. isNumber
  12. isNumberLess
  13. isNumberBigger
  14. areNumbersEqual
  15. isValueNaN
  16. isDefined
  17. isUndefined
  18. isNull
  19. isArray
  20. isEmptyArray
  21. isNotEmptyArray
  22. isObjectImmutable
  23. isPromise
  24. isPrototypeOf

Кроме того, внутри методов DOM из этой библиотеки есть внутренние проверки контрактов.

0 голосов
/ 13 июня 2016

Еще один - https://www.npmjs.com/package/bycontract Это небольшая библиотека, которая ожидает выражения JSDoc (http://usejsdoc.org/) для контракта. Хороший шанс для вас уже знаком с синтаксисом.

Просто посмотрите на это в действии:

// Simple test
byContract( true, "boolean" ); // ok
// Multiple Types
byContract( 100, "string|number|boolean" ); // ok 
// Optional Parameters
function foo( bar, baz ) {
  byContract( arguments, [ "number=", "string=" ] );
}

Вот пример из реальной жизни:

/**
 * @param {number|string} sum
 * @param {Object.<string, string>} payload
 * @param {function} cb
 * @returns {HTMLElement}
 */
function foo( sum, payload, cb ) {
  // Test if the contract is respected at entry point 
  byContract( arguments, [ "number|string", "Object.<string, string>", "function" ] );
  // .. 
  var res = document.createElement( "div" );
  // Test if the contract is respected at exit point 
  return byContract( res, HTMLElement );
}
// Test it 
foo( 100, { foo: "foo" }, function(){}); // ok 
foo( 100, { foo: 100 }, function(){}); // exception - ByContractError: Value of index 1 violates the contract `Object.<string, string>` 
0 голосов
/ 04 декабря 2013

Я также собрал мою идею типовых контрактов, которая делает то, что я хочу. Думаю, немного поздно, но я все же порекомендую его для людей, желающих посмотреть: https://github.com/lindem/FirstContract

Это WIP, но мне нужно было что-то подобное.

function bmi (weight, height) {
    return weight / height * height;
}

var c = require("firstcontract").c
    /* 
     * contract applies to function taking two non-negative numbers,
     * returning a negative number: 
     */
    , contract = c(["R+0", "R+0"], "R+0")
    , cbmi = contract(bmi)
    ;

он был создан для того, чтобы я мог добавлять и удалять его, не изменяя отслеживаемую функцию, и обеспечивает лишь фиксирование вокруг функции. Это обычное дело и на нпм.

...