{"__v":0,"_id":"5821f11063e87b25000cbcc6","category":{"version":"5821f10e63e87b25000cbc90","project":"570e9147a5da5e0e005fdec3","_id":"5821f10e63e87b25000cbc9a","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-04-26T20:07:26.613Z","from_sync":false,"order":9,"slug":"effective-chatops","title":"Effective ChatOps"},"parentDoc":null,"project":"570e9147a5da5e0e005fdec3","user":"570fbbbe2fd5441900f799d1","version":{"__v":1,"_id":"5821f10e63e87b25000cbc90","project":"570e9147a5da5e0e005fdec3","createdAt":"2016-11-08T15:36:46.296Z","releaseDate":"2016-11-08T15:36:46.296Z","categories":["5821f10e63e87b25000cbc91","5821f10e63e87b25000cbc92","5821f10e63e87b25000cbc93","5821f10e63e87b25000cbc94","5821f10e63e87b25000cbc95","5821f10e63e87b25000cbc96","5821f10e63e87b25000cbc97","5821f10e63e87b25000cbc98","5821f10e63e87b25000cbc99","5821f10e63e87b25000cbc9a","5821f10e63e87b25000cbc9b"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"0.16.0","version":"0.16"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-05-04T20:23:29.902Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"[block:callout]\n{\n  \"type\": \"danger\",\n  \"title\": \"Deprecated Content\",\n  \"body\": \"This documentation section has been deprecated. Please refer to the [Designing ChatOps Commands](https://cog-book.operable.io/#_designing_chatops_commands) section of [The Cog Book](https://cog-book.operable.io) for up to date information\"\n}\n[/block]\n# Small Sharp Tools\n* Commands should do one thing well. Multiple modes or actions indicate poor design.\n* Perform complex workflows by composing multiple commands into pipelines.\n  - Complex commands are inscrutable black boxes.\n  - Complex pipelines are explicit and readable.\n* Define aliases and use them to run common pipelines.\n\n# Naming\n* Bundle and command names should be descriptive but short as possible: `cp`, `mv`, `tr`.\n* Short bundle names minimize the pain of manually disambiguating command name conflicts. `s3:cp` not `aws-s3:cp`.\n* Good bundle names avoid doing too much. Prefer `s3` over `aws`.\n\n# Designing Command Interfaces\n* A well designed command reads like prose and can be diagrammed like a sentence.\n  - noun verb noun -> bundle command arg(s)\n  - The tree caught the kite -> tree:catch kite\n* Follow existing Unix CLI conventions when possible. _Especially_ when building a command which is similar to an existing Unix command. `s3:cp src dest` not `s3:cp --source=src --dest=dest`.\n* Prefer arguments over options.\n  - Arguments require less typing and naturally support multiple values.\n  - Options require more typing and are clunky to use when multiple values must be given.\n* Arguments should refer to targets of the same or closely related types.\n*  When using options set sane default values to the maximum extent possible. Target the most common use cases.\n  - Options should be used to indicate when the command should depart from default behaviors. For example, a `s3:ls` command might have a `--acls` option to indicate when it should display bucket entries' S3 ACLs.\n* Obey the  __DWIM__ (Do What I Mean) principle as much as possible. If you have a `pagerduty:page` command that takes a username and send a message, don't require quotes around the message -- simply concatenate all of the arguments after the name since you can reasonably infer the intent.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"pagerduty:page djohnson has the db restore finished?\",\n      \"language\": \"text\",\n      \"name\": \"IDEAL\"\n    },\n    {\n      \"code\": \"pagerduty:page djohnson \\\"has the db restore finished?\\\"\",\n      \"language\": \"text\",\n      \"name\": \"OK\"\n    },\n    {\n      \"code\": \"pagerduty:page --user=djohnson --message=\\\"has the db restore finished?\\\"\",\n      \"language\": \"text\",\n      \"name\": \"BAD\"\n    }\n  ]\n}\n[/block]\n# Pipeline Friendly Output\n* Design tools with the expectation that they'll be combined with other tools and as part of scripts.\n* Avoid reusing field names to refer to different types of data whenever possible.\n  - Nested collections are the only exception. The collection field name provides enough context to avoid confusion.\n* Bias toward returning data verbosely and filtering what the user is presented with at the template level. This allows maximum flexibility to work with the returned data in ways that the author did not expect.\n* Templates should focus on providing the simplest possible output that returns the most commonly needed data.\n* Only accumulate output when you absolutely must. Prefer stateless commands  over stateful streaming commands.","excerpt":"","slug":"designing-for-chatops","type":"basic","title":"Designing For ChatOps"}

Designing For ChatOps


[block:callout] { "type": "danger", "title": "Deprecated Content", "body": "This documentation section has been deprecated. Please refer to the [Designing ChatOps Commands](https://cog-book.operable.io/#_designing_chatops_commands) section of [The Cog Book](https://cog-book.operable.io) for up to date information" } [/block] # Small Sharp Tools * Commands should do one thing well. Multiple modes or actions indicate poor design. * Perform complex workflows by composing multiple commands into pipelines. - Complex commands are inscrutable black boxes. - Complex pipelines are explicit and readable. * Define aliases and use them to run common pipelines. # Naming * Bundle and command names should be descriptive but short as possible: `cp`, `mv`, `tr`. * Short bundle names minimize the pain of manually disambiguating command name conflicts. `s3:cp` not `aws-s3:cp`. * Good bundle names avoid doing too much. Prefer `s3` over `aws`. # Designing Command Interfaces * A well designed command reads like prose and can be diagrammed like a sentence. - noun verb noun -> bundle command arg(s) - The tree caught the kite -> tree:catch kite * Follow existing Unix CLI conventions when possible. _Especially_ when building a command which is similar to an existing Unix command. `s3:cp src dest` not `s3:cp --source=src --dest=dest`. * Prefer arguments over options. - Arguments require less typing and naturally support multiple values. - Options require more typing and are clunky to use when multiple values must be given. * Arguments should refer to targets of the same or closely related types. * When using options set sane default values to the maximum extent possible. Target the most common use cases. - Options should be used to indicate when the command should depart from default behaviors. For example, a `s3:ls` command might have a `--acls` option to indicate when it should display bucket entries' S3 ACLs. * Obey the __DWIM__ (Do What I Mean) principle as much as possible. If you have a `pagerduty:page` command that takes a username and send a message, don't require quotes around the message -- simply concatenate all of the arguments after the name since you can reasonably infer the intent. [block:code] { "codes": [ { "code": "pagerduty:page djohnson has the db restore finished?", "language": "text", "name": "IDEAL" }, { "code": "pagerduty:page djohnson \"has the db restore finished?\"", "language": "text", "name": "OK" }, { "code": "pagerduty:page --user=djohnson --message=\"has the db restore finished?\"", "language": "text", "name": "BAD" } ] } [/block] # Pipeline Friendly Output * Design tools with the expectation that they'll be combined with other tools and as part of scripts. * Avoid reusing field names to refer to different types of data whenever possible. - Nested collections are the only exception. The collection field name provides enough context to avoid confusion. * Bias toward returning data verbosely and filtering what the user is presented with at the template level. This allows maximum flexibility to work with the returned data in ways that the author did not expect. * Templates should focus on providing the simplest possible output that returns the most commonly needed data. * Only accumulate output when you absolutely must. Prefer stateless commands over stateful streaming commands.