JavaScript代码合同库?

时间:2010-12-15 00:14:47

标签: javascript code-contracts

我刚刚启动了一个新的Web应用程序,我想在我的JavaScript中实现某种形式的contract'esque样式验证。我做了一些快速的谷歌搜索,并遇到了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;
};

虽然将我自己的库与我想要的语法/方法放在一起不会花费很长时间,但如果其他人已经完成了工作并且它足够接近,那么它将节省我一些时间。提前谢谢。

更新

直到今天下午我才有时间研究这个问题,所以我会再花几个小时来看看是否有人有任何建议。如果没有,我会发布我在某处创建的任何内容作为下面的答案供其他人参考,如果他们愿意的话。

我还考虑了一些有意义的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()如上图所示。我可能会在UNDEFINED上使.whenNotNull()没有错误,但我认为NULL与UNDEFINED是一个重要的区别;我们会看到......所有其他方法都很典型......想法?评论

4 个答案:

答案 0 :(得分:5)

鉴于没有人推荐任何现有的图书馆,或者我认为这是一个好主意我疯了,我继续把一个基本的图书馆拼凑起来。代码不是很花哨,但它可以实现我想要的,并且运行起来相当快(IE中每毫秒大约40个链式检查)。

我选择了最终语法,如:

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的问题)...现在在IE中每ms处理大约100个链式检查。

答案 1 :(得分:1)

我可能会建议您使用下一个代码合同库: dbc-code-contracts

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

GitLab回购(主页):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));

支持以下合同(2017年11月2日):

  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
  25. 此外,还有来自此库的DOM方法内部合同检查。

答案 2 :(得分:0)

我也把我的类型合同的想法放在一起,这就是我想要的。我想,有点晚了,但我会建议那些愿意看的人: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)
    ;

它被创建,以便我可以添加和删除它而不更改监视本身的功能,并提供围绕该功能的钳位。这是常见问题,而且是在npm。

答案 3 :(得分:0)

还有一个 - 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>`