Vue development specification catalog and description
Preface: This document as the foundation of the vue development specification template, good code is really pleasant to read, in a team to maintain a unified code style is necessary, after all, you write the code is not only you a person to see, in different terminal, in terms of the different editor Spaces and tabs may display effect is different, also affect the reading experience. There are no standards for a specification; it’s what works for your team that matters.
- Specification purposes
- Naming conventions
- Structural specification
- Annotation specifications
- Coding standards
- The CSS specification
- Use caution
- The appendix
Specification purposes
Promote teamwork, reduce maintenance costs, improve teamwork efficiency, and produce high-quality code
More importantly, it helps the programmers themselves and their teams grow
Naming conventions
To get people to write maintainable code, not disposable code
Let the rest of the team see your code at a glance
You can even look at the code you wrote some time later
Common variable naming conventions
- Naming method: hump nomenclature
- Naming conventions:
- The name must be a word related to the content of the requirement, for example, if I want to declare a variable to represent my school, then we can define it this way
Const mySchool = "mySchool"
; - You have to add if you’re naming complex numberssFor example, if I want to declare an array that represents the names of many people, we can define it this way
const names = new Array()
;
- The name must be a word related to the content of the requirement, for example, if I want to declare a variable to represent my school, then we can define it this way
constant
- Naming method: all uppercase
- Naming conventions: Use a combination of uppercase letters and underscores to separate words.
const MAX_COUNT = 10
const URL = 'https://www.baidu.com/'
Copy the code
Component naming conventions
Official documents recommend and comply with the rules
PascalCase (uppercase naming) is the most common declaration convention
Kebab-case (dash delimited naming) is the most common usage convention
- Component names should always be multiple words, except for the root component App
- Meaningful nouns, short and readable
- Naming follows the PascalCase convention
- Common components begin with Viomi(company name abbreviation), such as (
AbcdDatePicker,AbcdTable
) - Intra-page components start with a short component module name and end with Item, such as (
StaffBenchToChargeItem, StaffBenchAppNotArrItem
)
- Common components begin with Viomi(company name abbreviation), such as (
- Use follow the kebab-case convention
- Using components in a page needs to be closed and separated by short lines, such as (
.
)
- Using components in a page needs to be closed and separated by short lines, such as (
- When importing and registering components, follow the PascalCase convention
- Also note that you must comply with the custom element specification: Do not use reserved words.
1. Component files
As long as there is a build system that can concatenate files, separate each component into a file. When you need to edit a component or look up its usage, you can find it more quickly.
Is:
components/
|- TodoList.vue
|- TodoItem.vue
Copy the code
Example:
Vue.component('TodoList', {
// ...
})
Vue.component('TodoItem', {
// ...
})
Copy the code
2. The case of the single-file component file
The filename of a single-file component should either always start with the word uppercase (PascalCase)
Is:
components/
|- MyComponent.vue
Copy the code
Example:
components/
|- myComponent.vue
|- mycomponent.vue
Copy the code
3. Name of the basic component
Underlying components that apply specific styles and conventions (that is, components that present classes without logic or stateless) should all start with a specific prefix, such as Base, App, or V.
Is:
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
Copy the code
Example:
components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue
Copy the code
4. Singleton component name
Components that should only have a single active instance should be named with The prefix to indicate their uniqueness. This does not mean that components can only be used on a single page, but only once per page. These components never accept any prop because they are customized for your application, not their context in your application. If you find it necessary to add prop, that means it is actually a reusable component that is currently only used once per page.
Is:
components/
|- TheHeading.vue
|- TheSidebar.vue
Copy the code
Example:
components/
|- Heading.vue
|- MySidebar.vue
Copy the code
5. Tightly coupled component names
Child components that are tightly coupled to the parent component should be named prefixed with the parent component name. If a component only makes sense in the context of a parent component, this relationship should be reflected in its name. Because editors usually organize files alphabetically, doing so puts related files together.
Is:
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
Copy the code
Example:
components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue
Copy the code
6. Order of words in component names
Component names should start with high-level (usually generically described) words and end with descriptive modifiers.
Is:
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
Copy the code
Example:
components/ |- ClearSearchButton.vue |- ExcludeFromSearchInput.vue |- LaunchOnStartupCheckbox.vue |- RunSearchButton.vue |- SearchInput.vue |- TermsCheckbox.vueCopy the code
7. All component names in the template must be lowercase.
Is:
<! -- In single-file components and string templates --><my-component/>
Copy the code
Example:
<! -- In single-file components and string templates --><mycomponent/><! -- In single-file components and string templates --><myComponent/>
Copy the code
8. Full-word component names
Component names should tend to be full words rather than abbreviations.
Is:
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
Copy the code
Example:
components/
|- SdSettings.vue
|- UProfOpts.vue
Copy the code
Method Method naming specification
Reference: front-end JS specification documentation
- Camel name, use a verb or verb + noun form
//badGo, nextPage, show, open, login// goodJumpPage, openCarInfoDialogCopy the code
- Request data methods, ending with data
//badTakeData, confirmData, getList, postForm// goodGetListData, postFormDataCopy the code
- Except for init and refresh words
- Try to start with common words (set, get, go, can, has, is)
Function methods:
Get get /set Settings, add add /remove delete create create /destory Remove start Start /stop Stop Open Open /close Close, Read Read /write Write Load load /save save create create /destroy destroy begin Start end backup backup /restore restore Import import /export Export Split /merge inject /extract, attach /detach /separate, view /browse edit /modify Select select /mark copy copy /paste paste undo undo /redo redo insert insert /delete remove add add /append add clean clean /clear Clear, Increase /decrease play play play launch /pause launch compile compile execute Debug debug /trace trace observe /listen Build /publish input /output Encode /decode Encrypt /decrypt compress /decompress Pack Pack /unpack Parse /emit generate connect /disconnect/send /receive Download /upload Update /revert/lock /unlock check out /check in Submit /commit push /pull expand /collapse begin /end, start /finish Enter /exit Abort discard /quit Leave obsolete /depreciate discard, collect /aggregateCopy the code
File name under views
- Folders are required even if there is only one file
- Try to be nouns and use the camel’s name
| - views view directory | | - the template view module name | | -- - | -- CreateWareTemp. Vue module page level component | | -- - | -- WareTempDetail. Vue module page level component | | -- - | - EditWareTemp. Vue module page level component | | -- - | -- WareList. Vue module page level component | | -- - | - indexComponents module page level component folder | | -- - | - components Module common components folderCopy the code
Props specification
The Props definition should be as detailed as possible
// Bad this is only acceptable when developing a prototype system
props: ['status']
// good
props: {
status: {
type: String.required: true.validator: function (value) {
return [
'syncing'.'synced'.'version-conflict'.'error'].indexOf(value) ! = = -1}}}Copy the code
exceptions
- Temporary variables can be abbreviated, such as STR, num, BOL, obj, fun, arr.
- Loop variables can be abbreviated, for example: I, j, k, etc.
Structural specification
Directory folder and subfile specification
- The following unified management offices correspond to corresponding modules
- The following global files are exported as index.js and imported in main.js
- The following temporary file, after use, the interface has been, after the release of the clearance
SRC source directory | - API interface, unified management | - static resource assets, unified management | - components common components, global file | - utils filter, Global tools | - lib external reference plug-in to store and modify the file | - mock simulation interface, temporary storage | - the router routing, Unified management | - store vuex, Unified management | - views view directory | | - the template view module name | | -- - | -- CreateWareTemp. Vue module page level component | | -- - | -- WareTempDetail. Vue module page level component | | - | -- EditWareTemp. Vue module page level component | | -- - | -- WareList. Vue module page level component | | -- - | - indexComponents module page level component folder | | -- - | - components Module common components folderCopy the code
Note:
-
The route is defined according to the folder where the file resides, as follows:
template/ware
-
API folders are grouped by module
API | | -- - | - template module folder | | -- - | -- ware. Js module level menu component filesCopy the code
Vue file basic structure
<template>
<div>
<! You must write the page in div.
</div>
</template>
<script>
export default {
components : {
},
data () {
return{}},mounted(){},methods: {}}</script>
<style lang="scss">
</style>
Copy the code
Element specifications for multiple features
Elements with multiple features should be written on one line (wrap).
<! -- good -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<my-component foo="a" bar="b" baz="c"></my-component>
<! -- bad -->
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
>
<my-component
foo="a"
bar="b"
baz="c"
>
</my-component>
Copy the code
The order of element attributes
Native attributes come first, directives come later
As follows:
-class-id, ref-name - data-* -src, for, type, href,value,max-length, Max,min, pattern-title, Alt, placeholder - aria-*, role - required,readonly,disabled - is - v-for - key - v-if - v-else-if - v-else - v-show - v-cloak - v-pre - v-once - v-model - v-bind,: - v-on,@ - v-html - v-textCopy the code
Component option order
As follows:
- components
- props
- data
- computed
- watch
- filter
- created
- mounted
- metods
Copy the code
Annotation specifications
Code comments are especially important in the later maintenance of a project, so we write component usage instructions for each component that is reused and method instructions for each method in the component
Be sure to add a list of comments
- Usage instructions for common components
- Description of important functions or classes in a component
- Complex business logic processing instructions
- Special case code processing instructions, for the code for special purpose variables, the existence of critical values, hacks used in the function, the use of a certain algorithm or ideas need to be commented description
- Multiple if statements
- The comment block must be
/** (at least two asterisks) begins with **/
- Single-line comments use //
Single-line comments
Comment on a single line. Do not comment on the same line after code. Such as:
bad
varName = "ABC";/ / name
good
/ / name
varName = "ABC";Copy the code
Multiline comment
Common component instructions, /** * Component name * @module component location * @desc Component description * @author Component author * @date, 05 December 2017 17:22:43 * @param {Object} [title] - Parameter Description * @param {String} [columns] - parameter Description * @example Invoke example *<hbTable :title="title" :columns="columns" :tableData="tableData"></hbTable>* * /Copy the code
Coding standards
Excellent project source code, even if it is developed by multiple people, see the code as one hand. Unified coding specification makes code easier to read, understand and maintain. Write as much code as possible in the ESLint format
The source code style
Code using ES6 style
- Let is used to define variables and const is used to define constants
- Static strings use single or backquotation marks. Dynamic strings use backquotation marks
// bad
const a = 'foobar'
const b = 'foo' + a + 'bar'
// acceptable
const c = `foobar`
// good
const a = 'foobar'
const b = `foo${a}bar`
const c = 'foobar'
Copy the code
- Deconstruction assignment
- When an array member assigns a value to a variable, destruct assignment is preferred
// Array destruct assignment
const arr = [1.2.3.4]
// bad
const first = arr[0]
const second = arr[1]
// good
const [first, second] = arr
Copy the code
- Function arguments that are members of an object use destruct assignment preferentially
// Object destruct assignment
// bad
function getFullName(user) {
const firstName = user.firstName
const lastName = user.lastName
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj
}
// best
function getFullName({ firstName, lastName }) {}
Copy the code
-
Copy an array
Using extension operators (…) Copy the array.
const items = [1.2.3.4.5]
// bad
const itemsCopy = items
// good
const itemsCopy = [...items]
Copy the code
-
Arrow function
When functional expressions are required, use arrow functions instead. Because it’s cleaner, and it’s bound to this
// bad
const self = this;
const boundMethod = function(. params) {
return method.apply(self, params);
}
// acceptable
const boundMethod = method.bind(this);
// best
const boundMethod = (. params) = > method.apply(this, params);
Copy the code
- The module
- If the module has only one output value, use export default. If the module has multiple output values, do not use Export default. Export default and ordinary export should not be used together
// bad
import * as myObject from './importModule'
// good
import myObject from './importModule'
Copy the code
- If a module outputs a function by default, the first letter of the function name should be lowercase.
function makeStyleGuide() {}export default makeStyleGuide;
Copy the code
- If a module outputs an object by default, the first letter of the object name should be capitalized.
const StyleGuide = {
es6: {}};export default StyleGuide;
Copy the code
Instructions specification
- Any abbreviations of instructions shall be in abbreviated form
// bad
v-bind:class="{' show - left: true}"
v-on:click="getListData"
// good
:class="{' show - left: true}"
@click="getListData"
Copy the code
- The V-for loop must have a key attribute, which must be unique throughout the for loop
<! -- good -->
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
<! -- bad -->
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
Copy the code
-
Avoid v-if and V-for on the same element (performance issues)
There are two solutions:
- Replace the data with a calculated property that returns the filtered list
<! -- bad -->
<ul>
<li v-for="user in users" v-if="user.isActive" :key="user.id">
{{ user.name }}
</li>
</ul>
<! -- good -->
<ul>
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
<script>
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
</script>
Copy the code
- Move v-if to container elements (such as ul, OL)
<! -- bad -->
<ul>
<li v-for="user in users" v-if="shouldShowUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
<! -- good -->
<ul v-if="shouldShowUsers">
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
Copy the code
other
- To avoid this. $parent
- Debug information Console. log() Is deleted after the debugger is used
- Except for ternary operations, if,else, etc
// bad
if (true)
alert(name);
console.log(name);
// bad
if (true)
alert(name);
console.log(name)
// good
if (true) {
alert(name);
}
console.log(name);
Copy the code
- Templates do not do logic processing, try to handle logic in the data source;
// bad
<el-table-column width="180px" label="State">
<template slot-scope="scope">
<span v-if="scope.row.status==-99">Turn the single</span>
<span v-if="scope.row.status==-1">To give up</span>
<span v-if="scope.row.status===0">allocated</span>
<span v-if="scope.row.status==1">Has been completed</span>
<span v-if="scope.row.status==2">To audit</span>
<span v-if="scope.row.status==3">approved</span>
<span v-if="scope.row.status==-3">Audit failed</span>
<span v-if="scope.row.status==4">In the review</span>
</template>
</el-table-column>
// good
list.forEach(item= > {
item.StatusStr = findName(this.status, item.status);
});
Copy the code
The CSS specification
General specification
- Use a hyphen (-)
- Omit the units with a value of 0
// bad
padding-bottom: 0px;
margin: 0em;
// good
padding-bottom: 0;
margin: 0;
Copy the code
-
If CSS can do it, don’t use JS
-
Recommend and abbreviate values appropriately to improve readability, except in special cases
“Suggested and appropriate” is because abbreviations always contain a list of values, and sometimes you don’t want to set a particular value to cause trouble, so instead of abbreviating, you can write them separately.
Of course, in all cases where you can abbreviate, be sure to abbreviate; its biggest benefits are byte savings, easy maintenance, and easy reading.
// bad
.box{
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
}
// good
.box{
border-top: 0;
font: 100%/1.6 palatino, georgia, serif;
padding: 0 1em 2em;
}
Copy the code
- Declarations should follow the order in the table below
Left to right, top to bottom
Display attributes | Its properties | Text attributes and other modifications |
---|---|---|
display | width | font |
visibility | height | text-align |
position | margin | text-decoration |
float | padding | vertical-align |
clear | border | white-space |
list-style | overflow | color |
top | min-width | background |
// bad
.box {
font-family: 'Arial', sans-serif;
border: 3px solid #ddd;
left: 30%;
position: absolute;
text-transform: uppercase;
background-color: #eee;
right: 30%;
isplay: block;
font-size: 1.5 rem;
overflow: hidden;
padding: 1em;
margin: 1em;
}
// good
.box {
display: block;
position: absolute;
left: 30%;
right: 30%;
overflow: hidden;
margin: 1em;
padding: 1em;
background-color: #eee;
border: 3px solid #ddd;
font-family: 'Arial', sans-serif;
font-size: 1.5 rem;
text-transform: uppercase;
}
Copy the code
-
Element selectors should be avoided in scoped
Class selectors are better than element selectors in the Scoped style because element selectors are slow to use in large quantities.
-
Nomenclature of classification
Use a single letter prefixed with “-“
Layout (grid) (.g-);
Module (.m-);
Unit (.u-);
Function (.f-);
Skin (.s-);
State (.z-).
-
Unified semantic understanding and naming
Layout (.g-)
The semantic | named | shorthand |
---|---|---|
The document | doc | doc |
The head | head | hd |
The main body | body | bd |
The tail | foot | ft |
The main bar | main | mn |
Main column child container | mainc | mnc |
The sidebar | side | sd |
Sidebar child containers | sidec | sdc |
Box container | wrap/box | wrap/box |
Module (.m-), component (.U -)
The semantic | named | shorthand |
---|---|---|
navigation | nav | nav |
The subnavigation | subnav | snav |
Bread crumbs | crumb | crm |
The menu | menu | menu |
TAB | tab | tab |
The title area | head/title | hd/tt |
Content area | body/content | bd/ct |
The list of | list | lst |
form | table | tb |
The form | form | fm |
hot | hot | hot |
ranking | top | top |
The login | login | log |
mark | logo | logo |
advertising | advertise | ad |
search | search | sch |
slide | slide | sld |
prompt | tips | tips |
help | help | help |
news | news | news |
download | download | dld |
registered | regist | reg |
vote | vote | vote |
copyright | copyright | cprt |
The results of | result | rst |
The title | title | tt |
button | button | btn |
The input | input | ipt |
Function (.f-)
The semantic | named | shorthand |
---|---|---|
Floating clearance | clearboth | cb |
The left floating | floatleft | fl |
Float to the right | floatright | fr |
Inline block-level | inlineblock | ib |
The text centered | textaligncenter | tac |
The text in the right | textalignright | tar |
The text in the left | textalignleft | tal |
Vertical center | verticalalignmiddle | vam |
Overflow hidden | overflowhidden | oh |
Disappear completely | displaynone | dn |
The font size | fontsize | fs |
The font size | fontweight | fw |
Skin (.s-)
The semantic | named | shorthand |
---|---|---|
The font color | fontcolor | fc |
background | background | bg |
The background color | backgroundcolor | bgc |
The background image | backgroundimage | bgi |
Background positioning | backgroundposition | bgp |
Border color | bordercolor | bdc |
State (.z-)
The semantic | named | shorthand |
---|---|---|
The selected | selected | sel |
The current | current | crt |
According to | show | show |
hidden | hide | hide |
Open the | open | open |
Shut down | close | close |
error | error | err |
Do not use | disabled | dis |
Sass specification
- When using the nesting functionality of Sass, it is important to have a clear nesting order. Here is the order an SCSS block should have.
- The style property of the current selector
- Pseudo-class selectors for parent selectors (:first-letter, :hover, :active etc)
- Pseudoclass elements (:before and :after)
- Declaration styles of parent selector (.selected,.active,.mended etc.)
- Query with Sass context media
- The child selector is the last part
.product-teaser {
// 1. Style attributes
display: inline-block;
padding: 1rem;
background-color: whitesmoke;
color: grey;
// 2. Pseudo selectors with parent selector
&:hover {
color: black; } / /3. Pseudo elements with parent selector
&:before {
content: "";
display: block;
border-top: 1px solid grey;
}
&:after {
content: "";
display: block;
border-top: 1pxsolid grey; } / /4. State classes with parent selector
&.active {
background-color: pink;
color: red;
// 4.2. Pseuso selector in state class selector
&:hover {
color: darkred; / /}}5. Contextual media queries
@media screen and (max-width: 640px) {
display: block;
font-size: 2em; } / /6. Sub selectors
> .content > .title {
font-size: 1.2 em;
// 6.5. Contextual media queries in sub selector
@media screen and (max-width: 640px) {
letter-spacing: 0.2 em;
text-transform: uppercase; }}}Copy the code
Special specification
- For page-level component styles, they should be scoped
- For common components or global component libraries, the class-based BEM strategy should be preferred
<style lang='scss'></style> // bad <! <style lang=' SCSS 'scoped></style> // good <! <style> // good.c-Button {
border: none;
border-radius: 2px;
}
.c-Button--close {
background-color: red;
}
</style>
Copy the code
Use caution (potentially dangerous patterns)
Implicit parent-child component communication
Parent component communication should take precedence over this.$parent or changing prop via prop and events.
Is:
Vue.component('TodoItem', {
props: {
todo: {
type: Object.required: true}},template: ` `
})
Copy the code
Example:
Vue.component('TodoItem', {
props: {
todo: {
type: Object.required: true}},methods: {
removeTodo () {
var vm = this
vm.$parent.todos = vm.$parent.todos.filter(function (todo) {
returntodo.id ! == vm.todo.id }) } },template: ` {{ todo.text }} `
})
Copy the code
The appendix
It is recommended to use VS Code for front-end coding, specifying a Tab size of 2 Spaces
1. Vs Code Configuration (to be perfected)
{
"editor.tabSize": 2."editor.formatOnSave": true.// Automatically format each save
"editor.lineNumbers": "on".// Turn on the line prompt
"files.autoSave": "afterDelay"."html.format.indentHandlebars": false."prettier.semi": true.// Remove the semicolon at the end of the code
"prettier.singleQuote": false.// Use quotes instead of double quotes
"prettier.tabWidth": 2."javascript.format.insertSpaceBeforeFunctionParenthesis": true.// Add a space between the function (name) and the following parentheses
"vetur.format.defaultFormatter.html": "js-beautify-html"."vetur.format.defaultFormatter.js": "vscode-typescript".// Format the JS in vue in the ts format that comes with the editor
"vetur.experimental.templateInterpolationService": false."vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": true // The property enforces line alignment
},
"prettier": {
"semi": false."singleQuote": true}},"git.confirmSync": false."editor.quickSuggestions": {
// Enable the automatic display of suggestions
"other": true."comments": true."strings": true
},
"eslint.autoFixOnSave": true.// Fix the code in ESLint format every time you save it
"eslint.validate": [
"javascript"."html",
{
"language": "vue"."autoFix": true}]."eslint.options": {
"plugins": [
"html"]},"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
},
"diffEditor.ignoreTrimWhitespace": false."[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[vue]": {
"editor.defaultFormatter": "octref.vetur"
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[less]": {
"editor.defaultFormatter": "michelemelluso.code-beautifier"
},
"workbench.activityBar.visible": true."workbench.statusBar.visible": true."window.zoomLevel": 0."explorer.confirmDelete": false."explorer.confirmDragAndDrop": false."gitlens.advanced.fileHistoryFollowsRenames": false."gitlens.advanced.messages": {
"suppressShowKeyBindingsNotice": true
},
"files.associations": {
"*.vue": "vue"
},
"javascript.updateImportsOnFileMove.enabled": "always"."terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe"."liveServer.settings.port": 8080."liveServer.settings.donotShowInfoMsg": true."dart.sdkPath": "E:\\Dart\\dart-sdk"."workbench.colorTheme": "Visual Studio Dark"."editor.fontSize": 16}}Copy the code
2. Vs code plug-in
- Auto Close Tag
- Path Intellisense
- Prettier
- Vetur
- vscode-icons
As a final note of caution, it is very easy to create a development specification that is appropriate for your company’s situation. It is important that we recognize the importance of the specification and stick to it.