I haven't been keeping up on my reading list for the past couple of weeks, and have only just read Joel's announcement that he'll be retiring from blogging. It's a sad day, and I feel a little bit like I'm heading to a funeral.
Joel's writing has been a great inspiration to me, and have stimulated many fiery connerdsations at the pub. I still browse back to some of the articles in his archive from time to time. They have the type of content that makes them remain relevant, in the same way as Peopleware remains relevant, many years after being written.
Cheers Joel, and good luck for the future!
A blog touching on topics such as technical code solutions (or problems) and software development processes.
Thursday, March 25, 2010
Tuesday, February 16, 2010
Tips and tricks for writing Windows services in C#
This is not meant to be an exhaustive tutorial on writing Windows services. This is just a couple of items that I tend to forget in the time between writing services. It’d be great if it helps anyone else in the process.
- If you haven’t done this before, or forgot everything you’ve learned, here’s a tutorial: http://www.grinn.net/blog/dev/2008/01/windows-services-in-c-part-1.html or refer to http://msdn.microsoft.com/en-us/library/zt39148a(VS.80).aspx
- Put your Business Logic/BOL/code that does something in a separate assembly, or at the very least in a separate method marked public, so that you can add a gui/console application/unit test to your solution to execute this code. It saves a lot of time in debugging code.
- The default timer in the toolbox, System.Windows.Forms.Timer, does not work in a service. You need to use System.Timers.Timer, which can be added to the toolbox. Refer here for an explanation of why it doesn’t work (Winforms timers need a messagepump on a UI thread): http://msdn.microsoft.com/en-us/library/tb9yt5e6.aspx
- Remember to stop your timer while processing, and restart it afterwards.To add an installer, right click on the component view of your service, and click “Add Installer”. Don’t bother with manually adding an installer to your project.
- Add a setup project to your solution to install the service. Add the service’s primary output action to the install, rollback and uninstall actions. If you don’t add it to rollback, a failure after the base.Install(stateSaver) in the installer class of the service, will leave you with a service that is installed, but can’t be replaced or uninstalled by your MSI. When that happens you need to use the InstallUtil command from the command line.
- To use the installutil from the command line, type "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil"
where is the name of the assembly of your service to install the service. Add the /u flag to uninstall the service. - Use Debug.Assert(false, "Attach here to debug") to have your service pop up a message to which you can attach the debugger to step through your code. Not absolutely neccesary, but it makes things easier. For that matter, this can also be used when debugging installers, or anything else requiring to be paused at a certain place for attachment, before a breakpoint can be hit.
- Remember to log exceptions, they will not be logged automatically (maybe if you use the logging enterprise application block?). The eventlog is a good place to do this, but remember to register your source first. This is probably best done in the installer, unless you make it configurable in the service. Creating a source requires admin privileges. Here’s a how-to: http://msdn.microsoft.com/en-us/library/k00ce235.aspx
- Include something to stop your service after n number of concurrent failures, or to stop logging the exceptions. You don't want to fill up the eventlog with nonsense.
- Application settings in the config file is used as usual with Properties.Settings.Default.PropertyName
- The default service name can be set on the properties of the service in the component view. There are a few other useful properties here, like CanPauseAndContinue. Check it out.
- The account for which to run this service is set in the properties of the ProcessInstaller component in the ProjectInstaller file’s component view.
Labels:
c#,
debugging,
windows services
Sunday, November 8, 2009
A view of the modern Business Analyst
Our organisation has a very diverse group of people responsible for the development and maintenance of our in-house IT systems. There are over 50 developers, working on hundreds of products, over 3 cities. Stakeholders include product owners, managers and users from relatively diverse business units. On the technical side we have BA’s, developers, architects, testers, delivery managers and more. Given all this diversity, one thing has stood out for me: having a good BA can make or break your effort.
This then leads us to the question: What is a good BA? It’s a very difficult thing to quantify, because quite often, we don’t really understand what we expect from our BA.
Our organisation used to expect them to thoroughly and meticulously detail the requirements for any new development. For months they would sit down with customers, and draw up pages and pages of lists of things the software should and shouldn’t do. Really keen BA’s also included diagrams depicting data and process flows. They would do all kinds of modelling to exactly indicate every eventuality. The reams of documents would then be signed off, and sent to the development teams. The BA’s would then move on to analyse another part of the business by creating a new set of requirements for another piece of software.
As far as the software products go, it didn’t work very well. The developers were invariable left with such vast and daunting tasks, that they just seem to ignore all the specs, and wrote a piece of software that they thought would work for the users. Sometimes they sought some input from the users. On rare occasions they even got it, and those were the more likely projects to succeed in providing some semblance of success. One of my colleagues remarked that in the 3 years here, he has never worked on a project that went live.
Our partial solution to the problem is agile development. This seems to be working very well for many software development groups (think Microsoft, Google and others). Without going into a discussion of agile (there’s plenty of them around), following it left an interesting dilemma. What to do with our BA’s? You see, traditionally, we expected them to fit in between the users and developers. Other, more advanced organisations, expected them to stand between anyone of a technical inclination and the users. In university, we were taught that the expectation of the business analyst was to represent the combined knowledge of the business unit in documentation so it may be encapsulate in software systems.
With the agile approach, we chucked a lot of that out the window. We invited the users to the party. We started interacting directly with the first tier owners and manufacturers of business knowledge. We changed our waterfall model which had everyone only partaking in a stage of the development. Under the new agile approach, everyone is a part of the entire lifespan of the project. The success and failure is a shared burden of the entire team, all the time. If the product get to UAT, and isn’t what the users wanted, everyone is to blame.
The good BA’s developed a new position in the process. They moved from being the guardians of the business knowledge to gentle facilitators. Instead of being a link in a game of Chinese Whispers, they set up telephone conferences. They stopped planning systems that would hide the processing difficulties, and started helping users to better understand their processes. They became less involved in the technology, and more involved with the problem. Together, we are changing the old pattern of creating expensive systems that perform inefficient tasks. We are making change where it’s cheapest, and most effective.
So where do we stand with our expectations from Business Analysts? What is the distilled essence of their function? In my opinion, the modern BA has one imperative: Empower the business to collaborate effectively in the creation of fit for purpose software.
When a BA strives to attain this goal, it makes life easier for me, as a developer. When I ask our user representatives whether they would mind if we cut the print function down to only print the component you’re looking at, they can actually debate the merits of either approach! In the old days, there would be no option, leaving you to implement the function as it was specified. You would have to create the page that allowed the user to print all 50 pages of tables and graphs, and would never be used because it took too long to load. Now, the specification is updated (by changing the acceptance criteria on the user story in the product backlog) and we can devote our effort to things that the users really care about, like improving navigation between the different tables and graphs. With empowered users, we can focus our resources to where it matters most for them. With BA’s focusing on the problem rather than the solution, many more possible solutions can be generated. Solutions can now involve changing the way users work, rather than the system they use. Our products are now going live, and the users are satisfied.
This then leads us to the question: What is a good BA? It’s a very difficult thing to quantify, because quite often, we don’t really understand what we expect from our BA.
Our organisation used to expect them to thoroughly and meticulously detail the requirements for any new development. For months they would sit down with customers, and draw up pages and pages of lists of things the software should and shouldn’t do. Really keen BA’s also included diagrams depicting data and process flows. They would do all kinds of modelling to exactly indicate every eventuality. The reams of documents would then be signed off, and sent to the development teams. The BA’s would then move on to analyse another part of the business by creating a new set of requirements for another piece of software.
As far as the software products go, it didn’t work very well. The developers were invariable left with such vast and daunting tasks, that they just seem to ignore all the specs, and wrote a piece of software that they thought would work for the users. Sometimes they sought some input from the users. On rare occasions they even got it, and those were the more likely projects to succeed in providing some semblance of success. One of my colleagues remarked that in the 3 years here, he has never worked on a project that went live.
Our partial solution to the problem is agile development. This seems to be working very well for many software development groups (think Microsoft, Google and others). Without going into a discussion of agile (there’s plenty of them around), following it left an interesting dilemma. What to do with our BA’s? You see, traditionally, we expected them to fit in between the users and developers. Other, more advanced organisations, expected them to stand between anyone of a technical inclination and the users. In university, we were taught that the expectation of the business analyst was to represent the combined knowledge of the business unit in documentation so it may be encapsulate in software systems.
With the agile approach, we chucked a lot of that out the window. We invited the users to the party. We started interacting directly with the first tier owners and manufacturers of business knowledge. We changed our waterfall model which had everyone only partaking in a stage of the development. Under the new agile approach, everyone is a part of the entire lifespan of the project. The success and failure is a shared burden of the entire team, all the time. If the product get to UAT, and isn’t what the users wanted, everyone is to blame.
The good BA’s developed a new position in the process. They moved from being the guardians of the business knowledge to gentle facilitators. Instead of being a link in a game of Chinese Whispers, they set up telephone conferences. They stopped planning systems that would hide the processing difficulties, and started helping users to better understand their processes. They became less involved in the technology, and more involved with the problem. Together, we are changing the old pattern of creating expensive systems that perform inefficient tasks. We are making change where it’s cheapest, and most effective.
So where do we stand with our expectations from Business Analysts? What is the distilled essence of their function? In my opinion, the modern BA has one imperative: Empower the business to collaborate effectively in the creation of fit for purpose software.
When a BA strives to attain this goal, it makes life easier for me, as a developer. When I ask our user representatives whether they would mind if we cut the print function down to only print the component you’re looking at, they can actually debate the merits of either approach! In the old days, there would be no option, leaving you to implement the function as it was specified. You would have to create the page that allowed the user to print all 50 pages of tables and graphs, and would never be used because it took too long to load. Now, the specification is updated (by changing the acceptance criteria on the user story in the product backlog) and we can devote our effort to things that the users really care about, like improving navigation between the different tables and graphs. With empowered users, we can focus our resources to where it matters most for them. With BA’s focusing on the problem rather than the solution, many more possible solutions can be generated. Solutions can now involve changing the way users work, rather than the system they use. Our products are now going live, and the users are satisfied.
Thursday, November 5, 2009
How to enable tracing on WCF services to troubleshoot things like serialization errors
This is an excerpt from an article on MSDN on tracing. Details can be found there.
It will help you debug that annoying "The connection has been forcibly closed" error, that has no usefull information attached to it at all.
1. Add the following code in your web.config or app.config for the WCF service:
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\log\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
This code should be added after the
<configSections>
element. Not doing so will cause an error.
Alternatively, use the configuration editor at Start -> All Programs -> Microsoft Windows SDK v6.0A -> Tools -> Service Configuration Editor to enable the diagnostics.
2. Make sure the "c:\log\" path is created and accessible to the appropriate accounts (I've just given the "everyone" account write access to it, but the .net worker process account would probably be enough)
3. Open the Traces.svclog file with the service traceviewer, which can be found here:
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe"
or go to Start -> All Programs -> Microsoft Windows SDK v6.0A -> Tools -> Service Trace Viewer
And that's it. The service viewer will show you any errors that was logged, and provides a very handy way to drill into the details.
It will help you debug that annoying "The connection has been forcibly closed" error, that has no usefull information attached to it at all.
1. Add the following code in your web.config or app.config for the WCF service:
<configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\log\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
This code should be added after the
<configSections>
element. Not doing so will cause an error.
Alternatively, use the configuration editor at Start -> All Programs -> Microsoft Windows SDK v6.0A -> Tools -> Service Configuration Editor to enable the diagnostics.
2. Make sure the "c:\log\" path is created and accessible to the appropriate accounts (I've just given the "everyone" account write access to it, but the .net worker process account would probably be enough)
3. Open the Traces.svclog file with the service traceviewer, which can be found here:
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe"
or go to Start -> All Programs -> Microsoft Windows SDK v6.0A -> Tools -> Service Trace Viewer
And that's it. The service viewer will show you any errors that was logged, and provides a very handy way to drill into the details.
Wednesday, September 9, 2009
"Microsoft JScript compilation error: Expected ';'" when parsing JSON in Javascript
This is a nasty one that I struggled with a bit.
I had some code parsing a JSON string returned from a callback.
var layer = eval(jsonLayer);
This worked fine, until I changed the object that was serialized to and from JSON from a collection inheriting from System.Collections.Generic.List to a base object, with the collection as a property.
I suddenly started getting an error stating "Microsoft JScript compilation error: Expected ';'"
Changing the code to:
var layer = eval("(" + jsonLayer + ")");
solved the problem. ( eval("var layer = " + json); will also work)
A discussion of the problem can be found here.
It turns out that while my object was a collection, the generated JSON looked something like this:
[{a: 'abc', b: 'def'},{a: 'ghi', b: 'jkl'}]
The parser clearly understood this as a collection object being initiated.
When I changed the underlying object, the JSON changed to something like this:
{a: 'abc', b: 'def', c: [{d: 'ghi'},{d: 'jkl'}]}
The string now started with a curly bracket '{', instead of a square bracket '['.
When evaluating this string using eval(), this quite literally means the start of a new block statement, with stuff inside evaluated as a set of instructions, and hence the error. Putting the parenthesis around the string changes it's meaning to denote the contents of an expression, and it is then treated as an object initialiser.
Without the parenthesis, the statement occurs as a lefthand statement, but with it, it is a right hand statement.
I had some code parsing a JSON string returned from a callback.
var layer = eval(jsonLayer);
This worked fine, until I changed the object that was serialized to and from JSON from a collection inheriting from System.Collections.Generic.List to a base object, with the collection as a property.
I suddenly started getting an error stating "Microsoft JScript compilation error: Expected ';'"
Changing the code to:
var layer = eval("(" + jsonLayer + ")");
solved the problem. ( eval("var layer = " + json); will also work)
A discussion of the problem can be found here.
It turns out that while my object was a collection, the generated JSON looked something like this:
[{a: 'abc', b: 'def'},{a: 'ghi', b: 'jkl'}]
The parser clearly understood this as a collection object being initiated.
When I changed the underlying object, the JSON changed to something like this:
{a: 'abc', b: 'def', c: [{d: 'ghi'},{d: 'jkl'}]}
The string now started with a curly bracket '{', instead of a square bracket '['.
When evaluating this string using eval(), this quite literally means the start of a new block statement, with stuff inside evaluated as a set of instructions, and hence the error. Putting the parenthesis around the string changes it's meaning to denote the contents of an expression, and it is then treated as an object initialiser.
Without the parenthesis, the statement occurs as a lefthand statement, but with it, it is a right hand statement.
Subscribe to:
Posts (Atom)