• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

SproutCore-Documentation-Guidelines

Page history last edited by majd87@... 14 years, 8 months ago

Sproutcore Documentation Guidelines (Abbot Draft)

 
SproutCore uses a customized version of JSDoc with some SproutCore specific extensions and has an application to view and generate documentation. To access the documentation tool, go to the following URL: http://yourapplicationurl:port/applicationname/-docs. To generate documentation for your application, click the button at the bottom left-hand corner of the page.
 
The SproutCore build tools do help you and create some scaffolding for newly generated files that include JSDoc compatible comments which will allow your files to appear in the SproutCore documentation for your app. However, in order to document your application code, you will need to follow the guidelines below. it is important to note that it is important to document your code in such a manner that someone who knows SproutCore but not this specific code, can pick up and without too much effort extend it or fix bugs. You don't need to be excessive in your level of commenting because that doesn't help anyone. Being focused and terse in your comments is encouraged.
 
The following tags that are most commonly used in documenting SproutCore applications. The covered tags and the examples of how to document files, properties, and functions are some of the recommended ways that they have been used so far. It is not necessarily the only way. JSDoc allows for many other types of tags that could be useful. If there are other property tags that could be useful, especially in the context of SproutCore, please feel free to add to the specifications and the documentation tools!
 
 

Mapped JSDoc Tags

First, for the people who are already familiar with JSDoc, we map some existing tags to SproutCore specific tag names:
 

SC Tag        

JSDoc Tag

@method =>

 

@function

 

@delegate =>

 

@namespace

 

@property =>

 

@field

 

@singelton =>

 

@class

 

 

 

New JSDoc Tags For SproutCore*

 

@copyright, @binding, @observes, @commonTask, @isReadOnly

 

*These tags will be explained further later in the document. 

 

 

Documenting at the File Level 

 

@class

This is used in the class header to signify that you're defining a class. When using sc-gen, this is automatically filled in. 

 

@extends ClassName.That.Is.Extended

This is used to name the classes that are extended. You can have multiple @extends entries. When using sc-gen, this is automatically filled in.

 

@since YourAppVersion.4.0

This an optional tag that allows you to specify which version of the application that this file was introduced. When using sc-gen, if the @version tag is specified in your config, new files will use that version number.

 

@author Author Q. Name

The author of your file. You can have multiple authors and they are specified in your config file. If none are specified, it is a default value. When using sc-gen, this is automatically filled in.

 

@static

A class is static if it is a singelton such as a controller. Otherwise, it is not.

 

@copyright

This is a copyright statement for your file as specified in the config. If not specified there, it is omitted. When using sc-gen, this is automatically filled in.

 

Below is an example of using sc-gen to create a controller and the default header created:

 

     %sc-gen controller myapp/canvas

 

     // ==========================================================================

     // MyApp.ViewController

     // ==========================================================================

 

     require('core');

 

     /** @class     

          (Document Your View Here)

 

          @extends SC.Object

          @author AuthorName

          @since 0.1

          @static

     */

     MyApp.viewController = SC.Object.create(

          /** @scope MyApp.viewController */ {

 

      // TODO: Add your own code here.

 

     }) ;

 

You can see that sc-gen created some basic information for you. In order to get the most out of your documentation, it is recommended to add additional information to your class header. By adding your own class description you can show at a high-level of the class is supposed to do. Also, by specifying the @author, @version, and @copyright tags in your config file, you can get even more out of sc-gen:

 

     // ==========================================================================

     // MyApp.ViewController

     // ==========================================================================

 

     require('core');

 

     /** @class

 

          This controller controls the view that are currently enabled in the application

 

          @extends SC.Object

          @author Peter Bergstrom

          @author Charles Jolley

          @since MyApp 1.0

          @copyright 2008-2009. Foo Bar Enterprises, Inc. All rights reserved.

          @static

     */

     MyApp.viewController = SC.Object.create(

          /** @scope Test.viewController */ {

 

       // TODO: Add your own code here.

 

     }) ;

 

 

Defining Properties

 

SproutCore at a lot of different options that can be used while specifying properties. A property is a variable defined on a class or object. It is recommended that you at least use the @type tag. When you describe a property it is recommended that you add some kind of description. The first sentence of your description will be the heading and any subsequent sentences will be part of the discussion section.

 

@property {type}

This is used to signify that you are documenting a property. In order for something to show up as a property this tag is required in all cases except for bindings. Types can be (Integer, String, Double, Float, Object, etc).

 

      Example usage of the @property tag:

     /**

          The number of views available.

 

          @property {Integer}

     */

     viewCount: 0,

 

 

@default defaultValue

This is used to document the default value of a property. If you don't know the default value and it is not read by something, the @default tag is not useful. This tag is optional.

 

     Example usage of the @default tag:

/**

The currently visible view.

  

@property {String}

@default 'emptyView'

*/

currentView: 'emptyView',

 

 

@private

When this tag is present, the property is documented as private. This tag is optional.

 

     Example usage of the of @private tag:

/** 

Used for internal bookkeeping of the number of views initializaed.

 

@property {Integer}

@private

@default 1

*/

 _initalizedViewCount: 0,

 

 

@isReadOnly

This is used to signify if a property is intended to be read only.  This tag is optional.

 

     Example usage of the @isReadOnly tag:

/**

This is the zoom step value of the slider.

 

@property {Integer}

@isReadOnly

@default 1

*/

zoomStep: 1,

 

 

@binding 

This used specifically for bindings and replaces the @property tag.  This tag takes the binding's path and adds it to the documentation.

 

     Example usage of the @binding tag:

/**

View threshold binding. Don't show items with less. 

 

@binding {Integer}

*/

viewThresholdBinding:  "MyApp.canvasController.viewThreshold",

 

 

@commonTask Common Task Name

This is used to group properties and methods/functions together in the documentation as part of a common task. This tag is optional.

 

Example usage of the @commonTask tag:

/**

Set to YES when the left view is visible.

 

@property {Boolean}

@default NO

@commonTask View Management

*/

leftViewShowing: NO,

 

 

 

Defining Functions

 

Functions are commonly defined as part of an object or class. It is important to describe what a function expects to be passed as a parameter as well as what it is expected to return. The general rule is that every function should have a description and if it has are parameters and an expected return value, those should be document under all circumstances.

 

Example of a typical function without any bells and whistles. Note that only the description of the function is present.

 

     /** 

     Zoom in towards the max value.

     */

     zoomIn: function()

     {

this.set('zoomValue', Math.min(this.get('zoomValueMax'), (this.get('zoomValue')+this.get('zoomStep'))));

     },

 

 

@param {type} paramName Description of parameter passed in to a function.

 

This is used to specify the details of a parameter that is passed into a function. Multiple parameters are listed on a separate line.

There are three things that you need to add:

     First, the type of the param inside of {}.

     Second, the name of the parameter.

     Third, a human-readable description of what the parameter is. It only shows the first sentence up until the period.

 

     Example usage of the @param tag. In this case, two params being passed in to a function.

/**

Set the preview box position and percentages.

 

@param {Integer} pctX The x percentage.

@param {Integer} pctY The y percentage.

*/

setParams: function(pctX, pctY)

{

this._setPreviewPosition((this._bounds.x+this._bounds.width*pctX), (this._bounds.y+this._bounds.height*pctY));

this._setPercentage();

},

 

 

@returns {type} Description of what is returned.

This is used to specify what the function returns. 

It is consists of two parts: 

     First, there is the type inside of {}. 

     Then, there is the description of what is returned.

If the function can return a mixed value, you can specify it's type inside the curly braces separated with |. {Array|Boolean}.

 

 

     Example usage of the @returns tag. In this case, there are two possible return types.

/** 

Converts an array of guids to a comma separated string of guids, if it is not an array, it is just return as is.

 

@param {Object|String} object The potential array of guids. 

@returns {String} The guids string.

*/

_handleMult: function(object)

{

if(typeof object == 'object')

{

object = object.join(',');

}

return object;

},

 

 

@private

When this tag is present, the function is documented as private. This tag is optional.

 

     Example usage of the @private tag:

/**

Generate a circle DIV element. 

 

@private

 

@param {DOM Element} childNode A child node to append to the circle. This is usually a text element.

@param {String} guid The guid of the paper.

@param {String} cacheStr The guid cache string.

@param {String} lineColor The line color

 

@returns {DOM Element} Returns the newly generated circle DIV element.

*/

_genCircle: function(childNode, guid, cacheStr, lineColor)

{

var div = document.createElement('div');

div.setAttribute('objGuid', guid);

div.style.borderColor = lineColor;

 

if(childNode)

{

div.appendChild(childNode);

}

this.divCanvas.appendChild(div);

 

 

// Add to the cache.

if(!this._guidCache[guid])

{

this._guidCache[guid] = [];

}

this._guidCache[guid].push(div);

this._htmlCache[cacheStr] = div;

 

return div;

},

 

@observes observedParameter

This tag is used to specify the parameters that are observed by an observer. If there are multiple observed properties, they are listed on separate lines.

 

     Example usage the of @observes tag with one observed parameter:

/**

    Observe value and set the innerHTML of the button.

 

    @observes value

*/

valueDidChange: function()

{

if(!this.isButton)

{

this.button.innerHTML = this.get("value");

}

}.observes('value'),

 

 

@commonTask Common Task Name 

This tag is used to group properties and methods/functions together in the documentation as part of a common task. This tag is optional.

 

     Example usage of the @commonTask tag:

 

/** 

When scolling, call this function to zoom in or out.

    

If there was a scroll event within the time period specified by the _scrollCoolDownAmount variable, then

don't do anything.

 

@commonTask Zooming Operations

 

@param {DOM Event} evt The scroll event.

*/

scrollZoom: function(evt)

{

// Check if the scroll event is within the cool down time, return.

if((Date.now()-this._scrollCoolDown) < this._scrollCoolDownAmount) return;

 

// Save a new cool down time.

this._scrollCoolDown = Date.now();

    

// Zoom in or out to the pointer location. If greater than zero, zooming in. Otherwise, zooming out.

this.setZoomToPointerLocation(Event.pointerX(evt), Event.pointerY(evt), ((evt.detail ? evt.detail * -1 : evt.wheelDelta) > 0));

},

 

 

 

Documentation Inside Functions or Methods

 

There are not solid guidelines for documenting inside functions themselves. It is important to use common sense and document what may be confusing to others trying to figure out what your code is doing. It is not useful to document every minute detail of your code. Document what you're doing in general, not every specific action. People should know how to program so it is not helpful to tell them how to re-implement your code step by step. For example, it is far more useful to tell them the input, algorithm, and output up front and let them figure out the syntactic details on their own. (If it is plainly obvious)

 

Useful Documentation:

 

     ...

 

     // Look through the relation array and find the items have been visited but not positioned. 

     // Save the max values for the number of children and weight.

     for(var i=0; i<rLen; i++)

     {

     var rel = r[i];

     var g = this.getGuidForRelation(rel);

     if(this._visited[g] &&  !this._positioned[g]) 

     {

     if(this._visited[g].childCount > maxChildren) 

     {

     maxChildren = this._visited[g].childCount;

     }

 

     var w = this.calcRelationWeight(rel);

 

     if(w > max) 

     {

     max = w;

     }

 

     rels.push([g, w]);

     }

     }

 

     ...

 

 

Not So Useful Documentation:

 

 

...

 

     // Loop over relationship array.

     for(var i=0; i<rLen; i++)

     {

     // Store the relation in a local varible.

     var rel = r[i];

 

     // Get the guid.

     var g = this.getGuidForRelation(rel);

 

     // If the guid has been visited, but not positioned go in here.

     if(this._visited[g] &&  !this._positioned[g]) 

     {

     // If the child count of the visited node is larger than maxChildren, set the count to maxChildren.

     if(this._visited[g].childCount > maxChildren) 

     {

     maxChildren = this._visited[g].childCount;

     }

 

     // Get the weight for the relation.

     var w = this.calcRelationWeight(rel);

 

     // If the weight is more than the max, set it to be the max.

     if(w > max) 

     {

     max = w;

     }

 

     // Push the guid and weight on to the new rels array.

     rels.push([g, w]);

     }

     }

     ...

 

 

 

 

Comments (1)

Miguel Moreira said

at 8:14 am on Aug 16, 2009

The text says it's possible to define tags such as @author, @version, and @copyright in a config file. Which file is it, and how should these values be declared?

You don't have permission to comment on this page.