`
| |
 |
 |
| Recent Thoughts
| Tags
|
|
|
|
Archive for the ‘Programming’ Category
Tuesday, June 21st, 2011
Time and again, I find developers (including myself) over-relying on our automated tests. esp. unit tests which run fast and reliably.
In the urge to save time today, we want to automate everything (which is good), but then we become blindfolded to this desire. Only later to realize that we’ve spent a lot more time debugging issues that our automated tests did not catch (leave the embarrassment caused because of this aside.)
I’ve come to believe:
A little bit of manual, sanity testing by the developer before checking in code can save hours of debugging and embarrassment.
Again this is contextual and needs personal judgement based on the nature of the change one makes to the code.
In addition to quickly doing some manual, sanity test on your machine before checking, it can be extremely important to do some exploratory testing as well. However, not always we can test things locally. In those cases, we can test them on a staging environment or on a live server. But its important for you to discover the issue much before your users encounter it.
P.S: Recently we faced Error CS0234: The type or namespace name ‘Specialized’ does not exist in the namespace ‘System.Collections’ issue, which prompted me to write this blog post.
Posted in Agile, Continuous Deployment, Deployment, Programming, Testing | 2 Comments »
Tuesday, June 21st, 2011
Industrial Logic’s eLearning has a feature where students can upload their programming exercise and get automated, personalized feedback. We do various server-side analysis (automated critique) of the student’s code to score them and to give them feedback about how well they performed in their programming exercises. To do this we need to compile their code on our server.
Recently we upgraded our .Net Compiler from version 2.0 to version 3.5. In version 2.0 we had to provide a reference to System.dll file (located in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll) for compiling. In version 3.5, they don’t have System.dll file. It was replaced by System.core.dll (located in c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll)
After making this change, when we ran the compiler using c:\WINDOWS\Microsoft.NET\Framework\v3.5\Csc.exe we got the following error:
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
SomeCSharpClass.cs: error CS0234: The type or namespace name ‘Specialized’ does not exist in the namespace ‘System.Collections’ (are you missing an assembly reference?)
It turns out that ‘System.collections.specialized’ namespace used to exist in System.dll in .net 2.0. In 3.5 System.Core.dll (which replaced the System.dll) does not contain it. Hence the compile time error.
We’ve fixed this issue by adding both System.Core.dll (v3.5) and System.dll (v2.0) to the compiler reference path. Not sure if this is the right thing to do. But it seems to work.
Posted in Deployment, Programming, Tools | No Comments »
Friday, June 3rd, 2011
As an Eclipse user, who still works with CVS for some projects, when I check-out a repository through Eclipse, I have the choice between
- extssh method: Enter the password only once,
- ext method: Enter the password at every operation, several times.
‘extssh’ is the obvious choice. And life is good, until you need to use the command line CVS client.
The latest version of CVS 1.12.13 from ftp.gnu.org does not support extssh method.
If you run a CVS command from the command-line on a project created by Eclipse, it gives the following error message:
$cvs log
cvs log: Unknown method (`extssh’) in CVSROOT.
cvs log: in directory .:
cvs log: ignoring CVS/Root because it does not contain a valid root.
cvs log: No CVSROOT specified! Please use the `-d’ option
cvs [log aborted]: or set the CVSROOT environment variable.
Unfortunately even after having reported this issue several years ago, the official cvs program does not support this method.
Luckily Eclipse offers an improved interoperability. You can specify ‘ext’ method while checking out the repository. Then via
Eclipse > Preferences > Team > CVS > Ext Connection Method
Select ‘Use another connection method type to connect’ and specify ‘Connection Type’ as ‘extssh’
If you had already created a project using extssh, don’t worry. You can always go the CVS Perspective > Select your repository > right click > Properties > change the connection type back to ext.
It will take a while for Eclipse to update the meta files on the disk. Once its done, you should be able to execute cvs commands from both Eclipse and the command line client.
Posted in Programming, Tools | No Comments »
Sunday, May 15th, 2011
Many people will argue that there is more badly written code than good code. And its important to write comments to avoid these situations. Therefore we should encourage (force) people to write comments.
IMHO they are absolutely right that today many project suffer from poorly written code without any (good) comments. However every team I know, that suffers from this problem, has always been told (forced) to write comments. In spite of the emphasis on writing comments it has not really helped them.
I usually ask:
By asking developers to write comments are we really addressing the root of the problem?
.i.e. developers don’t invest quality time to write self-documenting code; code that clearly communicates its intent and does not require the deodorant of comments.
May be its time to try something different?
I have seen this myself many times, when we emphasize & educate the team on how to write clean code and ask them to stop wasting time writing comments, the code starts to communicate lot better. Its lot more maintainable. Also we have found that writing automated tests is a great way to document your intent as well.
This is how I would explain the concept Comments Smell to a team:
Writing comments that explain “how” or “what” the code does, what it does, is evil IMHO. Comments (esp. about what and how) is a clear failure to express the intent in code. Comment is a deodorant to hide that failure (smell).
- If developers don’t invest time to write clear code, what is the guarantee that they will write clear comments?
- Is doing a mediocre job at both (comments and code) better than doing a great job at just Code?
- Will it actually be more productive to do both or just one?
Remember the biggest problem with comments it that they fall out-of-sync with code very soon. So its not just about the extra investment to write good comments, but also the investment to maintain them.
One has to think hard to write code that expresses intent rather than write some sloppy code with poor abstractions and get away (washing their hands off) by writing comments. Developers have to take responsibility for writing code that others can easily understand.
Having said that, there are times when “the why” (why we are doing something in the code, a particular way) is not apparent by just looking at the code. So if we don’t find a suitable way to communicate “the why” through code, comment is the fall back option.
Note that comments are a fall back option in “the why” case rather than a default option.
Posted in Agile, Code Smells, Programming, Training | 3 Comments »
Monday, April 18th, 2011
Building on top of my previous blog entry: Version Control Branching (extensively) Considered Harmful
I always discourage teams from preemptively branching a release candidate and then splitting their team to harden the release while rest of the team continues working on next release features.
My reasoning:
- Increases the work-in-progress and creates a lot of planning, management, version-control, testing, etc. overheads.
- In the grand scheme of things, we are focusing on resource utilization, but the throughput of the overall system is actually reducing.
- During development, teams get very focused on churning out features. Subconsciously they know there will be a hardening/optimization phase at the end, so they tend to cut corners for short-term speed gains. This attitude had a snowball effect. Overall encourages a “not-my-problem” attitude towards quality, performance and overall usability.
- The team (developers, testers and managers) responsible for hardening the release have to work extremely hard, under high pressure causing them to burn-out (and possibly introducing more problems into the system.) They have to suffer for the mistakes others have done. Does not seem like a fair system.
- Because the team is under high pressure to deliver the release, even though they know something really needs to be redesigned/refactored, they just patch it up. Constantly doing this, really creates a big ball of complex mud that only a few people understand.
- Creates a “Knowledge/Skill divide” between the developers and testers of the team. Generally the best (most trusted and knowledgable) members are pick up to work on the release hardening and performance optimization. They learn many interesting things while doing this. This newly acquired knowledge does not effectively get communicate back to other team members (mostly developers). Others continue doing what they used to do (potentially wrong things which the hardening team has to fix later.)
- As releases pass by, there are fewer and fewer people who understand the overall system and only they are able to effectively harden the project. This is a huge project risk.
- Over a period of time, every new release needs more hardening time due to the points highlighted above. This approach does not seem like a good strategy of getting out of the problem.
If something hurts, do it all the time to reduce the pain and get better at it.
Hence we should build release hardening as much as possible into the routine everyday work. If you still need hardening at the end, then instead of splitting the teams, we should let the whole swamp on making the release.
Also usually I notice that if only a subset of the team can effectively do the hardening, then its a good indication that the team is over-staffed and that might be one of the reasons for many problems in the first place. It might be worth considering down-sizing your team to see if some of those problems can be addressed.
Posted in Agile, Continuous Deployment, Learning, Organizational, Planning, Programming, Testing | No Comments »
Sunday, April 17th, 2011
Branching is a powerful tool in managing development and releases using a version control system. A branch produces a split in the code stream.
One recurring debate over the years is what goes on the trunk (main baseline) and what goes on the branch. How do you decide what work will happen on the trunk, and what will happen on the branch?
Here is my rule:
Branch rarely and branch as late as possible. .i.e. Branch only when its absolutely necessary.
You should branch whenever you cannot pursue and record two development efforts in one branch. The purpose of branching is to isolate development effort. Using a branch is always more involved than using the trunk, so the trunk should be used in majority of the cases, while the branch should be used in rare cases.

According to Ned, historically there were two branch types which solved most development problems:
- Fixes Branch: while feature work continues on the trunk, a fixes branch is created to hold the fixes to the latest shipped version of the software. This allows you to fix problems without having to wait for the latest crop of features to be finished and stabilized.
- Feature Branch: if a particular feature is disruptive enough or speculative enough that you don’t want the entire development team to have to suffer through its early stages, you can create a branch on which to do the work.
Continuous Delivery (and deployment) goes one step further and solves hard development problems and in the process avoiding the need for branching.
What are the problems with branching?
- Effort, Time and Cognitive overhead taken to merge code can be actually significant. The later we merge the worse it gets.
- Potential amount of rework and bugs introduced during the merging process is high
- Cannot dynamically create a CI build for each branch, hence lack of feedback
- Instead of making small, safe and testable changes to the code base, it encourages developers to make big bang, unsafe changes
P.S: I this blog, I’m mostly focusing on Client-Server (centralized) version control system. Distributed VCS (DVCS) have a very different working model.
Posted in Agile, Continuous Deployment, Deployment, Lean Startup, Product Development, Programming | 1 Comment »
Sunday, March 27th, 2011
public String execute() {
String resultStatus;
User user = getUser();
if (loggedIn(user)) {
String key = getParameter(KEY);
if (!isEmpty(key)) {
String id = findSourceIdFor(key);
Record record = new Record(user, key, id);
record.save();
resultStatus = "Successful";
} else {
logger.severe("Invalid key");
resultStatus = "Invalid Key";
}
} else
resultStatus = "User Not Logged In";
return resultStatus;
}
OR
public String execute() {
User user = getUser();
if (!loggedIn(user))
return "User Not Logged In";
String key = getParameter(KEY);
if (isEmpty(key)) {
logger.severe("Invalid key");
return "Invalid Key";
}
String id = findSourceIdFor(key);
new Record(user, key, id).save();
return "Successful";
}
Personally I like the second code sample. I’m a big fan of the guard clause pattern. Even though the second code sample has multiple return statements (which some people hate), it has much lower cyclomatic complexity.
Posted in Code Smells, Design, Programming | 10 Comments »
Friday, March 25th, 2011
I find myself using the following heuristics:
More details: Long Method Smell: When is a method too big?
Posted in Agile, Code Smells, Design, legacy code, Programming | No Comments »
Wednesday, March 9th, 2011
When confronted with Legacy code, we usually run into the Test-Refactor dilemma. To refactor code we need tests, to write tests, we need to refactor the code.
Some people might advise you to invest time upfront to create a whole set of tests. Instead I recommend that every time you touch a piece of legacy code (either to fix a bug or to enhance the functionality), you perform a couple of safe refactoring to enable you to create a few scaffolding tests, then clean up the code (may be even test drive the new code) and then get rid of the scaffolding tests.
Even though this approach might appear to be slower, why does this approach work better?
- You start seeing some immediate returns.
- On any given system, there are parts of the system which are more fragile and needs more attention than others. There are parts of code which we actively touch and others we rarely touch. When we have a limit time, it does not make sense in investing effort to create tests for areas that are fairly stable or rarely changed. Big upfront test creation might not take this aspect into account. So you might not get the biggest bang for your buck.
- The first few tests we usually write are fragile tests. But we won’t get this feedback nor the opportunity to improve the quality of our tests until its too late.
- When we get into a test creation mode, everyone is focusing on creating more and more tests. Finally when we start using the tests we’ve created, a small change in production code might breaks a whole bunch of tests. First few times developers wonder what happened, but if this generates a lot of false-negative (which usually they do), then developers start ignoring or deleting those tests. So the investment does not really pay for itself.
- Also when we have a whole lot of tests prematurely written, they start getting in the way of refactoring and genuinely improving the design of the code. (Defeats the whole point of creating test upfront so we can refactor.)
- People get too attached to the tests they had written (it was a big investment). They somehow want to make the test work. People fail to realize that those fragile tests are slowing them down and getting in their way.
- Unless the team gets into the habit of gradually building better test coverage, they will always play the catch up game with requirements constantly changing. (Remember we are chasing a moving target.)
- Its usually hard to take a fixed (usually long) duration of time off from CRs and bug fixes. People will be forced to multi-task.
I encourage you to share your own experience.
Posted in Agile, legacy code, Programming, Testing | No Comments »
Wednesday, February 16th, 2011
Technical Debt is any technical issues slowing down the project due to hasty (short-sighted) decisions made at an earlier point.
All of us make bad decisions, but not fixing them and just differing them really leads to bigger problems as these issues have a snowball effect.
Technical debt can be introduced at various levels:
- Code smells is the most obvious one,
- But things like lack of (or poor) automation,
- poor choice of tools,
- fragility in the development environment
- and so on
can also contribute to technical debt.
Posted in Agile, Design, legacy code, Programming, Testing | No Comments »
|