“Barriers to entry” and getting things done
I will mis-use the phrase “barriers to entry” to talk about how people keep themselves from getting things done.
You have some work that needs to be done. You are not particularly motivated to do it. You create an imposing mental barrier to doing the work. However, the barrier is all mental. You tell yourself:
you don’t feel like doing it
it will take too long
it will be drudgery
you don’t know how to do it
You have created a high mental barrier that you need to get over in order to start working on the items.
The key is that it is a mental barrier of your own creation in your head. You have amplified the height and burden of the barrier in your own mind. Once you get over it, you will see that it was a small bump in the road, not a major barrier at all. Once you step past your artifical mental barrier, you get immersed in the work, your motivation goes up, you look around and see what needs to be done, you start doing it, you see some succes, your motivation goes up, you get in the “flow” and before you know it the item is done.
Context switching makes this effect much worse. In the worst case, you context switch so much that you never have time to get over the barrier on any tasks. Your just sitting there in a lonely pit surrounded by barriers you can never get over.
The solution is to foster the discipline in yourself of forcing yourself over these barriers repeatedly. Do this every day, many times a day, and then look back on your path and see a solid record of accomplishments. Accomplishments that were achieved by barreling through the mental “barriers to entry”.
Comments (0)Operational responsibilities are good
If a developer stays on a project long enough they will inevitably be pulled into operations. Not only do they write the code, but they help make it run in production. This is a good thing. It is not necessarily glamorous, but it is good.
It makes a developer better because they experience the impact of their coding-time decisions.
It makes a developer more valuable because taking a new feature all the way through to production is more valuable than simply writing the code and leaving it for someone else to make work.
It secures a developer’s position on the team because keeping the system running is a more fundamental need than writing new code.
Your job is not to “help”
Some people define their role as inflicting help on people. Don’t do this. If you are a consultant, do not define your role as helping the team. If you are a manager of a team, do not define your role as helping. If you are in business as a smart technical person do not advertise yourself as offering help. If you find yourself doing this then translate the word “help” to “annoy” and you will see more clearly.
To define your role as “helping” is condescending and passive. The ego it takes to define your role in life as helping others reflects a fundamental misunderstanding of the universe. Instead, redefine your role to define what you are individually doing, what you are accomplishing (and this cannot be helping). Then as a secondary role you can be open to providing assistance to people who request it.
Suppose you are a consultant who primarily trains teams in development processes. Do not define your job as helping teams to implement good processes. Instead define your job as providing training. If in the course of providing training someone asks for your assistance then by all means help them. By focusing on providing training rather than helping, you will focus on getting your job done rather than focusing on all the deficiencies of your client and your responsibility to fix them. You will turn your critical eye on yourself to learn how you can more effectively prepare and deliver training.
While defining your role as helping sounds quite generous and charitable it actually reveals an unhealthy, egocentric attitude.
Comments (0)Tell the team when you mess with a shared server
You are working on a distributed team. There are a handful of other people working on the team. You are sharing a server. When you do anything disruptive on the shared server you must tell the team.
This means you must tell the team when you do things like:
- change the system configuration
- start/stop a shared server process
- run a resource intensive operation
- start/stop the server
At some point, everyone on the team is trying to understand why the server is doing what it is doing. Often it seems the server has a life of its own. There are enough wrinkles of complexity and unexpected dependencies in the operating system and the applications and in the network interactions that it can be very hard to understand what the server is doing. This problem is compounded greatly when there is a person on the other side of the world, invisibly making changes. Now the system really does appear to have a life of its own! The other person has effectively become part of the black-box everyone is trying to understand.
So whenever you are messing with a shared server tell.
Even if it is just a dev server tell the team.
Even if nobody else is online, tell the team (they are going to come online and they are going to wonder what is going on with the server).
Even if 99 times out of 100 nobody cares about your messages, tell them (you can never tell when it will be the 1 time out of 100).
Even if everyone says they don’t care about the messages, tell them (the messages are only “un-necessary because you are sending them).
The goal is to create a virtual, shared work room. In a virtual, shared work room you could see if someone stood up from their desk and walked over to the main server and started punching buttons on it. Everyone would notice this. Even if they did not care at the moment, they would still notice and have a basic situational awareness of what is going on in their world.
So tell the team when you mess with a shared server.
Comments (0)School is a terrible preparation for work
School trains people to think there is a predefined point of success. School trains people to place an upper bound on success. School prescribes a set of lectures to go to, a specific number of assignments to do. Tests have a limit. The best you can do is ace the test. There is a fixed number of classes needed to get a degree. School instills the notion that there is an upper limit on success and it is reached by getting the right items checked off on a predefined list.
School is antipreneurial. It opposes entrepreneurial thinking. Coding for money on the web means you are operating your own business. Entrepreneurial thinking is what you need to be successful coding for money on the web. School is a terrible preparation for working on the web.
Comments (0)Can inversion of control go awry?
Is there any downside to using inversion of control? Absolutely
Can the testing code become a disaster? Totally
Can you create a big mess of tangled code with inversion of control? Daily
Is it harder to read code that has been “distilled” so that compile time and runtime dependencies are different? Yep
So what is the conclusion? We need to train our brains to think in new ways and build/find tools to help us write code that supports automated testing (and therefore works and can be maintained).
We need to get better at distilling out the un-testable parts. We need to learn how to test more un-testable code. We need to learn better patterns of clearly doing inversion of control. We need to train our brains to think in different ways. We need to keep groping towards a better way of building software.
Comments (0)Distill code to make it testable
I am adding a small module to a big application. If I add the module in the default way it won’t be easy to test. The default way is to simply slap the new code onto the existing app and stir it all together nicely. If I want to test the new code I must run the entire application. And that is hard to do in an automated way.
To make this example concrete, let’s say I need to add table support to a word processor. The default approach is to just start adding code to the word processor code until I have tables working. But when I am done, the “table module” is very tightly integrated with the word processor app.
Here is an alternative approach: There are two kinds of code that are mixed into the new module that must be distilled out. The first, is application specific code. Find all the parts that are specific to this use of the new module and pull them together at the top. This is the common approach of making a library. This involves a bit of abstraction, pulling out constants and other details that apply to the application. So I make a table library and then use that table library in the application.
This part is fairly well understood, if not followed. The second aspect is much less well understood. The second kind of code that must be distilled out is system access code. System access code is any code that goes outside of memory and touches real resources. For example, reading a file, talking on the network, accessing a database, reading the system clock. This is all system access code that is harder to test than normal code.
Just as I distilled the application code out to the top of the new module, I need to distill the system access code out to the bottom of the new module. So imagine different pieces of code working together: the application code is on top (the word processor), making calls down to the new module (the table module), which in turn is calling bits of system access code that are plugged in underneath it.
The final step is to use inversion of control, to allow the application code to pass the system access code into the module. From an object construction perspective this pulls the system access code up on top of the module and puts it under the control of the application. (This point is complicated unless you understand inversion of control. The module still makes calls down to the system access code, but the system access code is constructed by the application code. So there is a runtime dependency from the module to the system access code. But, the system access code implements interfaces defined in the module, so the compile time dependencies are such that the system access code depends on the module, not vice-versa).
With inversion of control in place, I can create fake system access code that is just normal code (i.e. only uses memory, does not access other system resources). This makes it easy to test. For example, suppose the table module in the word processor needs to read a config file to know how many columns to create by default. With the file access code distilled out of the module, I can write simple automated tests that give the module different strings as “config files”.
To do this really well I want to only distill out pure application code and pure system access code. I want the distilled parts to be as small as possible. Why? Because they are going to be harder to test. I am going to put the module under extensive automated testing. So the more code that is in the module, the more code that will be tested. Which means: the more code that will work.
This approach also simplifies the task of automated testing because everything that must be faked for the automated test is gathered together at the top of the library (remember the system access code is “on top” with the application code from a compile time perspective). This means I can have a nice neat bit of code that “fakes” the system access, and then everything below that is the “real” module running.
So, to make my modules testable I need to keep them free of application code and free of system access code. I use inversion of control to allow the application code to control what system access code to use.
Comments (0)10 ways to spot a good coder
Some coders are really good. How can you identify them?
You gotta know how to read a stack trace. I know this is a pathetically low bar, but I have seen countless developers just stare in wonder at a stack trace. So even this low bar will eliminate a bunch of people.
Know your tools Know your IDE. Know your editor. Know your operating system. Select the right “power” tools and make them serve you. (An interesting corollary is that if you code on Windows then you have to use Cygwin to be a good developer.)
Know your language If you have things to say in code, then you need to know how to talk. Learn every part of your language syntax. Get a broad understanding of the libraries your language offers.
You have to be able to download a 3rd party package, get the source code compiling, make some changes to the source and get the hacked library working. Maybe they even have to use a decompiler to get the source.
Know how to use a debugger.
Know how to use a profiler. At some point the code is too slow and you need to know why. A good developer can bust out a profiler and get an answer.
Read a spec. Sure every developer will read the spec before coding. Good developers read the spec when they are done coding… then they code up all the stuff they missed.
Read code. Writing code is more fun, but a good developer reads someone else’s code, understand it, and make sensible changes to it.
Work from the command line. Yeah GUIs are great, but you are doing way too much manual work if you don’t drop down to the command line and script out what you need.
Create the build script It’s easy to find a good developer on a project. Find the guy who made the build script. He is the one who actually knows how the stuff works.
So what is the common theme here? The bad developers are faced with something new and they stare in wonder at all the meaningless symbols in front of them. Whether it be a stack trace or someone else’s code, or the confusion of buttons in our tools, or the build script. The good coders are filled with the same wonder, for a moment, but they apply their brain to gain understanding. They dig in, read, understand, learn. Programming is a knowledge business if there ever was one.
Comments (0)Resolio is live
I have been working on Resolio, a web tool for making online resumes. It is now live. Check it out if you want to make a nice looking web resume without a lot of work.
Comments (0)Requirements, people, and monsters (part 4)
The final complex system is the application we build: the system. Over time the system becomes a monster. A monster that threatens the team by causing damage, demanding attention, creating more urgent work, growing out of control, refusing to cooperate, and generally causing pain for the development team. The source code grows into a monster. The running system grows into another kind of monster.
The task is to tame the beast. The monster is supposed to serve the team and the users, not the other way around. We need to get the beast in a cage, tame him, get a bit in his mouth, and steer him where we want. We must make the monster serve people.
Once again, the agile movement shows us many of the key techniques we need. Create automated unit tests around each piece of the system. Create automated end-to-end functional tests that confirm the whole thing works as expected. These tests create a cage that constrains the monster.
Build with an eye to creating visible workings. The system cannot be a black box, it has to show its users what it is doing. The system has to provide useful logging and monitoring. Now people can reason about its behavior rather than making up superstitions to explain the rampages of the beast.
With extensive tests in place the development team has a safety net that emboldens them to keep the design from deteriorating into a big ball of mud. When a coder is working on a piece of code and when they see how terrible the code is they can make it better and count on the tests to help them keep things working. The code base can be steered in the direction of good design. The monster has a bit in his mouth.
Software development projects are dominated by these three complex systems: the requirements, the team, and the application itself. Each one of these offers endless opportunities for learning. Any one of them can run out of control and cause misery. Welcome to the joyful world of software development.
Comments (0)


















