I am in the process of building out a internal portal/dashboard for our company which will allow us to get a status of what is going on behind the scenes in our application. I want this site to utilize our existing WCF endpoint and as much existing code as possible. When doing this I realized pretty quickly that I needed to create Async Controller actions to hit our async endpoints which was a first for me. Of course the first thing I did was a quick Bing search to see if I could find some existing examples to help me a long. However, every example I found assumed that we were using the automatically generated proxy to access our endpoints rather than spinning up the connection manually via ChannelFactory and the service interface. Because I struggled to get this working I thought I would share my experiances in case others are having the same issue.
Our WCF Endpoint Definition
[ServiceContract] public interface IScheduledEventsService { [OperationContract(AsyncPattern = true)] IAsyncResult BeginScheduledEvents(ScheduledEventsRequest request, AsyncCallback callback, object state); Result<IList<ScheduledEvent>> EndScheduledEvents(IAsyncResult result); }
One thing to point out about the code above, the actual return value from our endpoint is a Result<T>. The result class is a simple container envelope which provides us back some metadata, this is not something to worry about or to try to find online, you can simply ignore this for your needs
My MVC controller definition
public class ScheduledActivitiesController : AsyncController { public Task<PartialViewResult> Listing() { return Task.Factory .StartNew(() => GetScheduleActivitiesAsync()) .ContinueWith(x => PartialView("_Listing", x.Result.ToList())); } private IList GetScheduleActivitiesAsync() { var baseUrl = ConfigurationManager.AppSettings["BaseWcfServerUrl"]; var channel = ChannelHelper.CreateFor<IScheduledEventsService>(baseUrl); var myTask = Task.Factory .FromAsync(channel.BeginScheduledEvents, new Func<IAsyncResult, Result<IList<ScheduledEvent>>>(channel.EndScheduledEvents), new ScheduledEventsRequest(), null, TaskCreationOptions.None); var taskResult = myTask.Result; return taskResult.ResultItem; } }
The above code is our entire controller (well at least the important parts her). Please take note of 3 things
One thing I want to point out here is that when trying to get the .FromAsync logic to work I keep getting compiler warnings telling me about a mismatch. This was because at first I was NOT declaring my two Func<T> and just assumed the compiler knew what I meant (guess not). As soon as I actually defined my 2 Func<T> signatures (I have removed the first one as R# told me it was not needed and sure enough it was not) the compiler was happy.
As you can see, once you make the compiler happy (pesky compiler) this is pretty straight forward. Hope this helps someone.
Till next time,
If you are interested to hear some of the back story behind Caliburn.Micro…or just curious about my own conception of MVVM and how it fits in with other popular UI design patterns, I hope you will check out this interview on InfoQ. As always, feedback is much appreciated. Happy Monday and have a blessed week
If you are building a XAML based WinRT application which uses a GridView it is very likely you are going to use an ItemTemplate style OR use the ItemTemplateSelector to determine which style to use. This is great and using either of these could not be any easier. HOWEVER, make sure you do not have both of them set at the same time in your XAML. Because if you do use them both you will be left to wonder why your TemplateSelector code is NOT working, but your provided style is.
As far as I can tell the ItemTemplate trumps the ItemTemplateSelector and your selector will NEVER get executed.
You will want to either use just the ItemTemplate OR use the ItemTemplateSelector.
Hope this helps.
It’s common for a single web page to include data from many sources. Consider this screen shot from Project Silk. There are four separate items displayed.
The primary concern of the page is displaying a list of vehicles. However it also displays some statistics and a set of reminders. I labeled the stats and reminders as orthogonal because they are (in a sense) independent of the primary concern. Finally, there is the ambient data of the currently logged in user. I call this data ambient because we expect it to be present on all the pages in the application.
It’s a common practice in MVC-style applications to map a single controller action to a view. That is, it is the responsibility of a single action to produce everything that is needed to render a particular web page.
The difficulty with this approach is that other pages often need to render the same orthogonal data. Let’s examine the code for the action invoked by \vehicle\list.
\vehicle\list
public ActionResult List() { AddCountryListToViewBag(); var vehicles = Using<GetVehicleListForUser>() .Execute(CurrentUserId); var imminentReminders = Using<GetImminentRemindersForUser>() .Execute(CurrentUserId, DateTime.UtcNow); var statistics = Using<GetFleetSummaryStatistics>() .Execute(CurrentUserId); var model = new DashboardViewModel { User = CurrentUser, VehicleListViewModel = new VehicleListViewModel(vehicles), ImminentReminders = imminentReminders, FleetSummaryStatistics = statistics }; return View(model); }
Disregarding how you might feel about the Using<T> method to invoke commands and other such details, I want you to focus on the fact that the controller is composing a model. We generate a number of smaller viewmodels and then compose them into an instance of DashboardViewModel. The class DashboardViewModel only exists to tie together the four, otherwise independent data.
Using<T>
DashboardViewModel
Personally, I prefer to avoid classes like DashboardViewModel and simply rely on dynamic typing in the view. However, others feel strongly about having IntelliSense support in the view.
Project Silk had separate actions just to serve up JSON:
public JsonResult JsonList() { var list = Using<GetVehicleListForUser>() .Execute(CurrentUserId) .Select(x => ToJsonVehicleViewModel(x)) .ToList(); return Json(list); }
You’ll notice that both JsonList and List use the same GetVehicleListForUser command for retrieving their data. JsonList also projected the data to a slightly different viewmodel.
JsonList
List
GetVehicleListForUser
While reevaluating this code for Project Liike, we decided to employ content negotiation. That is, we wanted a single endpoint, such as \vehicle\list, to return different representations of the data based upon a requested format. If the browser requested JSON, then \vehicle\list should return a list of the vehicles in JSON. If the browser requested markup, then the same endpoint should return HTML.
First, we needed to eliminate the differences between the JSON viewmodel and the HTML viewmodel. Without going deep into details, this wasn’t hard to do. In fact, it revealed that we had some presentation logic in the view that should not have been there. The real problem was that I wanted the action to look more like this:
public ActionResult List() { var vehicles = Using<GetVehicleListForUser>() .Execute(CurrentUserId); return new ContentTypeAwareResult(vehicles); }
Only, the view still needed the additional data of statistics and reminders. How should the view get it?
We decided to use RenderAction. RenderAction allows a view to invoke another action and render the results into the current view.
We needed to break out the other concerns into their own actions. For the sake of example, we’ll assume they are both on the VehicleController and named Reminders and Statistics. Each of these action would be responsible for getting a focused set of data. Then in the (imaginary) view for List we could invoke the actions like so:
VehicleController
Reminders
Statistics
// List.cshtml <ul> @foreach (var vehicle in Model) { <li>@vehicle.Name</li> } </ul> <section role="reminders"> @{ Html.RenderAction( "Reminders", "Vehicle") } </section> <section role="statistics"> @{ Html.RenderAction( "Statistics", "Vehicle") } </section>
Note that each action has it’s on associated view.
The value of using RenderAction is that we where able to create very simple actions on our controllers. We were also able to reuse the actions for rendering both markup and JSON.
A secondary benefit is the separation of concerns. For example, because we moved the responsibility of composition from the controller into the view, a designer could now revise the view for the \vehicle\list without needing to touch the code. They could remove any of the orthogonal concerns or even add new ones without introducing any breaking changes.
There are a few caveats with this approach.
First, don’t confuse RenderAction with RenderPartial. RenderAction is for invoking a completely independent action, with its own view and model. RenderPartial is simply for renders a view based on a model passed to it (generally derived from the main viewmodel).
Secondly, avoid using RenderAction to render a form. It’s likely won’t work the way you’d expect.This means that any form rendering will need to occur in your primary view.
Thirdly, using RenderAction breaks the model-view-controller pattern. What I mean is that, in MVC, it’s assumed that the view does nothing more than render a model. Controllers invoke a view, and not vice versa. Using RenderAction breaks this rule. Personally, I have no problem breaking the rule when it results in code that is more simple and more easily maintained. Isn’t that the whole point of best practices anyway?
Today I was trying to wrap one of our .dll projects in a wcf endpoint and ran into an odd issue that took 3 hours to resolve and the mad skills of my co-worker James to help resolve.
Long story short, when I would F5 my web project which was hosting our WCF endpoints I would get the following message in the browser.
Of course when I got this I immediately jumped to the referencing project and made sure I had referenced all the needed child assemblies. When this checked out I then jumped to the BIN folder to make sure they were copied correctly, they were. When THIS failed I fired up Just Decompile to ensure that the version of the assemblies were right… All of this lead me NO WHERE.
Now that I have done the typical checks I resorted to firing up the Fusion Log viewer with hopes that this would help… Yea that did nothing….
At this point I was beating my head against the desk, this was also the point that I enlisted the skills and knowledge of James. As we were talking through the problem and looking around we made our way over to the project properties of the dll I was referencing. When looking over the properties James noticed that my target platform was x86 (seen below),
which immediately sent up the red flag for him (it did nothing for me). Of course the question of ‘why is this x86’ was asked to which I answered ‘I don’t know’ but I did know the that project was originally a console app project prior to being switched to a library project…. Ding, Ding, Ding…. Console apps are set to x86 by default not Any CPU.
Once we changed it to Any CPU and recompiled my issues were resolved (seen below)
The moral of the story is that if you get the ‘bad image’ error make sure you are not trying to reference an x86 assembly in your x64 projects.
Do you ever have one of those ‘Doh’ days? One of those days where you spend like 6 hours trying to replicate a bug simply so you can debug it. One of those days you wish you could have back? Well I had one of those last week, let me explain.
Recently I was trying to debug an issue where when I would add an instance of an object to the db contenxt sometimes it would take it and sometimes it would not. I tried for hours to replicate the exact steps so I could narrow down the issue but was not able to. Here is what I was essentially doing.
dbContext.MyCollection.Add( instance1 ); dbContext.MyCollection.Add( instance2 ); dbContext.MyCollection.Add( instance3 ); (of course my logic was not like this in the actual code, but it did boil down to this)
At the end of my 3 adds I would do dbContext.MyCollection.Count and expect to see 3, but in almost ALL cases I would get a 1, color me perplexed. To make it even more perplexing for me is that after each .Add I would check .EntityState of the newly added instance and in EVERY case it was NEW. I would also hashcode for each instance to ensure they were different and as you may have guessed they were….. WTF
Fast forward a few more hours of my swearing like a drunk sailor, beating my head on my desk I decided to chat with a co-worker of mine whose knowledge in EF is order of magnitude larger than mine. Although he did not know the direct reason for my pain he did make a magic assertion which lead me to remember something I did a few weeks back. He said,
Well when you add an instance to the collection EF will essentially just check that object for equality versus all the other objects in the collection to make sure they were different.
The minute he finished that sentence the ‘ah F@CK’ bomb went off in my head. See a few weeks prior, during very early development of this feature I had this brilliant idea that I needed to override the .Equals() method on my entity objects (yea I know, that was dumb) so I did. However, as my logic matured over time the .Equals did not keep up because at some point I had realized that I did not need to override that but I was entirely to lazy to delete my overridden method, oh that came back to hurt.
As soon as I realized that this may be the issue I blew away the .Equals() along with my override of GetHashCode() (which actually was simply a pass through to the base implementation) and what do you know, everything simply worked.
The moral of the story here is that when dealing with EF (or any ORM for that matter) I would highly suggest you do not override the .Equals() on your objects, unless you like pain and suffering
till next time,
I started work with “Xaml-based” platforms in the pre-Beta days of WPF, so I’ve been working with this technology longer than most. Back then I was utterly awed and inspired by it’s capabilities. Today I’m frustrated and sometimes outraged. As I’ve traveled to various conferences, worked with various companies and interacted with the many Caliburn.Micro users, I’ve discovered that I’m not the only one who feels this way. This blog series attempts to catalog a number of the issues, some of which have been there from the very beginning; others creeping in over time. This is an aggregate of my own observations and those of the community.
Let’s take a brief stroll through the platform timeline:
If we focus on the platforms and ignore their various versions, we have something like this:
So, it appears that Microsoft has released a new UI platform at least every two years! Let’s contrast that to the timeline for pre-Xaml UI technologies:
Interesting. We have at least 5 – 6 years between platforms prior to Xaml, but it’s actually about 10yrs due to the fact that WinForms is just making Win32 available to managed languages. It’s just a wrapper around existing APIs. Each of the Xaml platforms is actually a different runtime altogether. So as far as platforms go, we’ve gone from one every 10yrs to one every 2 years. But that’s not all, let’s look at Xaml itself:
Aside from the actual platforms released, we have a parallel divergence in Xaml markup capabilities. In 2006 the first version of Xaml was released. It was formally defined and released as a spec shortly after. When Silverlight came along, Microsoft failed to create a Xaml language compatible with their own specification. In fact, even Silverlight 5 doesn’t comply with the Xaml 2006 spec. In 2009 Microsoft released a new version of Xaml that fixed several important shortcomings with the 2006 spec….but not a single platform implemented it. WP7 is still playing catch-up with Silverlight and WPF. WinRT/Metro Xaml has less Xaml features than any platform. Furthermore, it significantly changes some aspects of Xaml altogether, making it compatible with almost nothing. Furthermore, some of the changes they are making will prevent it from ever becoming compatible in the future.
When I step back and try to look at this information objectively, the most natural conclusion I can come to is that Microsoft UI technologies are, and have been for the last five years, in a state of complete instability…and it doesn’t show any signs of change (esp. with the rumors that WP8 will not use Silverlight, but some variant of WinRT). You can’t count on anything. If we forget about app developers for a moment, and think about the ecosystem, imagine the effect this has on third party products, control vendors, open source frameworks and tooling. Every time MS spits out a new platform or Xaml flavor, the entire ecosystem has to start over.
My own Experience
I first wrote Caliburn for WPF when there was no word on anything like Silverlight existing. When Silverlight was first announced, it was branded WPF/e so I thought my framework would port. Unfortunately, when SL2 was made available, there were so many differences that I had no choice but to completely re-write Caliburn. Then, when WP7 was announced, I started porting Caliburn to that, only to discover that it was not possible. So, I did another complete re-write resulting in Caliburn.Micro. Now we have WinRT/Metro. I think I can port it, albeit, with a ton of conditional code. But, I’m not 100% sure yet. If it looks like another re-write…I’m done with this game.
Maintenance and Innovation
There are lots of negative side-effects to this sort of instability. The one that hits me most is that it creates a battle between maintenance and innovation. Again, speaking of my own project, I have plenty of ideas about how to improve Caliburn.Micro. I think some of them are minor niceties, but others are more along the innovative lines. But, you will never see any of them come to fruition. Why? Because the instability of the underlying platform, the constant release of new platforms…has put my project into a state of perpetual maintenance. I can’t innovate because I’m still trying to deal with the differences in WP7.5 and I’ve got developers (who can blame them?) banging down my door wanting to know when WinRT/Metro version will be available. It’s been discussed much in recent years as to why innovation seams to happen in non-Microsoft open source and on other platforms like Mac…while very little happens in Windows software. Could it be because we are spending our time re-writing everything every two years? and don’t have time to develop anything forward thinking?
Careless and Arbitrary
Sadly, many of the API and Xaml differences were completely avoidable. I remember one particular bug I had in Caliburn. It resulted from the fact that List<T>.Remove was implemented differently between WPF and Silverlight. In a particular scenario it would work fine on one platform and crash your app on another. There are hundreds, probably thousands of such issues, from the BCL all the way up through the UI stack. We aren’t talking about missing features here. We are talking about the same features which exhibit different behavior or have altered APIs. Sure, Microsoft worked hard to improve this with successive releases of Silverlight. But then came WP7, which stepped us back in time. Now look at WinRT. There are a number of changes that are completely arbitrary. They serve no technical purpose and don’t improve the API. They just make more work for developers who want to port code. If you want another fine example, just try to write a cross-framework design mode check.
A Lack of Understanding
Sigh. This one perfectly ironic issue really troubles me sometimes. Through all of this, I’ve realized that Microsoft doesn’t understand their own platform. I’ve got more to say on this later, but let’s look at this from an API perspective here. Consider this: every control specific to WP7 development could have been built on top of Silverlight without a need for a modified runtime. Most controls could have been implemented simply by styling an existing control or applying a template. For example, the Pivot control can be implemented using a tab control with a custom template and some attached behaviors. In fact, wouldn’t it have been cool if you could just use a Tab control in WP7 and it just changed it’s appearance to work on the phone?! Wait, wasn’t that the idea behind templating and adaptive layout to begin with? Here’s another example: Behaviors. Perhaps you didn’t know that Microsoft built this twice? In WPF there were Triggers. In fact, in both WPF and the Blend behavior system, there is a class called TriggerBase. They have the same name! They do the same thing! But, you can’t create custom triggers or actions in WPF because the ctor is marked internal. Did it not occur to anyone that they should just remove that instead of re-inventing the wheel? As a result, we now have two methods of doing triggers, and you have to know which to use for what. It’s even true in Silverlight, which has limited support for “traditional” triggers, but does have some. Ridiculous. I could go on and on about the types of internal and cross-platform inconsistencies MS has created by not simply understanding the core capabilities of their own framework.
All of this get’s really interesting if you consider that Mac is the platform that is considered most cutting edge and innovative in terms of UX…and they’ve scarcely had any major breaking changes since 2002. Considering that their phone apps run on their tablet and they are porting a number iOS features back to OSX…it must be nice only having to worry about two platforms and knowing that the OS vendor is making a visible, tangible effort to unify those two platforms…..but I’m getting off topic now.
End of Part One
There are lots of problems with Xaml, but I chose to start this series with one of my particular pain points. Some developers neither care nor are affected (yet) by these sorts of version issues, but they have a big effect on the surrounding ecosystem and are going to be with us for the next decade. Over the next several blog posts, we’ll discuss many other problems, some technical, some not so much, but all have been singled out by multiple members of the community (read: not just me) as problems. It is my hope that Microsoft employees working on these technologies will read this and seriously consider what they can do to improve things going forward or at least not perpetuate the same mistakes again. I also hope that .NET developers will take a long, hard look at this part of the platform and make an honest valuation of its strengths and weaknesses.
1. Lakeshore is the name I’ve been hearing thrown around for the Xaml-runtime for XBox, which sources say is Silverlight-based, but drastically altered. I have no official word from Microsoft on this. It’s just what I heard through the grapevine, though I’m fairly confident in the accuracy of the information. Supposedly this is what is powering the “apps” in the new XBox dashboard which was released around last Thanksgiving. EDIT: Apparently the XBox version is called Lakeview not Lakeshore.
2. I don’t actually know when WinRT/Metro will be released. I imagine that 2012 is a reasonable guess.
Over the weekend I was pounding away at my first ‘WinRT’ application which I plan to submit to the marketplace. During this process I ran into some really odd issues with getting images to display in the UI at runtime.
Let me explain my issue:
I had images which were nested inside my Assets folder as below: /Assets -> /Category -> /Animals -> horse.png
These images were being bound to a view which was not in the root of the solution but rather in a views folder as below: /Views -> /Gameboard.xaml
Originally I was trying to use binding to the Image control to a ImageSource property. In my ImageSource property I was doing something like below
public ImageSource Image { get { var uri = new Uri("ms-appx:///Assets/Category/Animals/horse.png"); return new Bitmapimage(uri); } }
When I would put a break point in the property everything appeared right, however when I would bind to the UI no image would show up. I then tried to play with the URI path by adding ../ by putting the full ‘pack’ uri in there but nothing seemed to work. To prove that the image was NOT loading I also hooked up the ImageFailed event to the image control and of course that was helpful by providing a ‘network error’ value (that was helpful).
**** Note **** I knew the logic above was give-or-take valid because when I changed it too use an image in the root of the Assets folder everything worked just fine **** Note ****
After over an hour and a half of trying everything I could think of I decided to screw binding to an ImageSource and bind directly to the string value for the path.
public string Image { get { return "../Assets/Category/Animals/horse.png"; } }
When I changed my UI to bind to the new property everything magically worked as expected.
I am not sure if I was doing something wrong (likely the case) or if there is some hidden bug in WinRT, but I was able to get everything working.
I was invited to join Devlicious a few years ago by Jak and Brendan and very thankful for the opportunity. During this time, I have cross-posted some of my posts on both my personal site as well as here, and have found that as a result, conversations become segregated; somewhat expected.
As grateful as I am of the the privilege of being part of this great community, I value greatly conversations that arise from posts, and prefer to keep them in one place. It is easier for me, as well as you, dear reader. For this reason, I'll no longer be posting on here. If you'd like to continue the conversations, find me at my blog. I'd love for you to join the recent one about Dealing with Too many dependencies.
Once again, thank you to Jak, Brendan, and the entire Devlicious community, including my fellow bloggers. And most importantly, thank you.
Last night when I was doing some WinRT hacking I was trying to setup databinding to the selected item in the GridView control and I ran into a gotcha that I thought I would share.
First, I was using the ‘Split Application’ template for my C# project. This is important because this template will create a bunch to boiler plate code for you and I was taking this code and extending it.
When I was setting up my SelectedItem binding had had the following Xaml
<GridView SelectedItem={Binding SelectedDashboardOption, Mode=TwoWay} …… />
When I ran the app everything ran fine but when I selected an item nothing happened. I quickly noticed what I thought was the issue, I had not enabled selection in the grid, aka SelectionMode=Single, so I added that. This made my Xaml look like:
<GridView SelectedItem={Binding SelectedDashboardOption, Mode=TwoWay} SelectionMode=”Single” …… />
I gave this a spin but nothing…..
Then I had a thought, maybe the bindings which allowed the Item to be clicked was causing this, turns out I was right. The boiler plate code does not use MVVM (a real shame and IMO this needs to be addressed by MS) but rather click events. This meant that the following attributes were set by default for the GridView via the template.
<GridView …… IsItemClickEnabled=”True” ItemClick=”ItemView_ItemClick” ….. />
All told my Xaml was both setup to handling SelectedItem binding AND the click event. Turns out this is not allowed and will not allow your binding to work.
To solve my issue I simply removed the IsItemClickEnabled and ItemClick attributes and the now I could get the binding for SelectedItem to work.
When building a Windows Metro (aka Windows 8) application it is important that your application have a nice looking tile. It is also encouraged to enable your tile to be ‘live’, meaning it can update itself with content based on some event, if that is relevant to your application. When you create your tile you can decide to have either a small tile which is 150px x 150px (this takes up one column in the UI) or to have a large tile which is 310px x 150px (this takes up 2 horizontal columns in the UI). It is up to you to decide if you to support only the small, only the large or both. Fortunately for you associating the images used could not be simpler.
If you only provide a small logo you will only have that option on the Start screen. If you only provide a wide logo that will be the one which is used. If you provide both, the wide will be used by default, but the user can switch to the small if they want.
Here are the logo’ used in the image above (remember I am NOT a graphic designer )
Small:
Wide:
When I finally got around to upgrading my Build tablet to run the Consumer Preview of both Windows 8 and VS 11 I immediately ran into an issue when trying to attach a ‘legacy’ VS11 project from the Developer Preview version to a new project using the Consumer preview.
The error I received can be seen below.
Turns out the problem is easy to solve. Open up the offending csproj file and look for the line which looks like:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v1.0\Microsoft.Windows.UI.Xaml.CSharp.targets" />
Replace the line with
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
Once you replace the line you should be able to add the existing project as expected.
I just upgraded my dev laptop to Vs11 and all was great with the world….. Until I ran my command line build script on my Silverlight project. When my script failed with the following error I was perplexed because of course everything ran fine from INSIDE VS
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets(289,9): error MSB4006: There is a circular dependency in the target dependency graph involving target "CopySilverlightApplications". [C:\ Development\Source\\Main\Website\Thunderbird\ThunderbirdServer\ThunderbirdServer.csproj]
At first I tried to diff the Microsoft.WebApplication.targets file to see what changed there but nothing looked out of place…hum.
Finally when chatting about this issue with a co-worker it dawned on me what my issue was. Our silverlight project uses RIA Services and because of this there is technically a circular dependency between the web project and the client project.
How?
The client knows about the server because the RIA services end points are created inside the web project and post build the client side RIA endpoints are pushed into the Client project.
The server knows about the client because as a silverlight project we had the server setup to copy the .xap file into the ClientBin folder
How did I resolve this?
I removed the Silverlight copy dependency inside my server project as seen below
I added a post build event inside my Silverlight client project do xcopy the .xap into the correct ClientBin folder in the web project.
Once I made this change I was able to do the following
Hope this helps someone else
I know this may be lame but this may simply be the best install feature ever invented…. Enough said J
The biggest complaint most remote workers have in regards to working on a team? Feeling disconnected. The biggest complaint an office has about remote workers? They forget the remote workers are there and don’t always trust what they are doing. Want to learn how to get past both issues?
Hi, my name is Rob and I have a confession to make. I’m a remote worker four days a week. I’m a placeshift remote worker, and yet I am still highly collaborative with my team. “Placeshifting?” you say. “Highly collaborative?” you say. Over the next series of articles I am going to show you how this can be done.
If you are a business and you have not seriously looked into a technology known as Embodied Social Proxies, you are paying opportunity costs. You are losing money. More on that below. This series is for you so pay attention. I will highlight both business benefits and worker benefits.
If you are a worker and you have considered working from home (or just remotely) but you are not quite sure how you would make it work, this series is for you. Or you are already doing remote work and want to learn how to collaborate better.
Timeshift – This is when you perform work at different intervals than the mainstream office may perform the work. Many folks have done this kind of work in one respect or another, even when working a regular full time job. If you ever went home and continued working in the evening, you have done what some might consider timeshift remote work. This series is not geared to this type of remote work.
Placeshift – Placeshifting is when you perform work at the same time as everyone else, but at a different location. This is what most people think of when they hear the term remote workers. If you ever have work from home days, you know what it is like to placeshift. This series is geared to this type of remote work.
The terms placeshifting and timeshifting are borrowed from media industry (television, music, etc) with respect to devices like DVRs. Not quite clear? When you record a TV show and watch it later you are timeshifting the show. Timeshifting dates back to the 1970s with VCRs and Betamax, while placeshifting media is a newer concept made possible by devices like the Slingbox. When you use a Slingbox to watch a show from a device like your phone at the same time the show is playing, you are placeshifting. The difference should be clear when you think of placeshifting as same time, different location and timeshifting as different time, location irrelevant.
This same terminology can be applied to remote work. Although I was hoping to coin the remote work types terminology, Anybots and GigaOm beat me to print with their recent article (How and why robots are placeshifting remote workers). At least this means the terminology is sound.
Placeshifting remote work is not for everyone and not for every type of business work either. Some jobs have physical requirements or security requirements that negate the ability for remote work. Not every person is able to be productive in a setting outside the office (and the converse is also true). The world is not fair, okay? Get over it. If you are someone who can work by yourself and do so well without being easily distracted (read: there are ways to remove distractions in a work from home situation – I’ll touch on those), then it’s possible you have what it takes to be a remote worker.
This is the argument I hear the most. The biggest problem with this argument is that it is subjective. Remote work itself is subjective/situational. No two remote workers are going to be alike, no two situations are going to be the same. It’s possible you tried remote work with an individual who was not able to work remotely effectively. It’s highly possible you had an employee who moved away and you wanted to keep them so you allowed them to work remotely. But you may not have set yourself (and the individual) up for success. How much planning and research did you do prior to these remote work situations? How much enabling were you towards your remote worker? Did you attempt to manage your remote worker in the same way as the centrally located folks? Have you even heard of Embodied Social Proxies prior to reading this?
The awareness I am trying to raise with you is that there are situations for businesses to make it work. And you can benefit hugely from remote workers if you do the proper planning, research and understand guidelines for making it work in your situation.
Here’s a hard pill to swallow – you are limited by your talent pool. If you require people to be onsite for work, you are limited by the area in which you do business. I hate to be the one to inform you, but you are not the most awesome place to work. I’m sorry. No matter how awesome you are there is somewhere else that is more awesome and does x better. It’s a losing battle. Get over it already.
In this day and age less and less people will move just to work for you. If you expect the most talented folks in your industry to relocate for you, I have to tell you that 1990 called. I’m sorry to inform you it’s not going to happen in every case. And if it does, it’s borrowed time. Because someone else is going to attract them away.
It’s likely the most talented people in your industry will never work for you if you don’t have a remote option available. There are many reasons, but it boils down to where you expect your talent to live.
This is so huge I can’t even begin to give it the proper amount of attention. You want your workers to be happy. Tom Preston-Werner, cofounder of GitHub, speaks to this in a presentation called Optimizing For Happiness. Please go there now. The bottom line is that you keep your workers happy, and they are much less likely to leave your organization. Turnover costs are huge to a company. If you are not making your employees happy, they are talking to others about not working for you. They have their ears open to new opportunities. They are likely looking for other jobs as you read this.
If you think you are making your employees happy, I would ask what metric you use for evaluation. I’ll be the first to tell you that you are not doing enough to keep your employees happy. If you give out raises once a year and they are around 3-5% across the board, you might be doing it wrong. Not every employee is created equal, not every employee performs at the same level. Why would you pay them the same? Why would you give them the same raises?
I’m going to make a bold statement here: Your best people outperform your middle of the line folks by ten times. If you are not paying them ten times as much or even five times as much, you might want to re-evaluate how truly happy you are making your employees. If you are not challenging your employees, you are boring them and they will find something more exciting. If you are not doing x you are likely not making your employees happy. You need better metrics into what makes for happy workers.
Your facility costs are significantly cheaper when it comes to remote workers. A remote worker or semi-remote worker can take up a lot less space than a full time worker. If they come into the office once or twice a week, they will take up some space during that time, but the rest of the week that space could be used by other remote workers when then come into the office. Think of this as space sharing.
Remote workers don’t bring/keep a lot of items in the office. Seriously. Get up and walk around your office. Take a look. Notice how much stuff each worker has surrounding their areas. Notice how much space they take up. Go ask how much it costs for the space of each worker you have in the office per month. If you don’t have this number on hand, you won’t understand what it costs for that worker.
This actually isn’t that hard to calculate if you don’t have it. Just find out the costs of your office space on a monthly basis. Electricity, rent, etc. Now take that number and divide by the number of workers you have on site. This will give you a rough estimate. There are ways to get more accurate estimates, but this is a good start.
For the space of that one onsite worker, you might be able to put 5-10 remote workers in there (if you build and use embodied social proxies which are highly recommended and will be discussed during this series). Imagine that. 5-10 remote workers in that same space. That means for every 10 remote workers you hire, you can only hire one onsite person. Kind of sounds weird to hear it like that, right?
This is probably the most overlooked opportunity cost when it comes to remote workers. You are limited by the number of folks you have into what you can accomplish. When you open up to remote work, you also open up to the fact that you can take on more work. More work in some terms means more revenue for your business. This is huge.
Remote work is not without its challenges. I can tell you that the benefits far outweigh the challenges. If you’ve tried remote work in the past and it didn’t work out, don’t let that be a limiter to trying again. If Thomas Edison quit the first time he failed, he may not have been credited with the invention of the light bulb as we know it! Failure is a step on the road to success. Food for thought.
About The CodeBetter.Com Blog NetworkCodeBetter.Com FAQOur Mission Advertisers should contact Brendan
Subscribe Google Reader or Homepagedel.icio.us CodeBetter.com Latest ItemsAdd to My Yahoo!Subscribe with BloglinesSubscribe in NewsGator OnlineSubscribe with myFeedsterAdd to My AOLFurl CodeBetter.com Latest ItemsSubscribe in Rojo
Member ProjectsDimeCasts.Net - Derik Whittaker
Friends of Devlicio.usRed-Gate Tools For SQL and .NETNDependSlickEdit SmartInspect .NET Logging NGEDIT: ViEmu and Codekana LiteAccounting.Com DevExpressFixxNHibernate ProfilerUnfuddle Balsamiq MockupsScrumyJetBrains - ReSharper <-- NEW Friend!
Site Copyright © 2007 CodeBetter.Com Content Copyright Individual Bloggers