Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

xdbc

CallariS1.5kMIT1.0.95

A Typescript Design by Contract Framework

DbC, DesignByContract, Typescript

readme

XDbC / eX*plicit *Design b*y *Contract™

Leverages the explicit nature of metadata to provide a D*esign *by Contract™ Framework in a precise and comprehensible manner.

Do... Instead Of
@DBC.ParamvalueProvider
public method(@AE.PRE([new REGEX(/^.XDBC.\$/i)]) input : Array<string>) {
...
}
public method( input : Array<string>) {
input.forEach(( element, index ) => {
console.assert(/^.*XDBC.*$/i.test(element),"inconsistent error message");
});

...
}
@REGEX.INVARIANT(/^.*XDBC.*$/i)
public field = "XDBC";
get field() : string { return ... }
set field( toSet : string ) {
console.assert(/^.*XDBC.*$/i.test(element),"Inconsistent error message");

...
}
@REGEX.POST(/^XDBC$/i)
public method( input : unknown ) : string {
...

return result ;
}
public method( input : unknown ) : string {
...

if(!/^.*XDBC.*$/i.test(result) {
throw new Error("inconsistent error message");
}

return result ;
}
...and get consistent details about errors like: [ XDBC Infringement [ From "method" in "MyClass": [ Parameter-value "+1d,+5d,-x10y" of the 1st parameter did not fulfill one of it's contracts: Violating-Arrayelement at index 2. Value has to comply to regular expression "/^(?i:(NOW)
([+-]\d+[dmy]))$/i"]]]

What is D*esign *by Contract™ ?

D*esign *by Contract™ (DbC) is a software development approach focused on defining precise and verifiable contracts between software components. These contracts specify the preconditions that must be true when calling a component (e.g., a function or method), the postconditions guaranteed after the component's execution, and the invariants that must hold true throughout the lifetime of an object or class.

Benefits of Design by Contract:

Benefit Description
More Reliable Early error detection through contract checking
More Maintainable Clear responsibilities and expected behavior
Better Documentation Contracts as living behavior descriptions
Easier Debugging Error causes traceable through contract violations

DbC improves software quality and maintainability by explicitly defining and verifying contract conditions.

What is the difference between DbC and Assertions ?

Feature DBC with Decorators Assertions
Formality Formal, explicit in definition Informal, often within the body
Integration Metadata Built-in keyword
Features Can be more feature-rich Simple, primarily for error detection
Readability Generally good, contracts are clear Can become cluttered
Maintainability Often better, contracts are localized Can be harder to track and modify
Production Contracts can be kept or disabled Often disabled for performance

Demo & API Documentation

Check out the Demo.ts to see some examples usages and the API's documentation.

Installation

npm install --save xdbc

Usage

As by now there're nine contracts that can be used:

  • AE (Each element of the value-array has to fulfill a certain set of contracts)
  • EQ (Value has to be equal to a supplied reference value)
  • GREATER (Value has to be greater than a supplied reference value)
  • INSTANCE (Value has to be an instance of a supplied type)
  • JSON.OP (Value has to contain certain properties of certain type)
  • JSON.Parse (String-value has to be a parsable JSON)
  • OR (At least one of a set of contracts has to be fulfilled)
  • REGEX (Value has to be validated by a supplied regular expression)
  • TYPE (Value has to be of a certain type)

All of which expose a method PRE, POST and INVARIANT (precondition, postcondition and invariant).
Import the classes to use from xdbc. If parameters shall be decorated with contracts import class DBC also.

The PRE-Method can be used to decorate method-parameter: public method(@REGEX.PRE(/XDBC.*/g) input : string).
Whenever the method is invoked the value will be checked. Since parameter decorators don't have access to the parameter's value, the method itself must additionally be decorated with the ParamvalueProvider:
@DBC.ParamvalueProvider
public method(@REGEX.PRE(/XDBC.*/g) input : string)


The POST-Method can be used to decorate a method:
@EQ.POST(10)
public method() { return 10 ;}
Whenever the method returns, it's return-value will be checked.

The INVARIANT-Method can be used to decorate fields:
@REGEX.INVARIANT(/^a$/)
public testProperty = "a";

Whenever the field is assigned a value and also when initialized, the new value will be checked. So there's no need to write a getter and setter just because there's is the necessity to perform checks on the value anymore.

Certain contracts take other contracts as a parameter. For example the AE contract that applies a specified set of contracts on each element of the tagged object's value if it is an array or the object itself if it isn't: @AE.PRE([new REGEX(/^(?i:(NOW)|([+-]\d+[dmy]))$/i, new GREATER(10,"length")]).

With PRE, POST and INVARIANT decorators an optional path parameter may be specified. This parameter is a dotted path to a nested property of the tagged object that shall be checked instead of the tagged one. Thus **@DBC.INVARIANT([new REGEX(/^.$/)])** could also be defined as: **@DBC.INVARIANT([new EQ(1)],"length")**, that way demanding that the value to be set is a string with exactly one character.

Multiple instances of the class DBC with varying settings for e.g. reporting infringements may be instantiated. Which of these instances is used to report can be defined when either using PRE, POST or INVARIANT by defining their dbc parameter: **@DBC.INVARIANT([new EQ(1)],"length","MyVendor.MyDBCInstance")*, for example. The standard path (WaXCode.DBC*) leads to an automatically created instance, that is generated when the Framework is imported.

Many contracts got further features like the AE-Contract that can check specific ranges within the tagged array or the EQ- and GREATER-Contract that can be inverted turning them into not EQual- or LESS-Contracts. Check out the API for details.

A DBC's warningSettings & infringementSettings determine what happens on warnings and errors, whereas warnings are not implemented yet.

Contribution

Participation is highly valued and warmly welcomed. The ultimate goal is to create a tool that proves genuinely useful and empowers a wide range of developers to build more robust and reliable applications.