"Read The Code" is not a valid answer
Scott Bellware has a post titled Just Read the Code (or, Let them Eat Cake)
Here is a simple example, from my own code With.Cache, it is a small class, but in order to understand what it is doing you have to grok Disposable Actions, Semi Statics and the Local Data concept. And then you need to find out where the properties on this class are used, to understand what it is doing.
There is a reason that my primary tool for exploring through a code base that I am not familiar with is ReSharper for C# and grep for anything else. And that is in a code base that I consider pretty good. Code doesn't stand in isolation, in order to understand what it is doing, you need to understand how it is used, and what is it is supposed to be doing.
I had code bases thrown at me when I wasn't ducking fast enough, and trying to untangle that mess leaves scars. I learned SQL to as a self defence measure.
Yes, that is true, but it is important to understand the difference in the target audiance. To the Castle team, I can talk using a short handed terminology, because I can assume prior knowledge. This helps make communication efficent, and the code base more understandable if you understand the idioms used. If you don't, you are going to have hard time until you do. In other words, you have to already have an understanding of the code in order to understand the code.
Now, there is a not so fine line between the implementation and the interface of the code. If I am intending to make something that I will use later, that I will be as smart as possible in the implementation, so I can be as stupid as possible when using the interface. This is the way it should be, in my opinion, but it does make the implementation harder to grok, because it is doing more.
To quote Joel Spolsky:
If you are going into non trivial code base, you should expect to have to invest some time in understanding it. A good code base would help you do it, but again, it requires some knowledge before you can do that.
From Spolsky again:
Documentation helps in this regard. Not for the specifics of the code, but to document the what and the how. I am not a fan of documenting the code, but documenting the way you are supposed to use it is important. Once you understand how it is supposed to be used, you can look at the implementation and understand how it enables this usage.
Comments
I refute Joel Spolky's assertions categorically. Programs aren't inherently code that needs to be deciphered... it BECOMES code that needs to be deciphered. And there are disciplines for making code reading much faster than it is today.
There was likely a time at the dawn of written natural languages that it was as difficult to understand the written word as it was to understand code today. I expect that reading code should be somewhat slower, but I disagree completely that there's anything inherent in the code that causes it to be less literate.
Joel's examples of the little hairs aren't the result of bug fixes, they're the result of bug fixes by people who have refuted any responsibility to doing bug fixes while sustaining the solubility of the code... and inevitably its design. We can do better if we try.
Just having the discipline to write unit tests so that they have a more documentary style is a huge leap forward. Using successive levels of Composed Method to provide multiple levels of knowledge resolution solves a big chunk of teh problem. High cohesion and low complexity do wonders to code that already benefits from the first two disciplines. Sticking dilligently to domain-specific naming for ALL symbols in the codebase kicks it up yet another notch.
What I tried to call out in my post in talking about the 'best of the best" of programmers, is that you guys have x-ray vision. You can see through the code density. However, that same ability blinds you to the natural capacity for penetrating density that the rest of the population has.
The only way to leave no programmer behind is to to turn off the x-rays when you're writing code, and learn to write code with less density so that it is more readily soluble... if it's important to you that the community at large can learn from your work. If not, then no worries.
I don't really agree,having explicit names helps quite a bit, certainly. But this is not the hardest part of understanding the code.
Or, let me make it clearer, it is not the hardest part when understanding well-written code.
Understanding a piece of code in isolation is easy, understanding what it is doing in the grand scheme of things is much harder. Because you have to understand all the systems that it uses.
With.Transaction (delegate{
AppointmentSpec appointmentSpec = Repository<AppointmentSpec>.Load(15);
IAppointmentService appointmentService = IoC.Resolve<IAppointmentService>();
appointmentService.FromAppointmentSpecToConcreteAppointments (appointmentSpec, new DateTime(2007,1,1), new DateTime(2007,6,30) );
});
This piece of code is responsible for taking an appointment spec (every second wendsday, 8:00 AM) and turn it into a concrete appointment (2/2/2007, 8:00 AM).
appointmentService has not a shred of data access in it (nor should it, it is the same method that I use to display the appointment specs calander) - pure business logic. Never the less, this piece of code results in saving the new appointments to the database.
Here you need to understand Unit of Work and cascades, to get how you get this functionality for free.
I believe in making it clear what the code is doing, but it should be clear if you understand the basic concepts of the applications.
In the above example, Unit of Work and cascades are a core part of the way I work,if you don't understand them, you would have to "discover" it by debugging the code until you would figure it out.
My reasoning behind this are explained here:
http://www.ayende.com/Blog/archive/2007/03/06/Average-Code-and-Cost-Of-Change.aspx
This is where unit tests are really really really handy. Nothing helps you focus on what is important faster than what the developers saw worthy of testing.
Also, tests named like "public void MakeSureMethodXDoesNotThrowExceptionDueToThisBug();" tell you which methods have been problematic.
Comment preview