SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
1.
Code Quality
A brief introduction to writing code that is
scalable, shareable and usable.
Wednesday, 18th May 2016
2.
Hayden Bleasel
Product Designer, Entrepreneur &
Full-Stack Developer. Previously
at Zookal, Sumry and Palantir.
@haydenbleasel on Twitter,
GitHub and pretty much
everywhere else.
Nice to meet you.
3.
What languages do you write and how
do you ensure code quality?
Quick Question
4.
• Bad code: use once, copied from StackOverflow, thrown
away after or used to hotfix a bug
• Good code: used multiple times over several projects,
maybe a small plugin
• Great code: well-thought-out, up to date, unit tested and
maybe even open-sourced and built by the community
• We need to measure and enforce quality code.
What is “Quality Code”?
5.
• Clear and understandable design and implementation.
• Well defined interfaces.
• Ease of build and use.
• Ease of extensibility.
• Minimum extra dependencies.
• Tests and examples.
• Great documentation or self-explaining code.
• Up to date means to contact the developer.
Goals of Quality Code
6.
• European Space Agency took 10 years and $8
billion dollars to develop Ariane 5 (heavy lift
launch rocket).
• On June 4, 1996, it took its first voyage with $500
million cargo. In 40 seconds its inertial reference
system failed.
• 64-bit floating point number representing the
horizontal velocity of the rocket was converted
into 16-bit signed integer — conversion failed
because of overflow.
Why bother with quality?
7.
• Finding, fixing problem in production is 100 times more expensive than during
requirements / design phase.
• 40-50% of effort on projects is on avoidable rework.
• ~80% of avoidable rework comes from 20% of defects.
• ~80% of defects come from 20% of modules; about half the modules are defect free.
• ~90% of downtime comes from at most 10% of defects.
• Peer reviews catch 60% of defects.
• Perspective-based reviews catch 35% more defects than nondirected reviews.
• Disciplined personal practices can reduce defect introduction rates by up to 75%.
• ~40-50% of user programs have nontrivial defects.
But seriously, why bother?
8.
• Nobody has time to check their code, we’re all
busy trying to make amazing things.
• You need 2 things:
A. To know how to write good code (you think
you do but you really don’t).
B. To start using an array of tools and workflow
to your advantage.
But I don’t have time to check code!
9.
• Not really. The QA is meant to go over your output
and look for bugs in runtime and edge cases, not
to browse your junk code and make incremental
improvements.
• The only thing that does is gives the QA a reason
to yell at you about writing janky code and you’ll
go back to the drawing board (that, or more likely
it’ll leak into production and hilarity ensues).
Isn’t this the job of a QA?
10.
This is basically a giant to-do list for when you go home,
things you can add to your product, startup or app.
Practical Implementation
11.
Bill Gates
Measuring programming progress by lines of
code is like measuring aircraft building
progress by weight.
12.
• Writing code with style
• Keeping code in check
• Making code less confusing
Overview
• Managing dependencies
• Git and GitHub
• Automation and Testing
14.
• Don’t give variables cryptic names e.g.
Meaningful Variable Names
001. Writing code with style
x1 = 60;
x2 = 24;
x12 = x1 * x2;
• They don’t save space - you can compress the
output using a minifier. Might as well just use:
minutesPerHour = 60;
hoursPerDay = 24;
minutesPerDay = minutesPerHour * hoursPerDay;
15.
• This doesn’t lead to scalable code:
Using Constants
001. Writing code with style
coffee = makeCoffee(2)
• What does 2 mean? What does this function even
accept? We can introduce constants here:
SIZES = { small: 1, large: 2 };
coffee = makeCoffee(SIZES.large)
• We generally use uppercase for constants.
16.
• This function utilises it’s purpose stringently:
Flexible functions
001. Writing code with style
makeGrid = function (width) {
for (var i = 0; i < 12; i++) {
makeColumn(12 / width, 30);
}
}
• We can make this a bit more flexible:
makeGrid = function (width, columns, gutter) {
for (var i = 0; i < columns; i++) {
makeColumn(columns / width, gutter);
}
}
makeGrid(1170)
makeGrid(1170, 12, 30)
17.
• It’s pretty simple stuff, just go through all your
code and find thing to improve or fix.
• Look for runtime errors (overflows, type checking,
overwriting variables, memory leaks, etc).
• Look for syntax errors (missing a bracket or
semicolon, using 1 ampersand instead of 2)
• Look for logic errors (passing in the wrong
number, calling the wrong function).
Code Analysis
001. Writing code with style
18.
• There are two pretty fundamental things you
should avoid when writing large projects
(especially for open-source):
• Black boxes: Functions where parameters go
into, pure magic happens and an output comes
out, but we have no idea how it works.
• TODOs and Hacky Workarounds: Avoid them.
However, if you’ve got hacks or unfinished
code, document them somewhere outsite the
codebase, like GitHub issues.
Avoid Black Boxes and Hacks
001. Writing code with style
19.
• More lines of code typically means less code
quality. In each file or function, pick one thing and
do it really well, a bit like running a startup.
• Repeated lines of code or code that looks
incredibly similar in terms of structure and
purpose can be rewritten as a function.
• Seperate your code out into different files. Make
sure each file handles a small part of your app.
Refactoring and LOC
001. Writing code with style
20.
• If your linter, terminal or whatever throws a
warning, don’t ignore it.
• Warnings can outline hidden problems that you’ll
run into severely later on.
• Use the compiler or linter to treat warnings as
errors and you’ll be writing amazing code.
• If absolutely necessary (legacy code or
something), you can suppress warnings.
Treat Warnings as Errors
001. Writing code with style
21.
• Some languages, like Javascript and Perl, have a Strict mode that
you can enable.
• It makes several changes to normal language semantics.
• In JavaScript for example, Strict Mode:
• Eliminates some silent errors by changing them to throw errors.
• Fixes mistakes that make it difficult for JavaScript engines to
perform optimisations: strict mode code can sometimes be
made to run faster than identical code that's not strict mode.
• Prohibits some syntax likely to be defined in future versions of
ECMAScript.
Strict Mode
001. Writing code with style
23.
• A giant report documenting how you
and your collaborators should write
code on a particular project.
• Google has a massive one covering
every language they use: https://
github.com/google/styleguide
• Useful for when you’re running a
company or agency where heaps of
people are touching the same code.
Style Guides
002. Keeping code in check
24.
• Everything we’ve just discussed - that’s a lot of
work. Checking, refactoring, rewriting…
• Wouldn’t it be better if the code just checked
itself? (before it wrecked itself)
• Welcome to the wonderful world of rules. You
want your codebase to have rules, such as “make
sure every file ends with a newline” and “make
sure I use anonymous function callbacks all the
time”. The possibilities are endless.
Automagical code checking
002. Keeping code in check
25.
• Check it out at http://
editorconfig.org/
• Comes as a plugin for almost
every text editor and IDE
imaginable.
• Define extension-based rules
like newlines, charsets and
indenting.
• Runs and fixes on file save.
.editorconfig
002. Keeping code in check
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
[*.json]
indent_size = 2
26.
• My absolute favourite part of
this topic on code quality.
• Linters are absolutely
amazing and indispensable.
• They check your code as
you’re writing it.
• They literally enforce your
style on everyone else.
Linting
002. Keeping code in check
27.
• Some languages, like Javascript, have lots of
linters to choose from: JSLint, ESLint, JSHint, etc.
All of these can be configured, but the default
options and extensibility varies.
• ESLint is the one shown in these examples. It’s
the newest, most extensible linter for Javascript.
• You can most linters via CLI, automation module
(Gulp or Grunt) and text editor plugin.
Choosing a Linter
002. Keeping code in check
28.
"comma-dangle": [2, "never"],
"no-cond-assign": [2, "always"],
"no-console": 0,
"no-constant-condition": 2,
"no-control-regex": 2,
"no-debugger": 2,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-empty": 2,
Linter Configuration
002. Keeping code in check
• Configuring your linter is a tedious process.
My .eslintrc is 350 lines long:
eslint.haydenbleasel.com
29.
How I use my linter
002. Keeping code in check
brew cask install atom
apm install linter linter-eslint
npm install -g eslint
• Getting a Linter set up is mad easy. Just install the
module and plugins:
• That’s it! Just start writing code and save!
31.
• Text editors can massively affect code quality,
from default intent style to external plugins.
• I use Atom, a text editor by GitHub. It comes with
an inbuilt package manager.
• Packages like linter (+eslint), atom-beautify and
editorconfig address things we’ve talked about.
Text Editors and Plugins
002. Keeping code in check
33.
• Coupling determines how much one component
of your code knows about the inner workings of
another. We want to aim for LOW coupling.
• Ex: iPods are a good example of tight coupling:
once the battery dies you might as well buy a new
iPod because the battery is soldered fixed and
won’t come loose, thus making replacing very
expensive. A loosely coupled player would allow
effortlessly changing the battery.
Coupling
003. Making code less confusing
34.
• Cohesion refers to the extent that a component
of your code is focused only on what it should be
doing. We want to aim for HIGH cohesion.
Cohesion
003. Making code less confusing
function main (a, b) {
var x = (a * b) / 3;
var body = $(‘body’);
body.appendChild(x);
}
main(1,2);
function multiply (a, b) {
return (a * b) / 3;
}
function append (number) {
var body = $(‘body’);
body.appendChild(number);
}
var number = multiply(1,2);
append(number);
35.
• There are two main ways to minimise the complexity of
your code. Neither should be your ultimatum, but rather
a great referencing guide:
1. Pretty simple: just minimise the number of
parameters, depth (nesting) and statements per
function
2. Run a cyclomatic complexity test. It calculates
the overall intricacy of a function and to give a
score that reflects it’s complexity. Lower is better.
Complexity
003. Making code less confusing
37.
• A common pitfall that results in loss of code quality,
even in large organisations, is poor dependency
management.
• Vendor code is downloaded, chucked in a random
folder and modified to the core if it doesn’t work the
way you want it to.
• This results in all sorts of bugs and creates a generally
crap work environment for the developer.
Dependency Management
004. Managing dependencies
38.
• Bower is a package
management system
developed by Twitter.
• Bower is used to download
and manage front-end
development packages like
jQuery and Bootstrap.
• For example:
Bower
004. Managing dependencies
bower install jquery --save
39.
• Server-side applications also have dependency
management, except much better.
• Node.js has NPM, Ruby has Bundler and PHP has
Composer. There are plenty of dependency
management tools out there for any language.
• Rather than messing around with files and versions,
just get the latest version of Request with:
NPM / Bundler / Composer
004. Managing dependencies
npm install request --save-dev
40.
• If you’re not using a dependency manager but still want
to maintain the integrity and separation of your
codebase from third-party components, CDNJS is a
good option.
• Again, front-end components. Doesn’t have everything
but should have 99% of what you need.
• Just throw in a script tag like:
CDNJS
004. Managing dependencies
<script src=“https://cdnjs.cloudflare.com/ajax/libs/jquery/
3.0.0-beta1/jquery.min.js"></script>
42.
• You should kinda know this already. Git tracks version
history so you can see what you’ve done, revert
changes and blame mistakes on other people.
• Remember to check in your code in small batches,
frequently. Reverting massive amounts of unrelated
code is a nightmare plus it helps avoid merge conflicts.
• Version control is also helpful for semver integrity.
Version Control
005. Git and GitHub
43.
• GitHub is the best platform ever for developers.
• Use Issues to track your TODOs, hacky workarounds,
suggestions from others, etc. Keep the discussion out
of your codebase.
• Use PRs to filter external changes to your code. PRs
allow for Code Reviews where you can go through
every change in the diff and add comments.
Issues and PRs
005. Git and GitHub
44.
• Can happen in a variety of ways, but likely when you
gather all the homies together and start reviewing
code that you’ve written or that’s in your codebase.
• Great way to pick up and debate really small things that
might lead to a significant improvement in
performance, or maybe just be really pedantic.
• Theoretically, you’re meant to be positive i.e. instead of
“that’s lousy long method” say, “why don’t you split
that method…” but TBH most of us are savages.
Code Reviews
005. Git and GitHub
46.
• The original task-runner.
• Their architectural concept
sucks (pickup and put-down)
but it’s pretty widely used.
• Stop writing production code
in source, focus on quality of
source code and let your
automation handle the rest.
Grunt
006. Automation and Testing
47.
• Best task runner available -
unix streaming ideology
inside the JS ecosystem.
• Set up a bunch of tasks and
send files through the
pipeline (stream) without
touching the file system.
• Compile languages, remove
debug code, whatever.
Gulp
006. Automation and Testing
48.
• Write a script to test your
app. Can be as simple as
“npm start” which just runs
the app.
• Will automatically run this
every time you push to
GitHub.
• Also tests GitHub PRs - test
new code before you merge.
Travis CI
006. Automation and Testing
49.
• So you’ve written unit tests for your code, but how
much have you written in the scheme of things?
• JS has Mocha, Chai, Istanbul and other libraries to
handle this sort of things.
• It’s called test coverage - TL;DR it will give you a report
on how much of your codebase is covered by unit tests.
Most of them compute statement, line, function and
branch coverage with module loader hooks.
Coverage
006. Automation and Testing
50.
Go forth and stop writing bad code.
That’s everything
http://codequality.haydenbleasel.com/