You are on page 1of 32

Sign up Sign up Sign in Sign in

Files Commits Branches


b b a t s o v / c l o j u r e - s t y l e - g u i d e
P
U
B
L
I
C
g
Code Code Net work Net work Pull Request s Pull Request s Issues Issues Graphs Graphs
++
11 13 13
Re ad- Onl y access
A community coding style guide for the Clojure programming language Read more
ZIP ZIP SSH SSH Gi t Re ad- Onl y Gi t Re ad- Onl y https://github.com/bbatsov/clojure-style-guide.git
Tags yy mast er mast er 1
133 commit s
latest commit cc0f61724c
Add an opening quote
bbat sov authored 12 days ago
_ CONTRIBUTING.md 5 months ago Added contribution guidelines. [bbatsov]
_ README.md 12 days ago Add an opening quote [bbatsov]
README.md README.md
Role models are import ant .
clojure-style-guide / _
The Clojure Style Guide
HTTP HTTP
4 4 9 32
Search or type a command
Thi s re posi t ory Thi s re posi t ory @@
PDFmyURL.com
-- Of f icer Alex J. Murphy / RoboCop
This Clojure st yle guide recommends best pract ices so t hat real-world Clojure programmers can writ e code t hat can be
maint ained by ot her real-world Clojure programmers. A st yle guide t hat ref lect s real-world usage get s used, and a st yle
guide t hat holds t o an ideal t hat has been reject ed by t he people it is supposed t o help risks not get t ing used at all no
mat t er how good it is.
The guide is separat ed int o several sect ions of relat ed rules. I've t ried t o add t he rat ionale behind t he rules (if it 's omit t ed
I've assumed t hat is pret t y obvious).
I didn't come up wit h all t he rules out of nowhere - t hey are most ly based on my ext ensive career as a prof essional
sof t ware engineer, f eedback and suggest ions f rom members of t he Clojure communit y, and various highly regarded
Clojure programming resources, such as "Clojure Programming" and "The Joy of Clojure".
The guide is st ill a work in progress - some sect ions are missing, ot hers are incomplet e, some rules are lacking examples,
some rules don't have examples t hat illust rat e t hem clearly enough. In due t ime t hese issues will be addressed - just keep
t hem in mind f or now.
You can generat e a PDF or an HTML copy of t his guide using Transmut er.
Source Code Layout & Organizat ion
Synt ax
Naming
Collect ions
Mut at ion
St rings
Except ions
Table of Contents
PDFmyURL.com
Macros
Comment s
Comment Annot at ions
Exist ent ial
Tooling
Nearly everybody is convinced t hat every st yle but t heir own is ugly and unreadable. Leave out t he "but t heir own" and
t hey're probably right ...
-- Jerry Cof f in (on indent at ion)
Use t wo spaces per indent at ion level. No hard t abs.
;; good
(when something
(something-else))
;; bad - four spaces
(when something
(something-else))
Align vert ically f unct ion argument s.
;; good
(filter even?
(range 1 10))
;; bad
(filter even?
(range 1 10))
Source Code Layout & Organization
PDFmyURL.com
Align let bindings and map keywords.
;; good
(let [thing1 "some stuff"
thing2 "other stuff"]
{:thing1 thing1
:thing2 thing2})
;; bad
(let [thing1 "some stuff"
thing2 "other stuff"]
{:thing1 thing1
:thing2 thing2})
Opt ionally omit t he new line bet ween t he f unct ion name and argument vect or f or defn when t here is no docst ring.
;; good
(defn foo
[x]
(bar x))
;; good
(defn foo [x]
(bar x))
;; bad
(defn foo
[x] (bar x))
Opt ionally omit t he new line bet ween t he argument vect or and a short f unct ion body.
;; good
(defn foo [x]
(bar x))
PDFmyURL.com
;; good for a small function body
(defn foo [x] (bar x))
;; good for multi-arity functions
(defn foo
([x] (bar x))
([x y]
(if (predicate? x)
(bar x)
(baz x))))
;; bad
(defn foo
[x] (if (predicate? x)
(bar x)
(baz x)))
Indent each line of mult i-line docst rings.
;; good
(defn foo
"Hello there. This is
a multi-line docstring."
[]
(bar))
;; bad
(defn foo
"Hello there. This is
a multi-line docstring."
[]
(bar))
Use Unix-st yle line endings. (*BSD/Solaris/Linux/OSX users are covered by def ault , Windows users have t o be ext ra
PDFmyURL.com
caref ul.)
If you're using Git you might want t o add t he f ollowing conf igurat ion set t ing t o prot ect your project f rom Windows
line endings creeping in:
$ git config --global core.autocrlf true
If any t ext precedes an opening bracket ( ( , { and [ ) or f ollows a closing bracket ( ) , } and ] ), separat e t hat
t ext f rom t hat bracket wit h a space. Conversely, leave no space af t er an opening bracket and bef ore f ollowing t ext ,
or af t er preceding t ext and bef ore a closing bracket .
;; good
(foo (bar baz) quux)
;; bad
(foo(bar baz)quux)
(foo ( bar baz ) quux)
Don't use commas bet ween t he element s of sequent ial collect ion lit erals.
;; good
[1 2 3]
(1 2 3)
;; bad
[1, 2, 3]
(1, 2, 3)
Consider enhancing t he readabilit y of map lit erals via judicious use of commas and line breaks.
;; good
{:name "Bruce Wayne" :alter-ego "Batman"}
PDFmyURL.com
;; good and arguably a bit more readable
{:name "Bruce Wayne"
:alter-ego "Batman"}
;; good and arguably more compact
{:name "Bruce Wayne", :alter-ego "Batman"}
Place all t railing parent heses on a single line.
;; good
(when something
(something-else))
;; bad
(when something
(something-else)
)
Use empt y lines bet ween t op-level f orms.
;; good
(def x ...)
(defn foo ...)
;; bad
(def x ...)
(defn foo ...)
An except ion t o t he rule is t he grouping of relat ed def s t oget her.
;; good
(def min-rows 10)
(def max-rows 20)
(def min-cols 15)
PDFmyURL.com
(def max-cols 30)
Do not place blank lines in t he middle of a f unct ion or macro def init ion. An except ion can be made t o indicat e grouping
of pairwise const ruct s as f ound in e.g. let and cond .
Where f easible, avoid making lines longer t han 80 charact ers.
Avoid t railing whit espace.
Use one f ile per namespace.
St art every namespace wit h a comprehensive ns f orm, comprised of import s, require s, refer s and use s.
(ns examples.ns
(:refer-clojure :exclude [next replace remove])
(:require (clojure [string :as string]
[set :as set])
[clojure.java.shell :as sh])
(:use (clojure zip xml))
(:import java.util.Date
java.text.SimpleDateFormat
(java.util.concurrent Executors
LinkedBlockingQueue)))
Avoid single-segment namespaces.
;; good
(ns example.ns)
;; bad
(ns example)
Avoid t he use of overly long namespaces(i.e. wit h more t han 5 segment s).
PDFmyURL.com
Avoid f unct ions longer t han 10 LOC (lines of code). Ideally, most f unct ions will be short er t han 5 LOC.
Avoid paramet er list s wit h more t han t hree or f our posit ional paramet ers.
Avoid t he use of namespace-manipulat ing f unct ions like require and refer . They are ent irely unnecessary out side
of a REPL environment .
Use declare t o enable f orward ref erences.
Pref er higher-order f unct ions like map t o loop/recur .
Pref er f unct ion pre and post condit ions t o checks inside a f unct ion's body.
;; good
(defn foo [x]
{:pre [(pos? x)]}
(bar x))
;; bad
(defn foo [x]
(if (pos? x)
(bar x)
(throw (IllegalArgumentException "x must be a positive number!")))
Don't def ine vars inside f unct ions.
;; very bad
(defn foo []
(def x 5)
...)
Syntax
PDFmyURL.com
Don't shadow clojure.core names wit h local bindings.
;; bad - you're forced to used clojure.core/map fully qualified inside
(defn foo [map]
...)
Use seq as a t erminat ing condit ion t o t est whet her a sequence is empt y (t his t echnique is somet imes called nil
punning).
;; good
(defn print-seq [s]
(when (seq s)
(prn (first s))
(recur (rest s))))
;; bad
(defn print-seq [s]
(when-not (empty? s)
(prn (first s))
(recur (rest s))))
Use when inst ead of (if ... (do ...) .
;; good
(when pred
(foo)
(bar))
;; bad
(if pred
(do
(foo)
(bar)))
PDFmyURL.com
Use if-let inst ead of let + if .
;; good
(if-let [result (foo x)]
(something-with result)
(something-else))
;; bad
(let [result (foo x)]
(if result
(something-with result)
(something-else)))
Use when-let inst ead of let + when .
;; good
(when-let [result (foo x)]
(do-something-with result)
(do-something-more-with result))
;; bad
(let [result (foo x)]
(when result
(do-something-with result)
(do-something-more-with result)))
Use if-not inst ead of (if (not ...) ...) .
;; good
(if-not (pred)
(foo))
;; bad
(if (not pred)
(foo))
PDFmyURL.com
Use when-not inst ead of (when (not ...) ...) .
;; good
(when-not pred
(foo)
(bar))
;; bad
(when (not pred)
(foo)
(bar))
Use when-not inst ead of (if-not ... (do ...) .
;; good
(when-not pred
(foo)
(bar))
;; bad
(if-not pred
(do
(foo)
(bar)))
Use not= inst ead of (not (= ...)) .
;; good
(not= foo bar)
;; bad
(not (= foo bar))
Pref er % over %1 in f unct ion lit erals wit h only one paramet er.
PDFmyURL.com
Pref er % over %1 in f unct ion lit erals wit h only one paramet er.
;; good
#(Math/round %)
;; bad
#(Math/round %1)
Pref er %1 over % in f unct ion lit erals wit h more t han one paramet er.
;; good
#(Math/pow %1 %2)
;; bad
#(Math/pow % %2)
Don't wrap f unct ions in anonymous f unct ions when you don't need t o.
;; good
(filter even? (range 1 10))
;; bad
(filter #(even? %) (range 1 10))
Don't use f unct ion lit erals if t he f unct ion body will consist of more t han one f orm.
;; good
(fn [x]
(println x)
(* x 2))
;; bad (you need an explicit do form)
#(do (println %)
(* % 2))
PDFmyURL.com
Favor t he use of complement versus t he use of an anonymous f unct ion.
;; good
(filter (complement some-pred?) coll)
;; bad
(filter #(not (some-pred? %)) coll)
This rule should obviously be ignored if t he complement ing predicat e exist s in t he f orm of a separat e f unct ion (e.g.
even? and odd? ).
Leverage comp when it would yield simpler code.
;; Assuming `(:require [clojure.string :as str])`...
;; good
(map #(str/capitalize (str/trim %)) ["top " " test "])
;; better
(map (comp str/capitalize str/trim) ["top " " test "])
Leverage partial when it would yield simpler code.
;; good
(map #(+ 5 %) (range 1 10))
;; (arguably) better
(map (partial + 5) (range 1 10))
Pref er t he use of t he t hreading macros -> (t hread-f irst ) and ->> (t hread-last ) t o heavy f orm nest ing.
;; good
(-> [1 2 3]
reverse
PDFmyURL.com
(conj 4)
prn)
;; not as good
(prn (conj (reverse [1 2 3])
4))
;; good
(->> (range 1 10)
(filter even?)
(map (partial * 2)))
;; not as good
(map (partial * 2)
(filter even? (range 1 10)))
Pref er .. t o -> when chaining met hod calls in Java int erop.
;; good
(-> (System/getProperties) (.get "os.name"))
;; better
(.. System getProperties (get "os.name"))
Use :else as t he cat ch-all t est expression in cond and condp .
;; good
(cond
(< n 0) "negative"
(> n 0) "positive"
:else "zero"))
;; bad
(cond
(< n 0) "negative"
PDFmyURL.com
(> n 0) "positive"
true "zero"))
Pref er condp inst ead of cond when t he predicat e & expression don't change.
;; good
(cond
(= x 10) :ten
(= x 20) :twenty
(= x 30) :forty
:else :dunno)
;; much better
(condp = x
10 :ten
20 :twenty
30 :forty
:dunno)
Pref er case inst ead of cond or condp when t est expressions are compile-t ime const ant s.
;; good
(cond
(= x 10) :ten
(= x 20) :twenty
(= x 30) :forty
:else :dunno)
;; better
(condp = x
10 :ten
20 :twenty
30 :forty
:dunno)
PDFmyURL.com
;; best
(case x
10 :ten
20 :twenty
30 :forty
:dunno)
Use short f orms in cond and relat ed. If not possible give visual hint s f or t he pairwise grouping wit h comment s or
empt y lines.
;; good
(cond
(test1) (action1)
(test2) (action2)
:else (default-action))
;; ok-ish
(cond
;; test case 1
(test1)
(long-function-name-which-requires-a-new-line
(complicated-sub-form
(-> 'which-spans
multiple-lines)))
(test2)
(another-very-long-function-name
(yet-another-sub-form
(-> 'which-spans
multiple-lines)))
:else
(the-fall-through-default-case
(which-also-spans 'multiple
'lines)))
PDFmyURL.com
Use a set as a predicat e when appropriat e.
;; good
(remove #{0} [0 1 2 3 4 5])
;; bad
(remove #(= % 0) [0 1 2 3 4 5])
;; good
(count (filter #{\a \e \i \o \u} "mary had a little lamb"))
;; bad
(count (filter #(or (= % \a)
(= % \e)
(= % \i)
(= % \o)
(= % \u))
"mary had a little lamb"))
Use (inc x) & (dec x) inst ead of (+ x 1) and (- x 1) .
Use (pos? x) , (neg? x) & (zero? x) inst ead of (> x 0) , (< x 0) & (= x 0) .
Use t he sugared Java int erop f orms.
;;; object creation
;; good
(java.util.ArrayList. 100)
;; bad
(new java.util.ArrayList 100)
;;; static method invocation
;; good
(Math/pow 2 10)
PDFmyURL.com
;; bad
(. Math pow 2 10)
;;; instance method invocation
;; good
(.substring "hello" 1 3)
;; bad
(. "hello" substring 1 3)
;;; static field access
;; good
Integer/MAX_VALUE
;; bad
(. Integer MAX_VALUE)
;;; instance field access
;; good
(.someField some-object)
;; bad
(. some-object some-field)
Use t he compact met adat a not at ion f or met adat a t hat cont ains only slot s whose keys are keywords and whose value
is boolean true .
;; good
(def ^:private a 5)
;; bad
(def ^{:private true} a 5)
Denot e privat e part s of your code.
PDFmyURL.com
;; good
(defn- private-fun [] ...)
(def ^:private private-var ...)
;; bad
(defn private-fun [] ...) ; not private at all
(defn ^:private private-fun [] ...) ; overly verbose
(def private-var ...) ; not private at all
Be caref ul regarding what exact ly do you at t ach met adat a t o.
;; we attach the metadata to the var referenced by `a`
(def ^:private a {})
(meta a) ;=> nil
(meta #'a) ;=> {:private true}
;; we attach the metadata to the empty hash-map value
(def a ^:private {})
(meta a) ;=> {:private true}
(meta #'a) ;=> nil
The only real dif f icult ies in programming are cache invalidat ion and naming t hings.
-- Phil Karlt on
When naming namespaces f avor t he f ollowing t wo schemas:
project.module
Naming
PDFmyURL.com
organization.project.module
Use lisp-case in composit e namespace segment s(e.g. bruce.project-euler )
Use lisp-case f or f unct ion and variable names.
;; good
(def some-var ...)
(defn some-fun ...)
;; bad
(def someVar ...)
(defn somefun ...)
(def some_fun ...)
Use CamelCase f or prot ocols, records, st ruct s, and t ypes. (Keep acronyms like HTTP, RFC, XML uppercase.)
The names of predicat e met hods (met hods t hat ret urn a boolean value) should end in a quest ion mark. (i.e. even? ).
;; good
(defn palindrome? ...)
;; bad
(defn palindrome-p ...) ; Common Lisp style
(defn is-palindrome ...) ; Java style
The names of f unct ions/macros t hat are not saf e in STM t ransact ions should end wit h an exclamat ion mark. (i.e.
reset! )
Use -> inst ead of to in t he names of conversion f unct ions.
;; good
(defn f->c ...)
;; not so good
PDFmyURL.com
(defn f-to-c ...)
Use *earmuffs* f or t hings int ended f or rebinding (ie. are dynamic).
;; good
(def ^:dynamic *a* 10)
;; bad
(def ^:dynamic a 10)
Don't use a special not at ion f or const ant s; everyt hing is assumed a const ant unless specif ied ot herwise.
Use _ f or dest ruct uring t arget s and f ormal argument s names whose value will be ignored by t he code at hand.
;; good
(let [[a b _ c] [1 2 3 4]]
(println a b c))
(dotimes [_ 3]
(println "Hello!"))
;; bad
(let [[a b c d] [1 2 3 4]]
(println a b d))
(dotimes [i 3]
(println "Hello!"))
Follow clojure.core 's example f or idiomat ic names like pred and coll .
in f unct ions:
f , g , h - f unct ion input
n - int eger input usually a size
index - int eger index
PDFmyURL.com
x , y - numbers
s - st ring input
coll - a collect ion
pred - a predicat e closure
& more - variadic input
in macros:
expr - an expression
body - a macro body
binding - a macro binding vect or
It is bet t er t o have 100 f unct ions operat e on one dat a st ruct ure t han t o have 10 f unct ions operat e on 10 dat a
st ruct ures.
-- Alan J. Perlis
Avoid t he use of list s f or generic dat a st orage (unless a list is exact ly what you need).
Pref er t he use of keywords f or hash keys.
;; good
{:name "Bruce" :age 30}
;; bad
{"name" "Bruce" "age" 30}
Pref er t he use of t he lit eral collect ion synt ax where applicable. However, when def ining set s, only use lit eral synt ax
when t he values are compile-t ime const ant s.
Collections
PDFmyURL.com
;; good
[1 2 3]
#{1 2 3}
(hash-set (func1) (func2)) ; values determined at runtime
;; bad
(vector 1 2 3)
(hash-set 1 2 3)
#{(func1) (func2)} ; will throw runtime exception if (func1) = (func2)
Avoid accessing collect ion members by index whenever possible.
Pref er t he use of keywords as f unct ions f or ret rieving values f rom maps, where applicable.
(def m {:name "Bruce" :age 30})
;; good
(:name m)
;; more verbose than necessary
(get m :name)
;; bad - susceptible to NullPointerException
(m :name)
Leverage t he f act t hat most collect ions are f unct ions of t heir element s.
;; good
(filter #{\a \e \o \i \u} "this is a test")
;; bad - too ugly to share
Leverage t he f act t hat keywords can be used as f unct ions of a collect ion.
((juxt :a :b) {:a "ala" :b "bala"})
PDFmyURL.com
Avoid t he use of t ransient collect ions, except f or perf ormance-crit ical port ions of t he code.
Avoid t he use of Java collect ions.
Avoid t he use of Java arrays, except f or int erop scenarios and perf ormance-crit ical code dealing heavily wit h primit ive
t ypes.
Consider wrapping all I/O calls wit h t he io! macro t o avoid nast y surprises if you accident ally end up calling such
code in a t ransact ion.
Avoid t he use of ref-set whenever possible.
(def r (ref 0))
;; good
(dosync (alter r + 5))
;; bad
(dosync (ref-set r 5))
Try t o keep t he size of t ransact ions (t he amount of work encapsulat ed in t hem) as small as possible.
Avoid having bot h short - and long-running t ransact ions int eract ing wit h t he same Ref .
Mutation
Refs
Agents
PDFmyURL.com
Use send only f or act ions t hat are CPU bound and don't block on I/O or ot her t hreads.
Use send-off f or act ions t hat might block, sleep, or ot herwise t ie up t he t hread.
Avoid at om updat es inside STM t ransact ions.
Try t o use swap! rat her t han reset! , where possible.
(def a (atom 0))
;; good
(swap! a + 5)
;; not as good
(reset! a 5)
Pref er st ring manipulat ion f unct ions f rom clojure.string over Java int erop or rolling your own.
;; good
(clojure.string/upper-case "bruce")
;; bad
(.toUpperCase "bruce")
Atoms
Strings
Exceptions
PDFmyURL.com
Reuse exist ing except ion t ypes. Idiomat ic Clojure code, when it does t hrow an except ion, t hrows an except ion of a
st andard t ype (e.g. java.lang.IllegalArgumentException , java.lang.UnsupportedOperationException ,
java.lang.IllegalStateException , java.io.IOException ).
Favor with-open over finally .
Don't writ e a macro if a f unct ion will do.
Creat e an example of a macro usage f irst and t he macro af t erwards.
Break complicat ed macros int o smaller f unct ions whenever possible.
A macro should usually just provide synt act ic sugar and t he core of t he macro should be a plain f unct ion. Doing so will
improve composabilit y.
Pref er synt ax-quot ed f orms over building list s manually.
Good code is it s own best document at ion. As you're about t o add a comment , ask yourself , "How can I improve t he
code so t hat t his comment isn't needed?" Improve t he code and t hen document it t o make it even clearer.
-- St eve McConnell
Endeavor t o make your code as self -document ing as possible.
Writ e heading comment s wit h at least f our semicolons.
Writ e t op-level comment s wit h t hree semicolons.
Writ e comment s on a part icular f ragment of code bef ore t hat f ragment and aligned wit h it , using t wo semicolons.
Macros
Comments
PDFmyURL.com
Writ e margin comment s wit h one semicolon.
Always have at least one space bet ween t he semicolon and t he t ext t hat f ollows it .
;;;; Frob Grovel
;;; This section of code has some important implications:
;;; 1. Foo.
;;; 2. Bar.
;;; 3. Baz.
(defn fnord [zarquon]
;; If zob, then veeblefitz.
(quux zot
mumble ; Zibblefrotz.
frotz))
Comment s longer t han a word begin wit h a capit al let t er and use punct uat ion. Separat e sent ences wit h one space.
Avoid superf luous comment s.
;; bad
(inc counter) ; increments counter by one
Keep exist ing comment s up-t o-dat e. An out dat ed comment is worse t han no comment at all.
Pref er t he use of t he #_ reader macro over a regular comment when you need t o comment out a part icular f orm.
;; good
(+ foo #_(bar x) delta)
;; bad
(+ foo
;; (bar x)
PDFmyURL.com
delta)
Good code is like a good joke - it needs no explanat ion.
-- Russ Olsen
Avoid writ ing comment s t o explain bad code. Ref act or t he code t o make it self -explanat ory. ("Do, or do not . There is
no t ry." --Yoda)
Annot at ions should usually be writ t en on t he line immediat ely above t he relevant code.
The annot at ion keyword is f ollowed by a colon and a space, t hen a not e describing t he problem.
If mult iple lines are required t o describe t he problem, subsequent lines should be indent ed as much as t he f irst one.
Tag t he annot at ion wit h your init ials and a dat e so it s relevance can be easily verif ied.
(defn some-fun
[]
;; FIXME: This has crashed occasionally since v1.2.3. It may
;; be related to the BarBazUtil upgrade. (xz 13-1-31)
(baz))
In cases where t he problem is so obvious t hat any document at ion would be redundant , annot at ions may be lef t at t he
end of t he of f ending line wit h no not e. This usage should be t he except ion and not t he rule.
(defn bar
[]
(sleep 100)) ; OPTIMIZE
Use TODO t o not e missing f eat ures or f unct ionalit y t hat should be added at a lat er dat e.
Use FIXME t o not e broken code t hat needs t o be f ixed.
Comment Annotations
PDFmyURL.com
Use OPTIMIZE t o not e slow or inef f icient code t hat may cause perf ormance problems.
Use HACK t o not e "code smells" where quest ionable coding pract ices were used and should be ref act ored away.
Use REVIEW t o not e anyt hing t hat should be looked at t o conf irm it is working as int ended. For example:
REVIEW: Are we sure this is how the client does X currently?
Use ot her cust om annot at ion keywords if it f eels appropriat e, but be sure t o document t hem in your project 's README
or similar.
Code in a f unct ional way, avoiding mut at ion when t hat makes sense.
Be consist ent . In an ideal world, be consist ent wit h t hese guidelines.
Use common sense.
There are some t ools creat ed by t he Clojure communit y t hat might aid you in your endeavor t o writ e idiomat ic Clojure
code.
Slamhound is a t ool t hat will aut omat ically generat e proper ns declarat ions f rom your exist ing code.
kibit is a st at ic code analyzer f or Clojure which uses core.logic t o search f or pat t erns of code f or which t here might
exist a more idiomat ic f unct ion or macro.
Existential
Tooling
PDFmyURL.com
Not hing writ t en in t his guide is set in st one. It 's my desire t o work t oget her wit h everyone int erest ed in Clojure coding st yle,
so t hat we could ult imat ely creat e a resource t hat will be benef icial t o t he ent ire Clojure communit y.
Feel f ree t o open t icket s or send pull request s wit h improvement s. Thanks in advance f or your help!
This work is licensed under a Creat ive Commons At t ribut ion 3.0 Unport ed License
A communit y-driven st yle guide is of lit t le use t o a communit y t hat doesn't know about it s exist ence. Tweet about t he
guide, share it wit h your f riends and colleagues. Every comment , suggest ion or opinion we get makes t he guide just a lit t le
bit bet t er. And we want t o have t he best possible guide, don't we?
Cheers,
Bozhidar
Contributing
License
Spread the Word
PDFmyURL.com
Git Hub Git Hub
About us About us
Blog Blog
Contact & support Contact & support
GitHub Enterprise GitHub Enterprise
Site status Site status
Applicat ions Applicat ions
GitHub for Mac GitHub for Mac
GitHub for Windows GitHub for Windows
GitHub for Eclipse GitHub for Eclipse
GitHub mobile apps GitHub mobile apps
Services Services
Gauges: Web analytics Gauges: Web analytics
Speaker Deck: Presentations Speaker Deck: Presentations
Gist: Code snippets Gist: Code snippets
Job board Job board
Document at ion Document at ion
GitHub Help GitHub Help
Developer API Developer API
GitHub Flavored Markdown GitHub Flavored Markdown
GitHub Pages GitHub Pages
More More
Training Training
Students & teachers Students & teachers
The Shop The Shop
Plans & pricing Plans & pricing
The Octodex The Octodex
2013 2013 GitHub GitHub, Inc. All rights reserved. , Inc. All rights reserved. Terms of Service Terms of Service Privacy Privacy Security Security
[[
PDFmyURL.com

You might also like