Many freelance developers, however mostly beginners often come to this issue: I’ve been working on a (web) project on and off for a long time now… How can I change this part of my code and not break anything and affect the production?
Problem: THE FEAR OF BREAKING PRODUCTION
“If I tweak this part of the code, taking that all is ok with the syntax, will it break some part of the system?”
It’s hard to know most of the time!
And you usually cannot afford killing the production, even for a minute!
Users are using the service and they will curse you, ask their money back and leave forever if it’s broken…
Sounds familiar? Does to me.
Do not think for a minute there’s a good way to change live production code and make it work, while at the same time not caring about the immediate effects. It’s just not good practice and usually causes sleepless nights.
THE REAL SOLUTION:
Once working on a project, you should be able to stop and continue at any point, except when pushing to production which should never last more than a few minutes. The size of the project does not really matter in this sense.
The only way you would be able to do this is by working in a test environment. That means if your developing a web project you should have at least two code repositories:
1) The Testing Repository
2) The Production Repository
And also the Bare Repository which is “central” and keeps only tested and valid states of your project. The key is to sync your Production Repository with the Bare one each time a new feature is properly implemented and tested.
Also you should have two corresponding environments you can access:
1) The Testing Domain ( e.g. test.myproject.com )
2) The Production Domain ( e.g. www.myproject.com )
Both mapped to corresponding code repositories.
The most important part of it all is to be familiar and comfortable with UNIT TESTING.
And also the Agile approach to test-driven development:
1) YOU DO NOT WRITE A SINGLE LINE OF PRODUCTION CODE UNTIL YOU CREATE A TEST THAT COVERS IT
2) ONCE THE TEST IS WRITTEN, WRITE ONLY ENOUGH PRODUCTION CODE SO YOU GET NO ERROR OTHER THEN A FAILED TEST ( usually just the prototype of a function – a function with an empty body )
3) RUN THE TEST AND MAKE SURE IT FAILS, IF IT DOES NOT FAIL, YOUR TEST IS PROBABLY USELESS OR IT’S STILL TOO SOON TO WRITE IT (never rush)
4) CREATE THE SIMPLEST POSSIBLE SOLUTION THAT COMES TO MIND IN ORDER TO PASS THE TEST ( e.g. return 100; )
5) SEE THE TEST PASS
6) WRITE ANOTHER TEST FOR A REQUIREMENT WHICH WILL SURELY FAIL
7) CHANGE THE PRODUCTION CODE SO ALL TESTS ARE SATISFIED
8) REPEAT UNTIL DONE
9) RUN ALL UNIT TESTS IN YOUR PROJECT AND SEE THAT THEY PASS
10) DRINK BEER, YOU EARNED IT!
Pitfall prevention: “PRODUCTION CODE” above refers to the implementation of a feature, and not to code running in a production environment.
Although it may seem your wasting time, your actually saving time in the long run and as you progress you’ll only work faster doing it this way.
I can’t imagine there was a time when I did not know about this. But can you imagine how my life got better once I did come to know it? All the women, fame and glory and what not?
Another important thing to point out is that all of your unit tests should never leave traces behind. For example, your test should never end up writing to a database or a file nor send an e-mail. That means you have to properly decouple and implement your project architecture.
Usually this is done by DEPENDENCY INJECTION and creating MOCK OBJECTS ( objects which simulate required behavior but don’t really make any permanent changes ). Dependency injection in a sentence: Do not use the “new” keyword if the implementation is not at the topmost level ( e.g. a main function or script ). Which means all dependencies should be injected at some point ( usually upon constructing the object ). In other words, every object which lives in your code should be somehow externally configurable. Avoid the object instancing operator (“new” keyword) as long as you can!
So here is a what a typical scenario would look like, read carefully:
09:00 am – read an e-mail saying you have to implement a feature X
09:01 am – access your testing repository and bring up your testing domain
09:03 am – start preparing the first unit test for the new feature
09:05 am – finished the first test and tried to run it, you see it FAIL and it’s absolutely essential that it does – you have a smile on your face because of it!
09:07 am – now you start to implement the part of the feature in order to pass the test, and it does – you’re smiling again
09:08 am – prepare the next test and repeat the process
09:45 am – implemented a dozen tests and the entire feature is ok, all unit tests have first failed and now they all pass
09:46 am – send e-mail saying: I’ve implemented your new feature, please confirm that’s all you need and that it works as expected
10:15 am – receive e-mail saying: “Looks good, but could you just add this …”
10:17 am – write the single test required to accommodate the update of the feature
10:20 am – see the test fail, smile, start implementing to pass
10:22 am – all now works for the new feature
10:24 am – run all previously written unit tests on the whole project and see them all pass – this means nothing got broken and your new feature works – it is very important to do this!
10:26 am – send e-mail asking if that is all required…
10:30 am – e-mail response: “All is ok, let’s push it to production”
10:35 am – commit all the changes and push them to the bare repo
10:38 am – access your production repository and pull the changes from the bare repo
10:40 am – new feature is working in production with no issues.
10:41 am – the beer drinking commences (although it’s still quite early)
So this way you’ll always push only working code to production, your bug rate will rapidly decrease and you won’t worry about any implementation at all. Because you have tests that support the use cases and which you trust. Most of all, THE FEAR of breaking things is gone…
You can always come back to any part of code and mess around, optimize it, refactor it and make it work again while it becomes more readable and easier to maintain.
That’s what I call happy coding.
A Word about git
I use this ZERO-FEAR pattern all the time, and couldn’t achieve it without using GIT.
So if your new to it, start learning git right away!
Don’t have a testing server environment with full control?
You can get one for $5 a month and you pay only the hours you use it (talking about a few cents here), rest of the time you can put it to sleep. You get 512 MB RAM with fast SSD disk and any linux distro your heart desires.
See what DIGITAL OCEAN can do for you!
I use it for my testing all the time. The guys at Digital Ocean are great!
Happy coding indeed!