docs: function compileGettersAndSetters( attributes, computeds ) {
  	if ( !attributes || typeof attributes !== "object" || Array.isArray( attributes ) ) {
  		throw new TypeError( "definition of attributes must be object" );
  	}
  
  	if ( !computeds || typeof computeds !== "object" || Array.isArray( computeds ) ) {
  		throw new TypeError( "definition of computeds must be object" );
  	}
  
  
  	const definition = {};
  
  	const attributeNames = Object.keys( attributes );
  	for ( let i = 0, length = attributeNames.length; i < length; i++ ) {
  		( function( name ) {
  			switch ( name ) {
  				case "prototype" :
  				case "constructor" :
  				case "super" :
  					break;
  
  				default :
  					if ( !Model.prototype.hasOwnProperty( name ) ) {
  						definition[name] = {
  							get() {
  								return this.properties[name];
  							},
  							set( value ) {
  								this.properties[name] = value;
  							},
  						};
  					}
  			}
  		} )( attributeNames[i] );
  	}
  
  	const computedNames = Object.keys( computeds );
  	for ( let i = 0, length = computedNames.length; i < length; i++ ) {
  		const name = computedNames[i];
  
  		( function( computedName, computedFn ) {
  			switch ( computedName ) {
  				case "prototype" :
  				case "constructor" :
  				case "super" :
  					break;
  
  				default :
  					if ( !Model.prototype.hasOwnProperty( computedName ) && !definition.hasOwnProperty( computedName ) ) {
  						definition[computedName] = {
  							get() {
  								return computedFn.call( this );
  							},
  							set( value ) {
  								computedFn.call( this, value );
  							},
  						};
  					}
  			}
  		} )( name, computeds[name] );
  	}
  
  	return definition;
  }