If, like me, you grew up before the internet was a commercial affair, then you will have learned, mostly the hard way, to make code more robust through experience and battle scars. Those of you who grew up with the internet and have always been ‘online’, have the benefits of growing up with fantastic new languages, techniques and ways of thinking, however it has been observed that somehow in all the rush towards this new world, we’ve somehow lost some of the art of earlier generations.
In this talk we’ll explore the art of defensive programming, from both philosophical and practical perspectives, highlighting how it can be added to our repertoire of tools to enable us to add value and reduce failures in our code.
If, like me, you grew up before the internet was a commercial affair, then you will have learned, mostly the hard way, to make code more robust through experience and battle scars.
Those of you who grew up with the internet and have always been ‘online’, have the benefits of growing up with fantastic new languages, techniques and ways of thinking, however it has been observed that somehow in all the rush towards this new world, we’ve somehow lost some of the art of earlier generations.
I’ve been a developer for almost 20 years and have long history of consulting, adopting other peoples projects and running a kick-ass software agency.
For my day job, I am CEO of Magma Digital Ltd, a 20 strong team focussing on delivering business critical software development, using PHP, to enterprise.
I am also the driving force behind the UK's PHPNW conference, user group and brand, I started the group in 2008 and have, with assistance from many others, helped the group to be able to deliver eight years of high quality conferences, now with 400+ delegates. The passion for this comes from my personal drive to improve skills in those around me who I serve through mentoring, coaching, training and speaking.
Pleasure of attending all but 1 Benelux conference and speaking at PHPBNL 12, 14 and now 16 - seems like even numbered years are my thing!
BBC B December 1st 1981
I grew up in the era of the emerging internet (I even remember times before mobile phones and Google!), as new technology sprang up, there were no StackOverflow forums to guide us - you had your guile and search engines like Alta Vista to help.
This is the time before TDD existed, rich toolchains and great IDEs, it was the more painful var_dump/die era.
I’m now seeing a worrying trend where new entrants to our world, do not know how to protect themselves and their clients from basic mistakes - they repeat the testing and agile mantras, however somehow they’re missing something quite basic. This talk will address some of those issues and hopefully will reinforce good practices for those of you already engaging with them and encourage the rest of you to dive in.
Sod’s Law is the one I reach for the most - essentially defensive programming is about hoping for the best but expecting the worst - at all levels of your project.
Taking a pessimistic view of what could go wrong, rather than waiting for it to do so in production!
If things fail, make sure it’s known about - Klaxons, or Slack channel alerts - filp/whoops (https://github.com/filp/whoops), Monolog (https://github.com/Seldaek/monolog) -> Slack / Hipchat etc.
TDD - answer to ‘everything’ - so annoying, just because you have test coverage doesn’t mean it’s a robust / stable system.
Discipline - not meant to constrain, the contrary it’s meant to support creativity - once you know you’ve got stable, robust systems you can concentrate on the new & unique ideas! Get away from ‘Works on my machine!’ syndrome!
Minimise the assumptions that creep into projects!
Dev and Ops - configuration management databases (ansible, salt, puppet, chef), predict your infrastructure.
Are the new technologies defensive choices? / What’s wrong with your existing stack?
Do you keep up with advancements / improvements in your existing tech, or do you just assume it’s business as usual?
Name 3 new features in MySQL 5.7? InnoDB enhancements: now supports full-text parsers; ngram full-text parser for Chinese, Japanese & Korean; Native JSON data type - internal binary storage; Now can have multiple triggers per table; Better security, performance ++ over 5.6; https://dev.mysql.com/doc/refman/5.7/en/mysql-nutshell.html
As engineers we need to learn to get our ‘buzz’ from client feedback - ‘Wow this feature is great’! Be masters of business domain, solve the real problems, learn better approaches (patterns) - being a magpie with tech is a distraction!
Admin passwords, UAT - change before deploy live Config - store in the environment - http://12factor.net/
Write code for others to consume, including your future self!
Even though PHP itself it riddled with it, try and avoid having different return types from methods
Log and catch - having clients or Google show you the error messages is probably not the best for your reputation!
Code is harder to maintain without good structure - personal philosophy is that good code is like poetry - has recognisable form and flow.
No peer review - prone to errors not visible to the developer writing it, too close to your own code to see the failures. Pull requests, code reviews, pair programming.
Single technique zealots, as with some of the TDD for everything crowd, leads to a blinkered view of solutions / problems. False sense of security - ‘but we’ve got good code coverage’! Sure have preferences but urge you to be more eclectic in choices to remain flexible.
Documentation - in the project - Markdown etc. Wikis - people seem to assume “We’re agile we don’t document!” - very poor show.
Architecture - what approach does the team take - standard patterns, common choices for e.g. date handling, where does the business logic belong - if you’re not having these discussions or adopted a team style then there’s a likelihood of low defence walls - there will be trouble ahead!
Just because you’ve got a certain % of test coverage doesn’t mean you’ve got a robust system ready for production. Tests are great, but they need to address more than codebases coverage!
QA tools - ideally run in Continuous Integration, or on save in your IDE PHPMD, PHP Code Sniffer, PHP Metrics (.org) Profiling: XDebug, blackfire.io
OS X - Xcode -> Open Developer Tool -> More Developer Tools -> Hardware IO Tools (need dev account) -> Network Link Conditioner - http://blog.tcs.de/simulate-slow-network-connection-on-mac-os-x/ Linux - tc’s netem - simulate delays or packet loss - http://stackoverflow.com/questions/614795/simulate-delayed-and-dropped-packets-on-linuxhttp://bencane.com/2012/07/16/tc-adding-simulated-network-latency-to-your-linux-server/
Caches - OMG - number of times see this! Caches - are just temporary, they should be planned as a part of infrastructure designed to fail - they are for scale, not speed!
Always quote yourself, unless you can quote Batman Anthony Ferrara, then always quote Batman Anthony Ferrara!
(even better if you can quote out of context!)
Use PHPLeague/flysystem - abstract the file system to test redundancy and be prepared for scaling up when the need arises
Make sure services run as expected - make sure they’re started at boot up and use SupervisorD or similar to ensure things restart on failure
What happens if your replication fails - you do have a plan for that don’t you? You have got the change master statement scripted or in the project documentation haven’t you, you know for when things go wrong and the world’s on fire?
Service went away - real world example from another agency WTAF! - it’s 2016 people, this is not a professional level of service, given the tools we have at our disposal. However, it’s all too common in our experience.
“I’m pretty good at breaking things, but some of my clients are better” @petradreis
Team approach - about making solving the issues a first class citizen in your culture
Busy on all the wrong things
Noisy logs - pet hate - code with clean logs - less cognitive overhead & when things are on fire - much easier to see what’s going on!
Dev with E_ALL on I dare you! Clean logs with E_ALL error reporting saves a lots of “what’s going on” questions, clean as you go, rather than ‘fix’ by reducing error reporting in production! Don’t forget display_errors to see the output in dev
Tail your logs during dev - tail -f /var/log/apache/error_log | grep “xx”
Graphite / Statsd - https://codeascraft.com/2011/02/15/measure-anything-measure-everything/ - Node.js / Python. Can see when your clients take their lunch breaks!
New Relic - found an namespace error in a project whilst preparing for this talk - integrated with Jira - was able to open a ticket straight away - otherwise would have been missed! Not just for errors, also performance - UX, slow queries etc. New Error Analytics section is cool!
Log visualisation tools - saves wading through large amounts of data, focus on things that interest you rather than noise (esp. in legacy) - NewRelic/Loggly integration via Chrome plugin
Chat system integration - Slack, Hipchat etc. useful for the most critical of errors, filter via Monolog if too noisy - hopefully demo
NewRelic, showing a production server with low error rates, and good user response times (Appdex scores)
Databases - Live data editing, sometimes necessary evil - always make it a pair programming job - second pair of eyes to ensure you’ve got that all important where clause in place!
Plan for the any expected lifecycle of the project - load the DB with (fake) records, to see how it performs under scaled data. Also test that load on the real hardware, number of times I’ve seen it work fine on a nice SSD based dev machine and crawl miserably in production - indexes are your friend.
Also seen the opposite - where the lack of an index on a small table that had been joined to in a complex query ended up taking the service down with a query queue cascade - “Don’t know what’s wrong, it worked on my machine!” - Doh!
How do you upgrade / ship your vendor libraries? composer.lock in the repo! upgrade everything before you deploy right! Nooooo! composer update on live? Like to live dangerously? Nooooo!
Discipline about Back end - don’t apply same to Front end: what about npm, grunt/gulp etc. package.json bower.json Gruntfile.js
not a silver bullet!
The Lost Art of Defensive Programming
The Lost Art of
Who am I?
๏ Jeremy Coates, CEO, Magma Digital Ltd
๏ Founder of PHPNW User Group & Conference
๏ Lancashire Digital CIC Founding Director
๏ International Conference Speaker
๏ Coach of Coaches - WeCa.mp (code camp)
BBC Micro (Model B!)
8-bit, 32Kb, 2Mhz
๏ Purpose — Prompt thought, Discussion,
Reasoned argument (in the bar!)
๏ Themes — Philosophy;
Professionalism; Practical examples
๏ Convey a sense / approach —
not a rote-learnable technique(s)
๏ Murphy’s Law: “Anything that can possibly go wrong,
๏ Finagle’s Law: “Anything that can go wrong, will - at
the worst possible moment.”
๏ Sod’s Law: “If something can go wrong, it will”
(in British culture: “at the worst possible time”)
• “Hope for the best, expect the worst.”
๏ Plan for the worst — related to Fail Fast - with klaxons!
๏ Not anti-TDD, complimentary
๏ Security focussed — code, privacy,
๏ Discipline — planning, consistency, shared
standards (team), comments!
๏ Cross over point between Dev and Ops
๏ All engineers love new shiny! and other myths:
• “New systems need new tech!”
• “Old is slow”, “It doesn’t scale”
• “It’s just not cool any more”, “It breaks when”
๏ Longevity, scale, licensing, compliance, risk, support
๏ In a war with hackers, bots, human mistakes
๏ Tactics — establish a defensible perimeter
๏ Attempt to prevent
• Defacement, Malware, Link
injection, privilege escalation
๏ Filter Input, Escape Output — Filtering is not about preventing
security vulnerabilities, it's about not populating your database
with garbage. If you're expecting a date, make sure it at least
looks like a date prior to storing it.
๏ CSRF / XSS / CORS / SQL Injection
๏ Password hashing / Nonce hashes
๏ SSL — current generation — TLS 1.2+
๏ Deal with default states
๏ Ambiguity in return types
๏ Don’t spill errors to users
- try/catch; log
“When you assume,
you make an ass out of u and me”
Oscar Wilde on Assumption
๏ Mixed coding styles / naming / PSR - x
๏ One technique to rule them all
๏ Peer review
The unit tests all pass
We’ve got good code coverage!
๏ Latency varies — simulate
• OS X Xcode Hardware IO
Tools: Network Link
๏ Caches — temporary storage
• Plan for failure, code
shouldn’t rely on it being
Remove key components
Network Link Conditioner
๏ Low bandwidth — simulate
• Hotspot to your phone and turn
๏ File systems fail — abstract —
๏ Server reboot — do services
๏ Failover — kill the master or slave
Remove key components
๏ Block third party services:
• Test socket timeouts, API error handling
Remove key components
๏ Narrowing down to errors
• Actually read the error message!
• Not just Googling parts of the message
๏ Develop a strategy
• Be scientific, eliminate sources one at a time
๏ Noisy logs - reduce / eliminate unexpected output
— work with error_reporting(E_ALL) — in dev
๏ Graphite / StatsD — measure everything else
about your software,
method calls, key
actions, any events,
Practical approaches: Logs
๏ Database — indexes, field types, query
๏ Test for planned scale — ab, siege, jMeter,
๏ Automation is the key
• Rsync; Phing; Ansible; DeployHQ; Capistrano
• Symlink switching; full Atomic deploys
๏ Continous Integration — Jenkins, Bamboo etc.?
๏ Upgrading libraries — just
๏ Front-end — same strategy
• composer.lock, package.json,
๏ Defensive programming
• more than just code, lots of moving parts
• easier to learn with feedback from peers
• requires discipline and experience
• risk management, there’s a war on!
๏ Jeremy Coates, CEO, Magma Digital Ltd
๏ Founder of PHPNW User Group & Conference
Lost Art? https://joind.in/talk/a6b65