I love small business. They innovate. They drive our economy. They offer products in an agile manner.
I love cloud computing. It’s convenient. It’s flexible. It makes things affordable that once were cost prohibitive.
Doing business with anyone carries risk, and some may feel that doing business with small businesses carries greater risk. But we do it anyway because we like the product or service that is offered.
One such small business that I have done business with is CodeSpaces. They were a startup that provided cloud-hosted Source code control such as Subversion and Git. They had a continually improving project management dashboard oriented around agile methodologies. They were affordable, with plans as low as $2/month.
When I started HomeSpot HQ, I had a laptop. I did most of my development on that laptop, but knew I needed a place for source code control. Being familiar with Subversion, and being in need of a free or low cost solution, I researched and found CodeSpaces. Upon registering for an account, I pushed my source files in to the cloud, ready to access them anywhere.
CodeSpaces announced yesterday that their service had been breached by an unauthorized attacker, and that a good portion of the code, project information, and other customer data that had been willingly pushed to the cloud by their customers had been irreversibly destroyed.
CodeSpaces issued this statement about the incident:
Code Spaces will not be able to operate beyond this point, the cost of resolving this issue to date and the expected cost of refunding customers who have been left without the service they paid for will put Code Spaces in a irreversible position both financially and in terms of on going credibility.
As such at this point in time we have no alternative but to cease trading and concentrate on supporting our affected customers in exporting any remaining data they have left with us.
Thankfully for myself and for HomeSpot HQ, I had moved off of using CodeSpaces for my ongoing source control solution. But had I not, then not only was CodeSpaces’ business compromised, but quite possibly mine would have been as well.
I frequently receive emails from new HomeSpot HQ users that read something like this. “I really love your product and am excited to use it. However, what happens to my data if you disappear as a business? Is there a way to export or extract it?”
These users are rightfully being proactive in considering the safety and trustworthiness of the cloud. They recognize the value of the data they would provide, and the value of the time required to provide it. They want assurances that their effort will not be wasted because we close up shop overnight.
CodeSpaces is the victim of a crime. They indicate in their full statement that they have withstood previous attacks without incident. It is unfortunate that this crime leaves the company in a state where their only option is to close.
This story (and many like it) illustrate the risk we take when using hosted services. It forces me as the provider of such a service to redouble my efforts to keep my customer’s data secure. This is the world we live in.
One of the promising new features in SharePoint 2013 is the Minimal Download Strategy, which allows pages in non-publishing sites to be rendered using AJAX callbacks rather than full round trips and page refreshes. When it works, it provides a very seamless user experience, with only the essential portions of the page being changed.
However, when MDS fails, there is not much to go on. You will get some basic entries in the ULS log, but I found them to be just vague enough to not be helpful.
One such message is as follows:
MDSLog: MDSFailover: Master page mismatch occurred in MDS: Context Page MP (currentMPToken) = ['|WORKGROUPS|TEST:|WORKGROUPS|TEST|_CATALOGS|MASTERPAGE|SEATTLE.MASTER:2.15.0.0.0.15.0.4481.1005.2.FALSE.:en-US:en-US:RW'], MP supplied by page in URL (originalMPToken) = ['|WORKGROUPS|TEST:|_LAYOUTS|15|SEATTLE.MASTER:0.15.0.0.0.15.0.4481.1005.2.FALSE.:en-US:en-US:RW'], Current Request URL = ['https://domain.com/workgroups/test/SitePages/Home.aspx?AjaxDelta=1&isStartPlt1=1392132082249']
A bit of context for how MDS works. In order to be able to partially load a content page, certain elements of both the referring and destination page must be the same, namely the master page. If the two pages are determined to have different master pages, then SharePoint must force a full page load. The examination of the pages occurs on the /_layouts/15/start.aspx page, which is an intermediary page that is loaded as a url is followed.
If MDS fails, the start.aspx page will then do a full redirect to the destination url. The net effect of this failover however is a longer than normal page load since there are several redirects occuring.
In my case, however, this didn’t make sense. I was on a brand new Team site, and had made no master page changes. So why was MDS reporting a mismatch?
After hours of inspecting the page load sequences in Firebug and Fiddler, a curious observation came to light. MDS was working fine on pages that were in the _layouts folder, such as Site Settings and All Site Content. It was only pages in the main site that were failing.
It reminded me that in Central Administration, in the General Settings for a Web Application, there is a selection to indicate if pages in the _layouts are use the Site master page or not.
I found that if this property is set to No, the content page will render using _catalogs/masterpage/seattle.master location while the _layouts pages (including start.aspx) will render using _layouts/seattle.master. As best as I can tell, the MDS check is looking at the start.aspx master page rather than the actual destination page’s master page to make its comparison. While the content of these pages may be identical, since the paths are different, MDS fails over and issues the full redirect to the target url.
On a new web application, this setting defaults to Yes, so you may only experience this behavior if you have changed it.
I found very little about the MDSFailover online so I hope this helps the community.
This hour-long course is an in-depth look at using the Bootstrap responsive framework in SharePoint 2010 publishing sites. It was a lot of fun to create, and will hopefully be the first of many that I produce.
Earlier this month, I wrote about how it’s inevitable that you’re going to be distracted during the course of your workday. Today I’m adding a second installation to the “You’re going to…” series by assuring you that You’re going to fall behind.
What I mean by this is that as a developer, there will always be things you can’t keep up on. Be that a new language, framework, toolkit, backlog of features, unit test coverage, or even documentation. There simply has become too much to learn, too much to consume, too much to monitor, for any normal person with a day job to manage. And that is okay.
Back in the day
When I started software development in the late 1990’s, there really were fewer options for how you did your work. It really came down to a few languages, and those mostly supported by Microsoft, namely FoxPro, Visual Basic, and C++. Even Java, released in 1995, was only beginning to garner some momentum. Consequently, there were finite choices, and seemingly finite amounts of reference material to consume. These are the days when not only would you get 25 3.5 inch floppy disks to install the product, you’d get 3 or 4 printed volumes as instructional guides. If you were lucky enough, as I was, to have an employer who would spring for the CD-ROM based MSDN library subscription, then your reference base grew a bit more, especially with each quarterly release.
But in the end, if I had a problem I couldn’t solve, the standard solution was at the other end of the Microsoft Support telephone number. I have many memories of sitting on hold waiting for a support representative to pick up so I could ask a single question.
The release cycles for new products in the late 90’s and early 2000’s were long. And the infancy of the Internet at that stage meant that only so many new products or technologies became available each year. I dare say it was manageable, and if you paid attention, you could reasonably stay current with the latest and greatest.
The Internet changed everything
In my view, the Internet has had two significant impacts on the field of software development. The first is the amount of content available related to any given programming language, or in fact any given specific issue. The second is the acceleration of new technology being released for developers to leverage.
To illustrate the former point, do a simple Google search for your programming language of choice. The results may surprise you.
21 million results. 21 million pages that all may have something relevant to the problem you are trying to solve. It’s no wonder we feel overwhelmed.
How to keep up
Just as you would if you found yourself falling behind the pack in a footrace, keeping up with the industry requires that you dig deep in to your core and put all you have towards closing the gap. Here are some things I have found useful.
1. Plan to give a talk
One of the most effective ways I have found to embark on learning a new technology or method is to commit myself to giving a presentation about that topic. This can be at a user group, a code camp, or even just as a lunch-and-learn with your team. The risk of embarrassment in front of your peers is a giant motivator, and a deadline can help you prioritize and structure your learning.
2. Optimize your online consumption
With the glut of material out on the Internet, how possibly do you filter though the volume and get to the best resources. One method I use is to always start with what I call my trusted sources. These are individuals like Scott Hanselman, K. Scott Allen, and Randy Drisgill, who have an established reputation as reliable authors. The next tier is material from the producers of the technology themselves. Everything from Microsoft down to the discussion threads on CodePlex, if it’s directly tied to the people creating the technology, chances are you’ll get better quality information. Finally, expand to the general tech blogosphere. Every developer has their own application and experience with a language or tool, and that broad base will give you lots of insight as to what is good, bad, and ugly about the product.
3. Online video and Podcasts
In the last few years there has been a downright explosion of online video training materials available online. Free sites like DimeCasts; paid sites like WintellectNow and Pluralsight; and of course, lots of user-sourced material on YouTube. The genre of tech-focused online screencasts is maturing rapidly and gaining not just popularity, but quality. Similarly, chances are there are dozens of individual podcasts available oriented around the topic du jour. Online training and podcasts are great because they can be portable as well as passive. You can listen to a podcast while on the treadmill, or watch a video while traveling. These are great tools to help you incrementally grow in knowledge.
4. Start a side project
If you are like me, and I think most developers, you learn best by doing. So if your main job doesn’t afford you the opportunity to explore and apply new technology, create your own project that does. I started HomeSpotHQ.com in 2009, and it became the venue in which I learned MVC. Setting off to create a product, whether or not you make it public, is a great form of focused learning. If you’re particularly motivated, you can follow in Jennifer Dewalt’s footsteps and do 180 websites in 180 days, each implementing a specific method or tool. The point is to not just read and watch, but do.
Long journey, first steps
I think being a developer forces you to be a lifelong learner. There’s no other way to stay competitive and relevant in the marketplace. So when you find yourself worrying or frustrated because you learn about yet another JavaScript framework that released, remember that we’re all in the same boat. Pick up an oar, set a target, and get to work.
This weekend I had the distinct privilege of speaking at Raleigh Code Camp. This was a great day of technical sessions, meeting new people from the local .NET development community, and presenting. I want to thank all the planners and volunteers from TriNUG who put on an awesome day.
Here is a video of my presentation about using PhoneGap and Asp.Net WebApi to build data-driven mobile apps.
A few weeks ago I took my six year old daughter to a Scratch workshop at our local public library. I had heard about Scratch, but had not really seen it in action, and was very curious to see how my kid would take to it.
The workshop leader gave a very brief intro to the platform and did a simple sample program to get us started. He also had printed out the learning cards from the Scratch website, which give various samples and the specific code blocks to use to complete them.
By the end of the hour, we had implemented and adapted the program from one of the tutorials to make a picture of a cat chase a picture of a fish, and play a ‘meow’ sound whenever it ‘caught’ it. My daughter had a lot of fun, and now has added ‘can I play Scratch’ to her list of tech related requests, after 1. Can I watch a movie? and 2. Can I play on the iPad?
For those who may not be familiar with it, Scratch is a project from the MIT media lab. There is a great TED talk about its origins. The user interface is at the same time kid friendly and sophisticated.
Programming in Scratch involves selecting a sprite and assembling a list of commands by dragging-and-dropping them on to a program canvas. The commands are color coded, and snap together Lego-style. You can have multiple sprites, and all the basic programming constructs are there, including conditions, loops, variables, events, and properties.
While Scratch is one of a growing number of platforms intended to introduce children to programming, it makes me wonder if it is the future of programming. Given that a whole generation of kids may grow up using Scratch, and consequently think that programming is a drag-and-drop, snap-together experience, I wonder if they will be disappointed to know that in real life, programming is a lot of typing.
I have a lot of respect and admiration of Andrew Hunt and David Thomas, authors of The Pragmatic Programmer. One of their tips is simply “Write Code That Writes Code”. They liken code-generators to templates and jigs used by woodworkers to use for repeated tasks. In some regard, Scratch is a code generator, in fact, quite a dynamic one. The click-together code blocks abstract out the core usage into a simple UI based entity, suitable for even a 6 year old to comprehend.
As a professional developer, I have always had a love-hate relationship with code generation tools. Part of me is a purist, wanting to write and own my own code, line by line. Part of me sees the HTML generated by Microsoft Word and wants to throw up. I have always held that writing code and gaining the experience and understanding of what is really going on is more valuable than just getting something generated quickly. But would I be happier to be able to quit typing line after line and instead drag-and-drop blocks on to the canvas? Would I feel in control enough of the output to appreciate the simplicity and convenience that the canvas offers?
A more tangible analog to Scratch in the physical world are SnapCircuits. This ingenious kit allows kids to design and assemble electronic circuits and systems using snap-together components that conduct electricity through the contact points. There are switches, batteries, lights, bells, capacitors, and resistors. Using a underlying grid, you simply assemble the circuit by placing and connecting the individual parts. All the realities of electronics are there, just in a kid-friendly mode. Ohm’s law holds true for SnapCircuits just as it would any other electrical system.
But would you wire a house using SnapCircuits? Would we want to, given the chance? Wrapping wires around screws has worked for decades, right? Are these ‘snap-together’ systems only suitable for children?
If a system or new code-writing methodology would let me as a developer build systems faster, then there certainly is value to that. But are we too ‘mature’ to consider ‘kid-friendly’ methods as the way to achieve those gains? Perhaps my daughter’s generation will demand that shift, and they’ll have the bright minds at MIT who created Scratch to thank for it.
Recently, a fair amount of media attention has been directed at the idea of standing instead of sitting while one works. There are reports showing that sitting kills, and a variety of options for adjustable tables or desktop stands have hit the market.
As a developer who does in fact, work at a desk for the better part of 8 hours a day, I can attest that working while standing does allow me to feel more alert and focused while I work.
So I set off to design and build a sit-or-stand platform for my home office.
Since the file cabinet and desktop setup I constructed for my home office is shared between my wife and I, a free standing desk wasn’t an option. Rather, I needed something that could sit on top of my existing desk, but rise up to standing height when I preferred to work while standing. Since I have both a laptop and additional monitors, a product like the the Furinno laptop stand wasn’t viable, due to its size.
Furinno laptop stand
The next step up is to products like the Kangaroo from Ergotron or the Workfit S by Ergotron. These run between $300 and $600. There are models to support single or dual monitors, or laptop plus monitor in the case of the Kangaroo (shown below). However, the cost of these products was too high for me to justify, and their cubicle style appearance just wasn’t going to have a high enough Wife Acceptance Factor.
Kangaroo Hybrid by Ergo DesktopWorkfit-S by Ergotron
The next option that I found was the Varidesk. It is a freestanding unit that sits on the desktop, with a simple adjustable rise of about 15 inches. But at $300 it was still beyond my budget. Still, the Varidesk inspired my design in its simplicity and mechanics.
Design Criteria
Have a maximum footprint of less than 23 inches (the depth of my desktop)
Have a rise of approximately 12 inches, which would put the platform at about 42 inches in standing mode.
Allow enough space on the desktop to just open the laptop for quick usage.
Avoid permanently attaching or drilling in to the desktop.
Utilize as much scrap lumber and various hardware in the garage as possible.
My design would consist of a simple base, a primary platform for my monitor and laptop, with a slide out keyboard tray. I had decent lengths of 1×12 and 1×10 left over from my last project, so I chose them to be the platform and tray. For the base, I would use 1×4 stock, and rip down 1×2 lengths for the supports under the platform.
My primary concern was for strength and stability, so I chose to purchase a 3/4″ x 3/4″ square aluminum tube for my supports. This one item was about $12 for a 4 foot length, and represented the bulk of the project’s cost. Steel tube would have been less expensive, and 3/4″ electrical conduit, while round not square, would have been the least expensive option. I preferred the aluminum finish overall and decided to splurge.
For hardware, I used 3/8″ diameter bolts that were 2 1/2″ long. I ended up getting ones that were partially threaded, which turned out to be perfect so the supports aren’t rotating along the threads.
I needed 8 bolts, 8 nuts, and 32 washers. The cost of this hardware was about $10.
I found 12″ deep drawer slides in my garage from a previous project, but if I had to purchase these, they would be $4 or $5.
Construction
After cutting the 1×4 to 18″ lengths for the base, I then ripped down another plank to a true 2″ width. I cut four pieces at 11 7/8″ to go under the platform.
Geometry proved to be the biggest challenge of this project. I knew I wanted the platform to be flush along the back edge, and rotate up to be flush along the front edge, only 12 inches higher.
I first attempted to model this in Google Sketchup, which proved to be a big time sink. While it’s easy to model the boards, getting the rotation arc was hard to do (for me at least).
With my actual pieces in place, I decided to just try to mock it up with some thin strips of wood and tacks. My goal was to get the proper length of the vertical supports, and the proper offset for the pivot points in both the base and upper supports. Here’s a picture of my prototype:
After getting what I thought were suitable points, I needed to drill the holes for the bolts and countersinks for the washers. Using a drill press, I first did a 1″ for the countersink about 1/4″ deep. Then I flipped the piece over and did a 3/8″ hole from the other side (to prevent tear-out). I did this for all 8 pieces.
CAUTION: You’ll have to make sure to pair the pieces together and measure from the left on one and the right on the other so the holes match up.
Before committing to cut the aluminum tube, I first used 3/4 x 3/4 wood rods to make sure I got all my measurements correct. It’s a good thing I did, because in fact, I had miscalculated ever so slightly the placement of one of the holes. Consequently, my rotation was off, resulting in the platform not laying flat against the base.
In re-evaluating the measurements, it became clear that I needed both sets of holes to be the same distance apart. There is a form where by the spacing can be narrower on one side, provided that one diameter is longer than the other (a car jack has this arrangement.) But in my case, equal spacing was the trick to keep the vertical supports parallel all along their rotation. On the 2nd pass, the alignment came out much cleaner.
I then cut the aluminum rod using a hacksaw, and carefully drilled 3/8″ holes in each end.
My total width of the platform would be 32″, and the keyboard tray would be 25″. I cut these to length, then used a Kreg pocket hole jig to drill through the upper supports in order to mount them to the platform. Again, I paired the supports so all the pocket holes would be concealed.
Finally, I put a back support across the base to add stability and rigidity, and caps on the front for a clean look.
Stop Blocks and Pins
In order to prevent the platform from rotating all the way forward, I put stop blocks in the base at its maximum height.
To lock the platform in place, I found some surplus Allen keys from some piece of IKEA furniture we’d assembled. I drilled a hole through the base behind each of the rear supports, so that I can insert the pin to hold it in place. (If you wanted to have multiple height settings, you could have several pin locations along the rotation.)
Finally I installed the drawer slides and attached the keyboard tray, and gave the entire unit a coat of paint.
Do you like this design but aren’t interested in building your own? I’m taking orders for pre-made Standing Desks that I’ll build and ship to you. Check out www.freestander.us to learn more and place an order.
Installation
In order to prevent the unit from sliding when I would lift up the platform, I attached two adjustable L-brackets to the base so I could ‘hook’ the unit to the desktop and clamp it down. I used wing-nuts to make it easier to secure when near the wall.
My monitor mount attached nicely to the platform, and gives me plenty of room for either my 13″ Macbook Pro, or 15″ HP laptops. I also added some cable retainers to keep various cables close at hand.
Standing positionSitting position
This project took me two weekends, one for construction and one for painting, but I am totally pleased with the result. I may end up building a second one for my office at work.
UPDATE: Many people have asked for a video showing the operation of the desk, so I have put that together below.
One of the less promoted new HomeSpot features we added this year was a way for a user to cancel their account. I debated adding this option at all. While I wanted to believe that every person who signed up for HomeSpot would love it as much as I do, I didn’t want to be the site that locked you in unwillingly to something that just wasn’t for you.
For the first four years since HomeSpot released, if a user wanted to cancel their membership, we asked them to email our Support desk or submit the request through our Feedback form. In our support pages, we had a simple FAQ entry to help guide the user:
The hope was that if we had a more specific cancellation request form, we could get better feedback about how our product wasn’t meeting people’s expectations. So first, in the My Account page, we added a Cancel Account button.
This linked to a new page where we solicited the reason for why someone wanted to cancel their account.
And then we created what we thought were legitimate reasons a user may have, each one asking them to provide us some feedback in the comments field.
Since deploying this feature, we’ve had about 50 users cancel using this form. And I’ve learned that you have to be careful what you ask for. Feedback from users can illuminate opportunities; it also can sting a bit.
Here’s a breakdown of the reasons provided from those who have canceled their accounts.
Less than half of the users actually provided any additional comments. I chose not to make this field required, out of courtesy to departing users. So while they may have selected Lack of Features, they weren’t willing to tell us what they wanted, so I can’t help them.
Another set of responses I found interesting were those who complained about a missing feature that is actually in the product, meaning they couldn’t find the feature, or simply misunderstood it. For example, one user wrote
Works better if I do it myself on Google calendar instead of setting up a separate account.
HomeSpot has the ability to publish your home’s maintenance schedule to a Google calendar, which could have assisted this user. Another case was a comment that read
Option to delete reminders that don’t apply to my home. I don’t need to clean a garbage disposal since I don’t have one.
In this case, they must not have realized that the Delete this item button is shown when you actually view the item (rather than showing on the list view).
Most disappointing were the various forms of the comment “I don’t use it.” or “doesn’t meet my needs.” These are informative to the degree that any improvements we can make to foster user engagement will help draw users back to the product. Still, sometimes the truth hurts.
Improving User Feedback
There are lots of ways we may continue to try to get feedback from our users. One simple step will be to put links to our feedback and support pages on the Cancellation page, which may help answer some of the feature related questions or complaints.
Another approach may be to add a user forum component to our product, whereby users can post questions and get feedback from other users or our Support team directly. This approach would help make visible the questions and complaints from the user base and provide our responses to be globally available to all users.
With HomeSpot, we have always tried to listen first, then act, whether it is when adding premium features or updating our list of home maintenance tasks. Our users think of things that often never occur to us. But we’ll never know these ideas if we can’t effectively ask for and capture their input. And reviewing and adapting to those responses is critical to our ability to stay competitive.
So yes, asking for user feedback is worth it. You may be surprised at what you get.
In my presentation, I demonstrated how to incorporate the Bootstrap web application framework in to SharePoint master pages and page layouts in order to deliver a responsive browsing experience.
(Note: Unfortunately, when I switched from slides to the demo, and switched the display on my laptop from ‘Extend’ mode to ‘Duplicate’ mode, SnagIt didn’t pick up on the transition and the demo portion did not get recorded properly. Thankfully the code can be seen in the video up on the projection screen. If anyone has specific questions or wants code samples, just add a comment for this post or send me a tweet.)
We recently updated a SharePoint branding solution to have a custom content type which included Managed Metadata fields.
When I attempted to deploy this solution to my development farm, however, I got this error when trying to Activate the feature:
Count not find the taxonomy group Parameter name: name Actual value was Global.
The cause was that I had not set up the Managed Metadata term store yet with the term hierarchy referenced in the custom content type. Once I created the Group and Term Sets to match our production environment, the deployment and activation succeeded.