For most people, the idea of writing a book is a daunting one. There is little that scares people more than a blank page and the need to put 10,000 words onto it in the next 30 days or so. I believe that death and public speaking might be higher on the list, but only by a little. So the gumption it takes to put together a book proposal, submit it to a publisher, write all of those words, suffer with editors and technical editors making comments and finally get to the point where it’s it published is a big deal. For that reason, I’d like to celebrate two of my ObjectSharp colleagues, Lori Lalonde (@LoriBLalonde) and David Totzke (@VisualDragon) who now have a publication date for their book, Windows Phone 8 Recipes.
I know that it’s a thankless journey, but allow me to offer up my appreciation for your contribution to the world of technical literature. As for the rest of you, you can show your appreciation by going here and buying a copy. It is currently on pre-order with a scheduled publication date of June 26th, but you can buy an alpha copy of the book and get access to the wonders that are inside right now.
Hopefully most, if not all, of you will be aware of the AppFests that ObjectSharp ran in conjunction with Microsoft between September and December of last year. If you had the joy of attending, you would definitely be aware that by submitting apps to either the Windows Phone Marketplace or the Windows Store, you would have a chance to win either a Surface RT or a Nokia Lumia 920. Well, it has taken a while to get the submission information (and thanks to Jonathan Rozenblit for his help), but we have gathered up all of the apps that were submitted, calculated the entries and found our winners. They are as follows:
Surface RT Winner: Tom Walker (Orange Crush)
Tom submitted nine apps and the following is one of his better reviewed ones
Short Cuts - Life is to short to waste time trying to find your phone settings. Short Cuts enables the user to quickly access their phones wifi, bluetooth, airplane mode and cellular settings
Nokia Lumia 920 winner: Gordon Lo (13 Sides)
Gordon submitted a total of 8 apps and the following app received 4 stars over 17 reviews
My Business Card - My Business Card is a simple, fast, and lightweight way to share your contact information using a QR Code. This app encodes it as a MeCard that is compatible with virtually all QR Code scanners out there. Share quickly, and share easily with My Business Card.
Finally, just so you have a sense of the volume of apps produced through the AppFest engine :), we recorded a total of 107 Windows Phone apps and 49 Windows Store apps. Not bad, but I know you can do better. If you check out the Developer Movement web site (http://www.developermovement.ca), you can see how to sign up, submit your apps and win some cool prizes.
I will profile a number of the other apps that were created through the AppFest process over the next few blog posts. If you’d like to receive some publicity for apps that you have built, feel free to drop me an email with a link to your store or marketplace page.
At one of our clients, TFS build server was choking for no good reason with the following error “Please contact your administrator. There was an error contacting the server. Technical information (for administrator): System.ServiceModel.ServiceActivationException.” Not very useful error message, isn’t it? TFS logs were a bit more informative and had the following error:
WebHost failed to process a request.
Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/4342953
Exception: System.ServiceModel.ServiceActivationException: The service '/tfs/queue/DefaultCollection/Services/v4.0/MessageQueueService2.svc' cannot be activated due to an exception during compilation. The exception message is: This collection already contains an address with scheme http. There can be at most one address per scheme in this collection. If your service is being hosted in IIS you can fix the problem by setting 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled' to true or specifying 'system.serviceModel/serviceHostingEnvironment/baseAddressPrefixFilters'.
Parameter name: item. ---> System.ArgumentException: This collection already contains an address with scheme http. There can be at most one address per scheme in this collection. If your service is being hosted in IIS you can fix the problem by setting 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled' to true or specifying 'system.serviceModel/serviceHostingEnvironment/baseAddressPrefixFilters'.
Parameter name: item
at System.ServiceModel.UriSchemeKeyedCollection.InsertItem(Int32 index, Uri item)
at System.Collections.Generic.SynchronizedCollection`1.Add(T item)
at System.ServiceModel.UriSchemeKeyedCollection..ctor(Uri addresses)
at System.ServiceModel.ServiceHost..ctor(Type serviceType, Uri baseAddresses)
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(Type serviceType, Uri baseAddresses)
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri baseAddresses)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
--- End of inner exception stack trace ---
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)
at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath, EventTraceActivity eventTraceActivity)
Process Name: w3wp
Now, that’s a much better error message. It actually tells us that the problem is caused by multiple bindings in IIS on TFS website and it tells us how this error can be fixed. I love such errors. Anyway, to fix the problem we need to add the following line to web.config file on TFS server:
Then restart TFS Build Service, and it’s all good again…
Shortly after I published my last blog entry on the complaints that developers have about writing unit test (see Do I Have to Unit Test), I came across this blog entry from Derick Bailey entitled “You Are Not Paid to Write Software”. This approached the issue of excuses for the lack of unit tests from a different angle. And one that I wholeheartedly agree with.
So let me ask those of you who are professional developers a simple question. What do you think your job is?
Is your job to write the code that your boss tells you to write?
Is you job to write the code to implement every feature that your users ask for?
Is your job to find the most efficient and effective way to move the contents of a database and put it onto the screen?
Is it to optimize the code that you’re writing to squeeze every last drop of performance from it?
I’m going to suggest that you should have answered no to every single one of those questions.
If you are a developer, your job is to solve problems. The process is supposed to go as follows: users describe the problem, you develop a solution to the problem, you deliver solution to the problem, user is happy.
Sounds almost too easy, doesn’t it :)
But there is an unspoken contract in this process. Once you have solved a problem, there is no reason why you should have to solve the problem again. You don’t want to have to solve it again. And the user has no reason to have you solve it again. Not to mention that the user doesn’t want to find out that the problem that was previously solved is back again.
So why do you not do everything in your power to keep this from happening? And what is one of the simplest steps you could take?
Write unit tests.
You see? Derrick is correct. You are not paid to write software. You are paid to solve problems. And to make sure that they stay solved. Again, what is one of the easiest ways to make sure this happens?
Write unit tests!
Keep that in mind they next time you question whether you should be writing unit tests. It’s actually not a question that should come up. Writing unit tests should be part of your job. And if it’s not, then ask yourself what you think your job really is?
It could very well be the fact that I have four kids that makes me interpret this particular question as coming from the mouths of one of my children. It’s like I have asked developers to eat their broccoli while staring at a three scoop sundae sitting not 6 inches from where they sit.
First off, I’m not a ‘true believer’. I don’t do TDD for every drop of code I write. For instance, if I have a simple property (that is, nothing but storage and retrieval), I won’t start by writing a unit test. This changes the moment that I put any kind of functionality (like validation) into the property. But my starting point for properties is not truly red-green-refactor.
That having been said, my short answer to the question in the title is “yes”. My longer (and less sensitive) answer is ‘Of course you do. Duh! Why would you not want to write unit tests’.
To be honest, if you’re a developer and asking this question, I’m guessing that you don’t understand why you should actually demand that unit tests be written for your code. So let’s go over what the benefits of a good suite of unit tests.
Change != Breaking Changes
Your code is going to change. Maybe not today. Maybe not tomorrow. But some day and for the rest of its life. It’s one of the few givens in programming. But when you do make a change to your code, how do you know whether or not it’s a breaking change. I mean, you’re trying to avoid breaking changes (at least unintentional ones). But how do you KNOW?
The answer is that without unit tests, you don’t. So one reason for writing unit tests is to make sure that when you’re fixing a bug or adding a new feature that you don’t unintentionally introduce problems. This was driving home for me about 8 or 9 years ago. I was working on a project for a commercial application that had about 25-30 people on the team. We were getting close to delivery and we went through a performance sprint. In other words, the sole purpose of the sprint was to find bottlenecks and fix them.
Ask yourself this question. Would you, about two weeks prior to the delivery date of a large project, completely revamp some of the internal functionality? Change how some fundamental functions worked so that performance was improved? If you did, would you be putting your project at risk?
With a complete set of unit tests, we could do this knowing that so long as all of the tests were green when we finished the change, the rest of the application would be unaware of our modifications. Unit tests allowed me to sleep peacefully when the product was eventually released.
One of the interesting side effects of unit testing is that you have to be a consumer of your own classes. You have to create and use the methods that you have created. Sometimes that can be an interesting (and humbling) experience. If you find a method awkward to use, odds are that any other developer will have the same feeling.
So fix it. As you’re writing your unit tests, change your methods, change your parameters, make it better. This is part of the refactoring step in TDD. But if you haven’t had to actually use the methods that you created, you’re less likely to see that it’s not easy for someone else to use them.
How many of you write documentation for your code? Yeah, though so. How about putting comments into your code? More, but probably still not that many. What if you could provide any future changer of your code examples of how you expected that your methods would be called?
That’s what unit tests provide.
Again, for every reasonable combination of parameters, you have a method that demonstrates what you expect to go in and what you expect the result to be. It’s not as viewable as a help file, but it beats the heck of the ‘nothing’ that you’re currently doing.
Ultimately, the reason to unit test is not just to find bugs. It’s to allow for the natural evolution of the code you write to continue without you needing to be there. And doing something other than maintaining the code you’ve written is an ideal that we all strive for.
I have a customer that wanted to create Approvals for a particular work item type. We decided the best way to do this would be to create an Approval work item type and a new Link type called Approvals.
I found it difficult to find an example out there of creating new work item and linking it to another using my own link type. Once I got it working I thought I would Blog it so the next person looking for this has one more example.
Here are the steps; first using the process editor I created a new Link Type (see screen shot below for details). You can use the command line tool witadmin importlinktype to import your link type to the project.
Now to write a web service that is called via bissubscribe to create approvals for my source work item when the source work item is created. In the real code this was a bit more complicated. We had to look up who many approvals were required and create on approval for each person that was required. I have trimmed the code down to the bare necessities just to illustrate how to create the link.
Therefore here is a sample of the code to create a new work item of the type Approval and link it to the source work item with the relationship Approved By.
//Get the TFS Collection and ensure Authenticated
TfsTeamProjectCollection TfsCollection = new TfsTeamProjectCollection(new Uri "https://Server/tfs/Collection"));
//Get the Work item store
WorkItemStore workItemStore = TfsCollection.GetService<WorkItemStore>();
//Get the project
Project project = workItemStore.Projects["MyProject"];
//Get the Source Work item (Take for granted I have been passed the ID of the work item to be approved
WorkItem source = workItemStore.GetWorkItem(ID);
//Make a copy of that as an Approval. This way all the common data is pushed into the approval
WorkItem approval = source.Copy(project.WorkItemTypes["Approval"], WorkItemCopyFlags.None);
//Remove the related link that is created by the copy method
//Save the new work item
//Create a link of the type Approvals
WorkItemLinkType linkType = workItemStore.WorkItemLinkTypes["Approvals"];
//Create a linktypeend using the foward name in out case that is Approved By
WorkItemLinkTypeEnd linkTypeEnd = workItemStore.WorkItemLinkTypes.LinkTypeEnds[linkType.ForwardEnd.Name];
//Add the link to the source work item
source.Links.Add(new RelatedLink(linkTypeEnd, approval.Id));
As a starting point, the SSRS I’m talking about here is SQL Reporting Services (had a mix up with SSMS yesterday and I’m not taking any chances). And the basic scenario is a common one. The report, which happens to be in Tablix format, has a number of rows of headers that are intended to appear at the top of each page.
This is not an abnormal request. Not in the slightest. However a recent problem strained my patience as I attempted to put the silly headers at the top of every page.
The problem was that, on an irregular but consistent manner (which is to say that it didn’t happen for every combination of parameters, but once you saw the problem, it didn’t just “go away”), the header would go missing. Instead of appearing at the top of the page, it just not be there. Or perhaps it only some of the rows of the header would be there. In this later case, if you changed the page size, you could get it to appear. But then another combination of parameters would cause the same behavior. But the upshot is that I couldn’t depend on the headers to appear every time I needed them too. Frustrating doesn’t begin to describe the feelings I had towards SSRS and headers.
First off, if you’re looking for a solution, some of the pages you’ll find do cover the fundamental process. For example here, here and here. And the information provided therein was accurate. Yes, you need to get the RowGroup into Advanced Mode. And you need to set the RepeatOnNewPage property to true. And KeepWithGroup to After. And FixedData to true. However, I’m afraid this might not be enough. At least, it wasn’t for me. Those steps had already been performed and I was still seeing the problem.
For me, the key to getting to the complete answer was something that I just happened to stumble across. It was a line in an MSDN document (that I can’t seem to find again) that said that row headers were only displayed on each page if there was enough room vertically. Column headers, on the other hand, would always be displayed. In other words, if you had placed your ‘column headers’ as just values in rows within the Tablix, then SSRS wouldn’t do anything special to ensure that they appeared at the top of each page. And this would be true even if you had taken the steps mentioned in the previous paragraph. If there was “too much” report data on the current page, the headers would be cut off as part of the prioritization that SSRS does.
With that piece of information in hand, I had another clue to search with. And that led me to a post that talked about the fact that repeating column headings only worked *if* there is a column headings area on the report. And, depending on how you created the Tablix, that might not be the case.
You call tell if you have a column heading area if you see a double dotted line someplace in the Tablix. If you don’t, then you find yourself in the situation I was in. Now, you *could* create a column group and move your row headers up to that level. For me, that was not a practical choice (because of the complexity of the data being shown in the headers). So instead, I faked it.
Start by adding a Parent Column Group. It doesn’t matter what you group by, so just select an arbitrary field or type in a constant. I choose ‘0’. Doing this adds the column heading areas to the report. Now we need to get rid of the added row without getting rid of the column heading area. In the Grouping Panel at the bottom of the report, right-click on the just added column group and select Delete. In the dialog that appears, you will be given the choice to delete either the group and related rows and columns or to delete just the group. The correct choice here is to delete just the group. If you also delete the related rows and columns, you will be back where you were before with no column heading area. Once you have deleted the group, you can go into the Tablix and delete the row which is related to the column group.
At this point, you will have a Tablix that has a column heading area with no rows in it. And your report will look as it did before. But, more importantly, because there is a column heading area, the row headers which you had previously created (and which had been cut off or just plain went missing) are now visible at the top of every page, regardless of whether a soft or hard page break rendering engine is used.
And now the world can get back to spinning on it’s regular axis. Whew!
Unless you have been living in a cave (technology speaking), you should be aware of that amorphous thing known as the ‘cloud’. Even people who are not in the technology profession are aware of the term (although 29% think that it’s something related to the weather - Citrix survey). Still 97% use cloud services in one way or another and 59% believe that the workplace of the future will exist entirely in the cloud. While I don’t expect that to be the case (at least not within my lifetime…a phrase that gets easier to be correct in using with each passing year), there is no question that the cloud is no longer about future hype. It’s here, it’s real and it’s ready to grow.
So, what does that mean for you and your career. Well, if you believe the new study published by Microsoft and IDC, the answer is "lots”. According to the study, there are currently 1.7 million open cloud jobs worldwide. And companies are having a difficult time filling their needs. Not only that, the expectation is that 7 million cloud jobs will be created over the next three years.
So what are ‘cloud jobs’? Well, the contention made by the study is that the new jobs will involved architecture, design and traditional services. In other words, not just the normal heads-down, ‘tech’ job, but one that includes a mix of business acumen and IT competency. The jobs where knowing how to do stuff is not sufficient. Jobs where you need to defend and explain your choices to both technical and non-technical management. In other words, what I consider to be the ‘interesting’ IT jobs.
So how can you prepare for this ‘cloudy’ world? Get some knowledge. Unfortunately, taking one course or even a couple is just the start (ObjectSharp does offer a course on Azure). You need to learn about the broad swath of technologies that are including in the ‘cloud’. Check out the latest functionality in Windows Azure. Looked at it last month? Well, look again…it changes that quickly. Keep you ears tuned to Azure-related social media. In Canada, there is the @CdnAzure Twitter account as well as the Developer Connection blog. As well, you can follow my Twitter account (@LACanuck) or my blog. While I don’t blog about Azure too much (I’m actually in the middle of writing a book on Azure which will hopefully come out in a few months), I do tweet about it quite regularly.
In other words, the process of making yourself cloud capable is an on-going and active one. The information will not come to you unbidden. Reach out and grab it wherever you can find it. And don’t be afraid to ask. I (and many others in the community) are happy to help out whenever we can.
I’m privileged to be the Tech Chair for Cloud and Windows 8 tracks at DevTeach. This time out, the conference is being held at the Delta Meadowvale in Mississauga from May 28 to 30 (see http://www.devteach.com/ for details). All of these sessions (in both topics) will take place on the same day, which (based on the current schedule) will be the 29th.
So what am I looking for? Topics that will help developers solve the problems that they face every day. Topics that will let developers become more effective. Topics that go beyond the introductory level (they can already get that through various channels, such as Channel 9) and get into the meat of the technology. The template for submission is available at: http://www.devteach.com/download/DevTeachToronto2013SessionAbstractsTemplate.xlsx. The deadline for submission isn’t until the end of January, so you have the time to be creative. And I look forward to seeing what the developer community can come up with.
A few things you might want to keep in mind as you think about your possible topics:
- The audience for the conference will be about 50% web developer ( including about 10-20% of those who are SharePoint developers) , 25% other developer (client, mobile, etc) and 25% admin
- I’m mostly looking for developer talks but I am willing to consider admin talks. I won’t be selecting more than one admin talk for each track
- Crossover topics are possible. I’ll determine which track they will fall into based on the complete list of submissions.
- ObjectSharp will be doing an intermediate to advanced level post conference workshop on Windows 8 XAML, so keep that in mind
If you have any questions, please ask. I’m happy to provide any assistance or guidance that you might need.
One of the tools any TFS admin keeps in their toolbox is the TFS Administration Tool. This tool makes it very easy to manage security for TFS. Allowing you to manage user permissions on all three platforms used by TFS. Specifically TFS, SharePoint and Reporting Services.
Download version 2.2 here.