## Whoops!
-It's bound to happen. Something that you thought was good didn't work the way you planned and now you're realizing that you've made a terrible error. Sometimes it's something that could have been avoided (committing in code that was meant for debugging for instance). The ones that really frighten me though are the ones that I did not expect at all. It's the side-effect from using a module in a way that you later learn wasn't intended to be used that way. It's the realization that this small module will be part of a larger module and your code isn't designed to make a smooth transition.
+It's bound to happen. Something that you thought was a good idea didn't work the way you planned and now you're realizing that you've made a terrible error. Sometimes it's something that could have been easily avoided (committing in code that was meant for debugging for instance). Sometimes it's a cascade of errors, each piling on the efforts on the previous error. There's the side-effects of using a module in a way that you later learn wasn't intended to be used that way. Or it's the realization that you've designed a small module and later realize that module will be part of a larger piece of software and your code isn't designed to make a smooth transition. Whoops!
+
+The ones that really frighten me though are the ones that I did not expect at all where the unintended consequences run rampant throughout the system. Those sorts of errors keep me up at night.
Programmers make mistakes. The nature of our jobs requires us to be aware at all times of what is going on in multiple sections of code and no matter what safeguards we put into place we lose track of the state of our program and committed code. We rush and rely on muscle memory to pick up the slack. We deny ourselves areas where we can adequately test code because we feel we need to get things done sooner.
## Avoiding mistakes
-Let's be clear: there's no way to eliminate mistakes. Software is too complex to be completely bug free. But what we can do is create places where we can tease out as many bugs as possible from the code before we put it out in front of others. When we have the ability to debug and test our code we get to better places of understanding what the code is doing and how it behaves under certain circumstances. Creating a model environment of the target system allows us to test our code against what we think the target system will do and how it will behave.
+Let's be clear: there's no way to eliminate mistakes. Software is too complex to be completely bug-free. But what we can do is create places where we can tease out as many bugs as possible from the code before we put it out in front of others. When we have the ability to debug and test our code in a safe environment we can better understanding what the code is doing and how it will behave under certain circumstances. Creating a model environment of the target system allows us to test our code against a miniaturized version of the target system's reality and see how it behaves under those conditions.
-We put a lot of emphasis on avoiding mistakes, both in programming and in programming culture. There are horror stories told of how a small bug in a program caused enormous pain for those involved. The morals of the story tend to illuminate that a simple mistake can be a costly mistake and we need to be more diligent about avoiding mistakes. All these tales do is make programmers more paranoid about making any mistakes. And when we operate in a fear-based mode we begin to panic. Telling programmers to make no mistakes is akin to telling someone not to be afraid - they then become afraid of being afraid.
+We put a lot of emphasis on avoiding mistakes, both in programming and in programming culture. There are horror stories of how small bugs in a program caused enormous pain for those involved. The morals of those stories illuminate that a simple mistake can be costly and we need to be doubly careful about avoiding mistakes. All these tales do is make programmers paranoid about making any mistakes at all, and when we operate in a fear-based mode we begin to panic. Telling programmers to make no mistakes is similar to telling someone not to be afraid: they become more afraid of being afraid.
-The only way we learn is by making mistakes. When we deprive ourselves of making mistakes we deprive ourselves of the opportunity to make mistakes. That doesn't mean we have to make every mistake that other developers have made before us (that would be a lot of mistakes). But we need to make our own mistakes in order to keep learning and to figure out where our gaps in understanding are.
+The only way we learn is by making mistakes. When we deprive ourselves of the freedom to make mistakes we deprive ourselves of the learning opportunities in making those mistakes. That doesn't mean we have to make every mistake that other developers have made before us (that would be a lot of mistakes). Nor does it mean that we need to introduce chaos into our development process in order to learn better. What it means is that we need to make our own mistakes in our own way in order to keep learning and figure out where the gaps in our understanding exist.
## Making a model
-What we need instead are areas where programmers can set up environments where they can safely learn from their mistakes. We need areas where developers can feel OK about trying new things. But we also need an area where developers can test those changes and ensure that they don't have other rippling effects on other code.
+We need an environment where programmers can safely learn from their mistakes. We need areas where programmers can feel good about trying new things. We need to have places where developers can try out their ideas and not have those changes ripple to other unrelated systems. This is the best way that developers can learn and be brave in their learning process.
+
+These environments must model the target systems, and they must be as close as is practical to those target systems. That doesn't mean you need to make exact copies of expensive production environments but you do need to have models of production environments that test enough of the pieces your code will come in contact. Having models that mirror production systems means you'll be less likely to introduce changes that have unintended consequences. You'll give yourself some comfort in knowing that the changes you enact in these models will be the same changes that will appear on the target system.
+
+Ideally you'll need to have an environment like this on a machine that you control. This means that you're not competing with other programmers in your organization that are also being brave with their changes. But you'll also want to ensure that you keep your environment up-to-date with their changes (and any production changes) so you're development model matches what's on the target system and what will be on the target system.
+
+This also means having an environment that you can quickly rebuild and replicate as needed. Having a model that becomes its own separate reality becomes one more system to maintain. This model should be something that you can destroy and rebuild at will in order to remove any previous experiments. It's best to think of it as an ephemeral copy of your target environment that has limited use and can be tossed when no longer necessary. It should be quick to replicate this environment so there's little friction in creating new environments to play in. That can mean scripting the building process for these environments. How you decide to do this is up to you but keep in mind that you want something that's as simple as you can make it and requires as little thought as you can manage to replicate it.
+
+Again, it doesn't have to be perfect - it's only a model. But it does need to be close enough where your code will behave in a similar fashion between the model and the target environment.
+
+## Time machines
-We also need environments that model the target system. They need to be as close as is practical to those target systems. That doesn't mean you need to make exact copies of expensive production environments, but you do need to make models of production environments that test enough of the pieces your code will come in contact. That also means keeping this model updated as systems change.
+There are plenty of other folks who will tell you the benefits of revision control (and many folks who will show you the exact steps for how to set up revision control). Having a good revision control system will allow you to create areas where you can test code without having to merge these tests into production. Good revision control will allow you to create a space (or "branch" in git parlance) based off of existing code that you can use to experiment and develop on. It also allows you to commit to that space and diverge as much as you need to in order to fully explore the changes you're making. What's most important though is that good revision control will allow you to abandon that space if you need to - you're not forced to commit those changes back to a production machine. This allows you to see if something might work and abandon those changes if they don't pan out. Good revision control affords the programmers the ability to branch off from any point in time and explore what happened in the code base. In a sense they're time machines, allowing you to play "what if?" scenarios with your code. This is vital for your learning because you can feel secure in testing and trying things and have the ability to rewind those changes (or delete them entirely) without affecting the work of others.
-Again it doesn't have to be perfect - it's only a model. But it does need to be close enough where your code will behave in a similar fashion between the model and the target environment.
+Learning how your revision control system works will give you freedom in making mistakes. Many of these systems can seem complex at first but with continued practice and patience you'll understand what the revision control is doing and what its capabilities are. You'll be able to judge how many risks you can take with your code and be more confident with the risks you take.
## Learning from failure
Sometimes we fail. Sometimes the code that we wrote isn't up to the realities of the system it's implemented on. Sometimes we push code that does something that we didn't expect and does any number of things. In all of these cases it causes discomfort, whether to us, the folks we support, or the folks we work with.
-I'm not going to lie. Failure sucks. It makes us feel like we're somehow less of a person because we failed. We feel inadequate and wonder how others think of us. Do they think less of us? Have we damaged our relationship with those who use whatever we've programmed? Have I damaged my relationship with my co-workers? All of these questions come at the forefront and they all stem from a desire to do our best and make sure that we don't cause harm to others. We want others to think well of us and our skills and failure amplifies whatever feelings of inadequacy we might have. We wonder if we should eve be doing this at all, or if our talents lie elsewhere. We feel like giving up.
+I'm not going to lie: failure sucks. It makes us feel like we're less of a person because we failed. We feel inadequate and wonder how others think of us. Do they think less of us? Have we damaged our relationship with those who use whatever we've programmed? Have I damaged my relationship with my co-workers? All of these questions come at the forefront and they all stem from a desire to do our best and make sure that we don't cause harm to others. We want others to think well of us and our skills and failure amplifies whatever feelings of inadequacy we might have. We wonder if we should eve be doing this at all, or if our talents lie elsewhere. We feel like giving up.
We don't usually let failure be part of the learning process. Failing feels a lot like and end-point of the journey. In school a failing grade doesn't usually mean "I need to practice this some more"; it usually means that we're going to cause shame and discomfort to ourselves and our loved ones. I think there's a huge disservice we give ourselves if we don't acknowledge that failure is part of a process and that it's OK to fail. Not everything we do will be perfect. Mistakes will creep into the best code we write. We'll slip up and deploy to the wrong system. We'll cause discomfort to others.