Has your Internet connection failed in the last year? Did it leave you without a way to publish your code for several hours?
Proactivity is the ability to choose our own response to the external stimuli; it's the contrary of reactivity. While working, it's possible to experience hardware failures (the Internet connection example, or a broken hard disk), software failures (showstopper bugs into our preferred application), or "people" failures (such as a teammate not able to deliver).
Instead of complaining, we can take a step to fix the problem, or at least to learn if it is under our influence or not. While redundancy is a good strategy for physical objects issues, it is not for software or for working with other people. We can commit to local branches instead of pushing our code with distributed version control systems; we can use paper instead of yUML when it cannot represent what we want, or it is too slow; we can work with Test Doubles until a colleague has completed the implementation we need. Don't let.
Begin with the end in mind
The "end" word is used here in the sense of a goal, not as a temporal event only. With Covey's words, all things are created twice: once in your mind and then for real.
TDD and BDD are probably the best expression of beginning with a goal instead of cowboy coding. They also gives you the power to iterate over the names of your classes and methods, or the API of an object; you are forced to ask yourself how many methods to create and in which order to call them, or even whether to move towards pure functions or objects encapsulating state.
You can extend this process to personal goals to accomplish during the day, especially while freelancing. TDD and BDD has given back us the power of specifications.
Put first things first
This principle deals with the relative weight of firefighting and of the other important things in your available time and energy.
Refactoring is often applied as cowboy coding, instead of little transitions between working states of the code. But it is possible to refactor in different directions, horizontally (with the application of a new design across many subclasses or implementations) or vertically (moving code between inheritance and composition relationships).
Although it may be beneficial to our ego to just explore the design into a refactoring in a vertical way, sometimes it is beneficial to apply it horizontally to discover unforeseen problems with the new solution. The first goal is to maintain the code in a working state, and the code in a coherent picture; getting away hacking a single class is no use if we let the rest of the system to rot and we don't integrate our changes.
Think win win
Interactions with other people have different possible, paradigms, depending on who is earning value from them; a win-win situation is the only one sustainable in the long run.
The Agile movement prescribes a search for win-win scenarios between software developers and customers. It's about building the best software for the user, as fast as possible, instead of just what the written contract specifies. Arguing over the clauses and the changes is a win-lose situation, where one of the parties may win now but ruin the relationship in the future.
Seek first to understand, then to be understood
Why not writing exploratory tests and integration tests instead of blaming poor documentation? Or googling and opening a reference manual book instead of trying random combinations of method calls? I recognize I'm guilty of the latter behavior from time to time.
Especially when working with standards: the standard is likely to be more correct than us in many cases. For example it happens often to me while working over TCP. The last time I tried to get a complex object graph to work, but there was a TCP connection in the middle. I couldn't get the object on one side of the connection to know that the other had closed it.
The initial approach was to try calling close(), shutdownOutput() and similar calls on the Socket instance. It turned out that only by attempting to write to the socket you can detect the connection has closed. It was fine for me, but my write attempt just blocked indefinitely.
By trying out the Server class API and a OutputStream/DataOutputStream/PrintWriter in a JUnit test of 20 lines, I was able to detect a combination that was working: Socket.close() and PrintWriter.checkError().
This simple exploratory test written in the morning brought me more forward than two hours of throwing calls at the Java network API the previous day. I'm not advocating reading only documentation instead of jumping to write code, but writing the right integration testing to satisfy a learning goal, before jumping to real code.
Synergy: a whole greater than the sum of its parts
In business, sinergy is the working together of different parts who couldn't reach the same result alone. I think this principle works very well also in engineering, and in particular in software engineering, where the parts are classes, objects, functions, or even applications and machines.
Chopping up responsibilities into the right roles often makes the difference between a design that is easy to extend and to understand, and one where every new functionality has to be forced in.
Trying out multiple possibilities in our architecture is not a waste of time, but a search for a solution which abstracts away all its internal concerns and accomplishes more than the sum of what the single objects do. Objects conforming to wise interfaces can be combined in unexpected ways - for example, in a P2P application I started using client classes on a server process to bridge the different servers together, with no modification of the original code. A simple solution is not the same as a stupid one: if it seems stupid, it's because hours of thinking and exploration have brought you to a solid model.
Sharpen the saw
Sharpening the saw means that sometimes when cutting wood it pays very well to stop often, and sharpen the saw instead of continuing to work until the blade is ruined and hopelessly rough.
This habit is really where XP and Agile practitioners are shining now. There are more and more events and conferences where developers can meet to train: although there is a strong networking side to these events, the basis is always an opportunity to exercise together on some difficult problems.
When I exercise alone, I read technical articles weekly and perform code katas, which are becoming a standard format for self-contained training tasks. But I started attending interesting events in Milan, such as user groups meetings and code retreats. Really, the habit of sharpening the saw is popular, and if you're reading here it means you are aready on the right track...