If you are working on a project that uses 3rd party products you should be facing this dilemma regarding upgrades, regularly. It could be a core system upgrade such as .Net framework version or a SQL Server database version or a significant 3rd party component upgrade. Usually these upgrades proposals come from tech teams.
Assuming that cost of the software that is being upgraded itself is not prohibitive, most of the arguments are centered on the work that needs to be done by the team to stabilize the product with the upgraded version
Arguments
1. Arguments in favor of the upgrade
a. If we don’t upgrade now, when would we upgrade? After we acquired another 1000 customers?
b. It would be an incentive for the developers. It will help with both hiring and retaining good developers, since they tend to want to work on the latest and greatest.
c. We could get rid of some of the nagging bugs in the product, as the new upgrade solves them
d. New upgrade contains significant and important changes and we should take advantage of them
e. If we are up to date with the latest version, our product won’t become obsolete
2. Arguments against the upgrade
a. There aren’t many useful features in the new version
b. Everything works now so why should we unnecessarily disturb the code base?
c. What is in it for customers, since they didn’t ask for the upgrade?
d. If we upgrade component A, component B will not work
e. We will need to test the whole product, which would be very expensive. We might miss some parts which can put the product at risk
f. The whole process could be exhaustive and we may burn out the team
Most of the arguments against the upgrade are centered on changing the code base, and the fact that changing code could be a risky affair. However, I usually favor staying as current as possible, because the speed with which new upgrades are being released to the market is extremely fast, and if we fail to stay current, the product will end up becoming stale and will almost certainly require a big rewrite in the future.
Process – What Not To Do
Upgrade by committee
It is very tempting to gather all parties involved and conduct formal meetings, get all of their buy ins, create and manage a project plan. This means lot of meetings, follow ups, emails and creates inevitable creation of heroes who will end up taking on the bulk of the work to meet some arbitrary deadline. It may sound logical, and works most of the time. But this is a very expensive process, and usually involves lots of meetings. These meetings are the breeding grounds for “Fear, Uncertainty, Doubt (“FUD”). Any one person in these meetings can derail the attempt or significantly delay the process. After one such upgrade experience you will lose the appetite for any future attempts.
Process – What To Do
If you are really looking ways for successfully convince the organization or your boss for an upgrade here is a summary of what worked for me.
1. Build confidence
Your organization must have faith in your team. They should believe that your team can deliver. They should know that you can fix issues fast and that you care about the success of both the business and the product. This won’t come in a single day. You need to build that confidence every day. One trick that works is to constantly solve simple problems. These kinds of problems won’t take much time. They don’t need big project plans. They come from all parts of the organization. Solving them proves that you are for continuous improvement.
Try to tackle troubled areas of the products. These are the parts of the software that attract frequent bugs, frequent code churns. Try to take initiative and make that area trouble free. Once you successfully solve such problems, you are guaranteed to gain the support in any of your future upgrade proposals.
2. Build safety net
If you don’t have them already, you should start writing tests for important areas of your application. These tests when written properly help you in two ways. They help you identify the problem quickly and also help serve as a repository of business knowledge. You must run these tests with every code check-in.
3. QA is your friend
The most important help you can get from you QA team is in the form of exploratory tests and also from testing tedious, non-automated parts of the application. A tester with an intention to solve the problem is the best resource than a tester with an intention to just report a problem. Have them involved in every non trivial decision your team makes.
4. Research
If the upgrade is going to have big impact on your product, wait for about 6 months after the release date of the upgrade. Go through the release notes, breaking changes, write small prototypes to test the areas of the concern.
Most importantly go through the product support forums to understand the quality of the version you are upgrading. Even if you decide not to upgrade, this research helps you decide the future direction of your product.
5. Build excitement within the team
Try to lay out the broad plan for the upgrade. Take your team’s consensus. Understand possible real problems. Tell them why the upgrade is important. A self-organizing, motivated team can make the whole upgrade process a trivial affair. As a team, you should try to think through and anticipate every major problem, and come up with possible options. Consider other major projects your team is dealing with to make sure that they are not being unnecessarily burdened. Come up with a possible time line.
6. Sell the proposal
Get the major stake holders in a room and sell your proposal. If you did your homework properly this should go well.
7. Appoint a facilitator
Find someone in the team (a PM, BA, team lead etc.) who can act as glue with all the team members. Their job is to continuously update all stake holders (management, team, end users etc.) about the team’s decisions, choices and find answers.
8. Short but to the point standup meetings
Meet twice a day to talk about the most important issues that you team is facing that day. This helps the team to share the work, gather questions, seek answers and inform stake holders about problems.
I too often here developers complaining that their organization is not good at keeping at the top of the latest technology trends. I believe that this is mostly due to the lack of effort from the software teams themselves.
Saturday, July 16, 2011
Saturday, March 5, 2011
Routes with non optional parameters
You can define restful routes in asp.net mvc applications. I recently ran into an interesting problem.
I defined the following route.
This route works fine. However somewhere else in the code, when I try to output the route url in a page, by doing the following
To my surprise I saw an empty string in the page output. I wrote a test to see the problem.
Yes that test fails. It turns out that in case of non optional parameters, I must pass their values for MVC framework to identify the route. So the following test passes.
And in a view, if you ever want to dynamically construct the above url using javascript, you could do the following
Here we are using jquery to bind a click event to a button, that grabs the user entered value and gets the member detail url.
Here I am passing a dummy value {0} to get the correct url and then replacing that value with the memberId entered by user.
Note that Url.RouteUrl method always encodes the url string.
I defined the following route.
routes.MapRoute("MemberDetail", "Member/{memberId}", new { controller = "Employee", action = "Details" });Here I am defining a route named "MemberDetails", that allows user to use urls similar to Member/1234 to get a member's detail.
This route works fine. However somewhere else in the code, when I try to output the route url in a page, by doing the following
UrlHelper.RouteUrl("MemberDetail")
To my surprise I saw an empty string in the page output. I wrote a test to see the problem.
[Test]
public void MemberDetailRoute()
{
Assert.IsNotNull(_mockedUrlHelper.RouteUrl("MemberDetail"))
}
Yes that test fails. It turns out that in case of non optional parameters, I must pass their values for MVC framework to identify the route. So the following test passes.
[Test]
public void MemberDetailRoute()
{
Assert.AreEqual("/Member/123", _mockedUrlHelper.RouteUrl("MemberDetail", new {memberId = 123}))
}
And in a view, if you ever want to dynamically construct the above url using javascript, you could do the following
Here we are using jquery to bind a click event to a button, that grabs the user entered value and gets the member detail url.
<script type="text/javascript">
var memberUrl = '<%: HttpUtility.UrlDecode(Url.RouteUrl("MemberDetail", new {memberId = {0}) )%>';
$('#Go').click(function() {
var memberId = $('#memberId').val(); // get the member id from a textbox
window.location.href = HttpUtility.UrlEncode(url.replace("{0}", memberId));
});
</script>
Here I am passing a dummy value {0} to get the correct url and then replacing that value with the memberId entered by user.
Note that Url.RouteUrl method always encodes the url string.
Thursday, March 3, 2011
Sunday, February 27, 2011
Connecting to a windows 7 printer from Mac
It seems that I am ending up searching for these instructions many times, just so I don't forget these steps
On the Windows 7 PC
1. In Windows 7 Control Panel
2. Select "Programs and Features" pane
3. Click "Turn Windows Features on or off"
4. Click on the "LPD Print Service". Under "Print and Document Services"
5. Ensure printer(s) are shared
On the Mac
1. Open "System Preferences" - "Print & Fax"
2. Click "+" to add a printer
3. Right click -> tool bar to customize and add "Advanced" button
4. Select "Advanced"
5. In the "Type:" field select "LPD/LPR Host or Printer"
6. In the "URL:" field enter lpd://ipaddressofwindows7machine/PrinterShareName
Using lpd://ServeName/PrinterShareName does not work, the IP address must replace ServerName
The IP address is the address of your PC, the one assigned by your router
7. Click the "Add" button
If nothing works, just reset the print system on your mac. This would delete the existing printers allowing you to start fresh.
On the Windows 7 PC
1. In Windows 7 Control Panel
2. Select "Programs and Features" pane
3. Click "Turn Windows Features on or off"
4. Click on the "LPD Print Service". Under "Print and Document Services"
5. Ensure printer(s) are shared
On the Mac
1. Open "System Preferences" - "Print & Fax"
2. Click "+" to add a printer
3. Right click -> tool bar to customize and add "Advanced" button
4. Select "Advanced"
5. In the "Type:" field select "LPD/LPR Host or Printer"
6. In the "URL:" field enter lpd://ipaddressofwindows7machine/PrinterShareName
Using lpd://ServeName/PrinterShareName does not work, the IP address must replace ServerName
The IP address is the address of your PC, the one assigned by your router
7. Click the "Add" button
If nothing works, just reset the print system on your mac. This would delete the existing printers allowing you to start fresh.
Wednesday, February 9, 2011
Asp.net WebSite Administration Tool
Asp.net allows to quickly setup a security for the site using WebSite Administration tool, which can be instantiated from visual studio. If that tool throws an error, there is no place find what went wrong.
I ran into one such case with the following cryptic error.
"An error was encountered. Please return to the previous page and try again."
I found a work around for this problem. I needed to hit F5 (run the site in the debug mode) and then click the "WebSite Administration tool" icon from solution explorer to get rid of the above error.
I ran into one such case with the following cryptic error.
"An error was encountered. Please return to the previous page and try again."
I found a work around for this problem. I needed to hit F5 (run the site in the debug mode) and then click the "WebSite Administration tool" icon from solution explorer to get rid of the above error.
Monday, November 29, 2010
Thursday, October 28, 2010
Rendering asp.net controls with dynamic ids
You have a legacy asp application with lots of html and server side code.
And you you have a loop in which you are trying to add server controls and you want their ids to be dynamically generated.
You want the mark up to look like the following. Here for this blog post purposes I am using textbox.
You might intuitively try the following
But this results in to the following error
The ID property of a control can only be set using the ID attribute in the tag and a simple value. Example: <asp:Button runat="server" id="Button1" />
Workaround for this issue is as follows.
First the Markup.
<% for (var i = 0; i < 5; i++) {
AddTextBox(i);
} %>
Here we are adding 5 text boxes dynamically to the page in place.
This kind of code gets executed at the rendering stage of the page life cycle. Trick is get the html out of the text box and just render in place.
And code for AddTextBox method
Here we are creating a new TextBox control and setting its id property dynamically. And then using RenderControl method, we are populating the StringBuilder instance. And then outputting the value to response stream.
This can easily be turned in to an extension method. Then the usage looks like the following
<%= TextBox.ToHtml(id, val) %>
And you you have a loop in which you are trying to add server controls and you want their ids to be dynamically generated.
You want the mark up to look like the following. Here for this blog post purposes I am using textbox.
<input name="0" type="text" id="0" />
<br />
<input name="1" type="text" id="1" />
<br />
<input name="2" type="text" id="2" />
<br />
<input name="3" type="text" id="3" />
<br />
<input name="4" type="text" id="4" />
You might intuitively try the following
<% for (var i = 0 ; i <5; i++){ %>
<asp:TextBox runat="server" id="<%# i %>" />
<% } %>
But this results in to the following error
The ID property of a control can only be set using the ID attribute in the tag and a simple value. Example: <asp:Button runat="server" id="Button1" />
Workaround for this issue is as follows.
First the Markup.
<% for (var i = 0; i < 5; i++) {
AddTextBox(i);
} %>
Here we are adding 5 text boxes dynamically to the page in place.
This kind of code gets executed at the rendering stage of the page life cycle. Trick is get the html out of the text box and just render in place.
And code for AddTextBox method
void AddTextBox(int i){ var ctrl = new TextBox() { ID = i.ToString() };var sb = new StringBuilder();
using (var sw = new StringWriter(sb)){ using (var textWriter = new HtmlTextWriter(sw)){ctrl.RenderControl(textWriter);
}
}
Response.Write(sb.ToString());
}
Here we are creating a new TextBox control and setting its id property dynamically. And then using RenderControl method, we are populating the StringBuilder instance. And then outputting the value to response stream.
This can easily be turned in to an extension method. Then the usage looks like the following
<%= TextBox.ToHtml(id, val) %>
Subscribe to:
Posts (Atom)