Close Call

Time for a change. No developers slang or pics of mobile phones, it’s time to take a look behind the scenes at the systems which make These Days people able to work and do their stuff.

At These Days, it’s pretty simple. I’ve installed a NetApp SAN (FAS 2050c) about 2 years ago. It’s a clustered box which contains all fileserver data (the normal network drives which almost every digital company has and where employees save all their documents and work-related files) and it also contains all data from our VMware virtual infrastructure environment. The latest is a 25-30 virtual server clustered farm, These Days is completely virtualized and thus heavily dependent on the NetApp SAN/Virtual Infrastructure.

So basically, if the NetApp box goes down, we’re in big trouble. No fileserver nor access to servers anymore (development, finance, planning, …) and 80 people who are unable to work. You don’t even want to know how much that would cost for an office. Imagine 80 people completely unable to work! Time is money right?

But the NetApp SAN doesn’t go down. It’s made and designed for that. You boot it up once and you never turn it off or reboot it. It doesn’t require patches or updates. OK, you’ve got the occasional firmware updates but they can be done online with a 40sec Disk I/O interrupt. So yeah, that’s not bad. It’s even clustered, 2 controllers in an active/active mode, so IF something went wrong and one of the controllers died, the other one would take over and keep everything running.

It’s a box which stays online, 24×7.

Unless… you get a power outage like we did last week. It happened between 4-5 AM. The UPS (emergency battery power) kicked in and gave me 40 minutes to restore power or shut everything down. But I didn’t wake up from those text alert messages at 5AM! So UPS time went down while I was sleeping and dreaming of hot chicks ICT Business Continuity. Eventually the whole server room was without power and everything went down.

When I woke up, I saw the text messages and said (more like screamed) something along the lines of “EEK!” and “F*CK”. Phone calls from the early birds in the office were already coming in saying there was no power and after the fastest bike ride ever to the office, I booted up everything and got the whole thing up and running again in 15mins.

Now the cool thing about this experience kicks in. The same day, in the afternoon, I noticed something was wrong with one of the NetApp controllers. LEDs weren’t on/flashing, no network activity, nothing, completely nothing. I checked the box and noticed a failover happened and one controller was handling all traffic and took over all tasks from the other controller.

I was shocked and happy at the same time. Shocked as in: one of the controllers didn’t boot up and happy as in: cool, we’ve been running on one controller for a whole day and no one noticed a thing! All iSCSI and CIFS connections stayed up with no problems.
After some testing, I declared the faulty controller dead and called support to bring me a new one. It probably died from a voltage spike when restoring power.

The next day, I received a brand new controller and replaced the dead one. Another cool thing about NetApp controllers: all OS and config data is stored on the compact flash. So placing the flash card from the old controller in the new one restores all configs on the new controller. The only thing that needs to be done manually is reassign the disks to the new system ID, which takes about… 3 seconds.

The point of this post is to show how important it is to have redundancy on your business critical systems. What if our NetApp box wasn’t clustered? These Days would have been down for an entire day and lost large amounts of money, it’s the nightmare of every IT Manager. Sometimes we need to invest in these complex solutions to guarantee business continuity and in a situation like this, it pays off. Big time.

ROI on the NetApp? Ha, yeah, we reached it and even went completely over it :-)

10 tips for designing mobile websites

10 tips for web designers in 2010 – the year of the mobile.

1. Design with a fluid layout, min-width: 320px

There are two factors that make this a necessity. First, mobile device screens are so small that you really need to utilise all of the available space. Second, there are a lot of different screen resolutions out there. The only way to utilise all of the space available on different sized screens is with a fluid layout.

I have found websites with a minimum width of 320px will look good on most high-end mobile devices like the iPhone, Android and Nokia N97. Here are the screen resolutions of some of the most popular devices:

Device Screen res (height x width)
iPhone 320 x 480
iPhone 4 320 x 480 (scaled by a factor of 2)
Nokia N97 360 x 640
HTC Legend 320 x 480
LG eXpo 480 x 800


Technically, the retina display on the iPhone 4 has a screen resolution of 640 x 960 pixels but don’t worry, if you optimise your site for 320 x 480, the iPhone 4 will scale it up by a factor of two so it fits the whole screen. You will need to insert higher resolution images – but more on that in the next section!

2. Include high res images for the iPhone 4 retina display

The iPhone 4 display has four times the number of pixels as that of the original iPhone. To prevent mobile sites from looking tiny, it magnifies them by 200%. That works great on text and vector images like SVG. But its not so hot on bitmap images (or even the HTML5 canvas so it would seem). To avoid pixelation, you need to insert alternative high resolution images for the iPhone 4.

Designers should create their Photoshop documents with a width of 640 pixels. Developers should export the images at full res for iPhone 4 and 50% res for everything else.

Here’s how to use a CSS media query to insert a high resolution image for iPhone 4:

.myImage {
    height: 40px;
    width: 100px;
    -webkit-background-size: 100px 40px;
    background: url("images/myImage.jpg");
}

@media screen and (-webkit-device-pixel-ratio: 2) {
    .myImage {
        background: url("images/myImage@2x.jpg");
    }
}

The first line that might jump out at you as being a little unusual is probably -webkit-background-size: 100px 40px;. The -webkit-background-size CSS property takes two parameters: width and height. The parameters can be lengths, percentages or "auto", and can even be mixed, i.e. -webkit-background-size: 100% auto. This tells the browser to stretch the background image to a specific size.

The second interesting part is the media query @media screen and (-webkit-device-pixel-ratio: 2) {...}. This means that any styles contained within the curly braces only apply if the device has a pixel ratio of 2 (two physical pixels per measurement pixel). Inside the media query selector, we override the .myImage class, and replace the background image with the high resolution image myImage@2x.jpg.

The left half of this screenshot shows the pixelation that occurs on iPhone 4, and the right half shows how it looks when we insert with a high resolution image:

The left half of this screenshot shows the pixelation that occurs on iPhone 4, and the right half shows how it looks when we insert with a high resolution image

3. Turn off auto-scaling

Mobile devices will assume your website is optimised for desktop computers unless you tell them otherwise. Add a viewport meta tag to the head section of your HTML to set the width of your website to match the width of the display, render with a zoom level of 100% and prevent the user from zooming in/out.

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

Mobile phones will also adjust text size when the screen orientation changes unless you include a special CSS parameter:

body {
    -webkit-text-size-adjust: none;
}

4. Make clickable elements big enough for a fingertip, ≈44px²

Your mobile visitors don’t have the accuracy of a mouse – they are often using their fingertips on a touch screen. Don’t make them put their fingers through a pencil sharpener just to click your button! Apple has said that the average finger tap on an iPhone is 44px by 44px (in your high res Photoshop doc that will be 88px by 88px), so aim to make clickable areas at least that size. This doesn’t mean you have to design gigantic looking buttons. Just add some padding to your small buttons to enlarge the clickable area.

5. Don’t use hover states

Today’s touch screens can’t detect when a finger is getting close to touching, so the concept of rollovers does not apply. On the iPhone your :hover style will actually display on click and then remain on screen even after the user takes their finger away, which can be really annoying. So the rule is – don’t use :hover in your CSS or mouseover in your JavaScript.

6. Create icons for your site

Hopefully users will really love your site and add it to their home screen for easy access. Don’t ruin the mood with an ugly default icon! Add these meta tags to the head section of your HTML to define icons.

<!-- 57 x 57 Android and iPhone 3 icon -->
<link rel="apple-touch-icon" media="screen and (resolution: 163dpi)" href="icon57x57.png" />
<!-- 114 x 114 iPhone 4 icon -->
<link rel="apple-touch-icon" media="screen and (resolution: 326dpi)" href="icon57.png" />
<!-- 57 x 57 Nokia icon -->
<link rel="shortcut icon" href="icon57x57.png" />

Note: The iPhone will automatically add rounded corners and a glossy effect to your icon. If you want to turn this off, change the rel attribute to apple-touch-icon-precomposed. Thanks to Jesse Dodds for discovering how to specify a seperate high res icon for the iPhone 4 retina display.

7. Reduce load time by using CSS3 instead of images for gradients, rounded corners, shadows, etc.

Depending on the devices you are targeting, CSS3 can be an excellent option for mobile design. With old school web design techniques, a button with a gradient and rounded corners might consist of 9 separate image slices, a bunch of nasty non-semantic markup and a hefty amount of CSS. With CSS3, you can create this:

CSS3 button

With this:

.redButton {
    color: #B91440;
    font-size: 19px;
    line-height: 25px;
    padding: 10px 30px;
    border: 1px solid #FFFFFF;
    background: -webkit-gradient(linear, left top, left bottom, from(#F2F2F2), to(#FFFFFF));
    -webkit-box-shadow: 0 0 2px #E4E3E3;
    -webkit-border-radius: 5px;
}

Go here for everything you need to know about CSS3.

But be careful! While the iPhone, Android and Nokia all have good CSS3 support, the Windows Mobile 6.5 browser is built on a version of IE6 (sigh…). Define, define, define your target devices before you begin design and development.

8. Use an HTML5 doctype

Not all browsers implement HTML5 features, but they will still accept an HTML5 doctype.

<!DOCTYPE html>

Using this doctype declaration will allow you to display HTML4 elements to all browsers, and then add in additional functionality for the browsers that support HTML5.

9. Make your site operate offline

Your visitors won’t always have a fast Internet connection. If you’re designing the type of site that will have return visitors, consider leveraging the client-side storage capabilities of HTML5. It can be as simple as creating a cache manifest file that tells the browser what files it needs to cache for offline access. A more advanced option is to create an SQLite database on the client with JavaScript.

10. Include an option for your mobile visitors to view the normal website

Detection scripts can get it wrong, or a user might simply prefer not to use the mobile optimised interface. So my final tip is, always offer users a way to switch back to ‘normal mode’.

So there’s a few mobile web tips I’ve picked up over the last few months. I’d love to hear yours too in the comments!

Logging in – a barrier to application uptake?

An analysis of the Facebook “Request for Permission” dialogue as a barrier to application uptake.

I have always wondered how much of a barrier the “Request for Permission” dialogue presents to uptake of Facebook applications. So two months ago I set up a simple one-page app to gather some statistics about user behavior.

My sample group consisted of 4000 unique visitors who spoke English, Dutch, Spanish or Portugese. Visitors came from 82 countries but the largest groups were from Portugal, Belgium, the Netherlands and Argentina.

The idea of the application was very simple. Users were asked to enter their birthday with one of two input methods, either (a) through a series of dropdown boxes or (b) with a button that gave the app access to the birthday on their Facebook profile. The app then calculated how many days, weeks and months the person had been alive for and allowed them to post the result to their Facebook profile.

This is what the input screen looked like:
Your Age in Days input screen

And the resulting profile story:

Your Age in Days result

So what were the results? For whatever reason, 96% of users chose method a – the dropdown boxes. That’s a pretty significant majority, but it doesn’t tell us why users chose this option. They probably had different reasons, but I think some would have been:

  • “The dropdown boxes look quicker and/or easier”
  • “I don’t want to give this application access to my personal information”
  • “I don’t know what will happen if I click the Facebook button”

Personally, I can understand people not wanting to grant the application permission to access their information. Even the lowest level of authorization gives an app access to the user’s name, profile picture, list of friends and other “public” parts of their profile.

Facebook permissions dialogue

Much of the time when we develop Facebook apps we can’t avoid asking users for authorization. But we need to be aware of the barrier this creates. We should delay the authorization request in our application flow until the point where we really need it. And hopefully by that time the user will be able to see the value of authorizing our app.

Dependency injection with Spring.NET

Hands-on introduction on how to configure dependency injection using Spring.NET

In a previous post I’ve discussed a simple n-tier approach using a Facade and Dao pattern. The Facade provides a single access point for the business tier, and wraps a data access object that encapsulates the implementation of the persistence mechanism, separating the concerns.

I also mentioned that these objects introduce a large dependency (high coupling) as the Facade does not function without the Dao. I will now show you how this dependency can be overcome, by injecting the Dao into the Facade using the Spring.NET framework.

In the following example we will create a simple web management tool for a Zoo (inspired by amazedsaint). The tool needs to list all animals and caretakers, and allow the manager to rename animals or to assign one or more caretakers to an animal.

We start out by creating the business entities:


public class Caretaker

{

public string Name { get; set; }

public int Age { get; set; }

}

public abstract class Animal

{

public string Name { get; set; }

public IList<Caretaker> Caretakers { get; set; }

}

public class Lion : Animal { }

public class Elephant : Animal { }

We will also create a Facade which allows consumers to have a good understanding of the class library without having to worry about the exact implementation. Therefore, a good practice is to set up an interface:


public interface IZooManagement

{

IList<Animal> GetAllAnimals();

IList<Caretaker> GetAllCaretakers();

void RenameAnimal(Animal a, string newName);

void AssignCaretaker(Animal a, Caretaker c);

}

This should cover all requirements. The animals and caretakers will be stored in some kind of data store, so we’ll create a data access object (Dao) that will handle this for us. We haven’t decided on which type of data store or which ORM to use, so for now, let’s not worry about its implementation and create the interface:


public interface IZooDao

{

IList<Animal> GetAllAnimals();

IList<Caretaker> GetAllCaretakers();

void UpdateAnimal(Animal a);

}

Ok, now let’s implement the Facade. For the sake of simplicity, I will leave out any validation or error handling. Eventually, the minimal implementation will look much like this:


public class ZooManagement : IZooManagement

{

private IZooDao dao;

public virtual IZooDao Dao

{

set { dao = value; }

}

public IList<Caretaker> GetAllCaretakers()

{

return dao.GetAllCaretakers();

}

public IList<Animal> GetAllAnimals()

{

return dao.GetAllAnimals();

}

public void RenameAnimal(Animal a, string newName)

{

a.Name = newName;

dao.UpdateAnimal(a);

}

public void AssignCaretaker(Animal a, Caretaker c)

{

a.Caretakers.Add(c);

dao.UpdateAnimal(a);

}

}

The persistence mechanism has now completely been abstracted from the Facade. Also notice that the Facade does not instantiate a Dao: the property allows us to “inject” the Dao implementation and completely remove the dependency (this can also be done using a constructor parameter).

We now need to find a good way to inject the Dao into the Facade, and this is where the Spring.NET framework provides additional support, as one of its many features allows you to set up dependency injection through configuration.

Before we configure the dependency injection, let us create a “dummy” Dao, one that does not really access a data store, but holds a list of animals and caretakers internally:


public class DummyDao : IZooDao

{

private IList<Animal> animals;

private IList<Caretaker> caretakers;

public DummyDao()

{

animals = new List<Animal>();

animals.Add(new Lion() { Name = "Simba" });

caretakers = new List<Caretaker>();

caretakers.Add(new Caretaker() { Name = "Leo", Age = 25 });

}

public IList<Animal> GetAllAnimals()

{

return animals;

}

public IList<Caretaker> GetAllCaretakers()

{

return caretakers;

}

public void UpdateAnimal(Animal a)

{

throw new NotImplementedException();

}

}

If you want to use the Spring.NET framework, you will first need to add a reference to your web project. The latest version can be downloaded here. Next, you’ll need to configure Spring.NET in the Web.config:


<sectionGroup name="spring">

<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>

<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>

<sectionGroup name="child">

<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>

</sectionGroup>

</sectionGroup>

<spring>

<context name="ParentContext">

<resource uri="config://spring/objects"/>

</context>

<objects xmlns="http://www.springframework.net">

<object id="ZooDao" name="ZooDao" type="TheseDays.Business.DAL.DummyDao, TheseDays.Business">

</object>

<object id="ZooManagement" name="ZooManagement" type="TheseDays.Business.ZooManagement, TheseDays.Business">

<property name="Dao">

<ref local="ZooDao"/>

</property>

</object>

</objects>

</spring>

The first part is standard and announces the Spring.NET configuration. The second part is where the magic happens: the spring/context section is necessary for Spring to create its application context, and the spring/objects section allows you to configure the resources.

The object configuration is pretty straightforward: we tell Spring.NET we want to create an object of type ZooManagement (our Facade) and to set its property with an object we also configured, an object of type DummyDao.

Once we have implemented an actual Dao (rather than a dummy one), in order to start using it all we need to do is reconfigure its type. For example, if we would create a RealDao that also implements the IZooDao interface, and we need to pass a connection string to the constructor, the configuration of the Dao would look like this:


<object id="Dao" name="Dao" type="TheseDays.Business.DAL.RealDao, TheseDays.Business">

<constructor-arg name="connectionString">

<value>Server=.;Initial Catalog=Zoo;User=ZooUsr;Password=ZooPwd;Application</value>

</constructor-arg>

</object>

In the web application we can then access the ZooManagement Facade through the Spring’s application context. Here’s a demonstration of a small helper class I often use:


public class ApplicationContextHolder

{

private static ApplicationContextHolder instance = new ApplicationContextHolder();

public static ApplicationContextHolder Instance

{

get { return instance; }

}

private IApplicationContext applicationContext;

private IZooManagement zoo;

private ApplicationContextHolder()

{

applicationContext = ConfigurationManager.GetSection("spring/context") as IApplicationContext;

zoo = applicationContext.GetObject("ZooManagement", typeof(ZooManagement)) as IZooManagement;

}

public IApplicationContext ApplicationContext

{

get { return applicationContext; }

}

public IZooManagement Zoo

{

get { return zoo; }

}

}

Now you can access the ZooManagement in the web pages with a single line of code:


IZooManagement zoo = (ZooManagement)ApplicationContextHolder.Instance.Zoo;

Surely a nice feature when you’re building your own framework!

You can download the full source code of the example here.

Concept blogpost: Future web browsing

Innovation Sam | 23 Apr. 2010 | 10 comments

Concept blog post about how browsing could be more user-friendly in the future.

After reading the ‘goodbye http‘ blog post on thenextweb.com I first thought that it was a crappy idea to change the way of browsing for users… but @donotfold managed to change my mind…

Let me quote one of his emails:

“Everything that is illogical or irrelevant for the end-user should be popped out, it’s a logical next step in the evolution of the internet and web browsers.”

And after reading that I couldn’t agree more. So we started thinking .. how far can we actually take this? For example; I’m a huge fan of the windows7 explorer. Can’t we port this technique to web browsing? There’s bound to be a point where, by over-simplifying things, you will eventually begin to make it more difficult for the end user … the ultimate goal would be to find that tipping point. So let’s try out some ideas, shall we? :)

Our starting point; A regular website made by John Doe with a .com url.

Let’s get rid of the http:// as suggested by google.

And if we can delete the http:// part in URL’s, why not hide the extensions too? No one really cares about whether your site has been made in PHP or ASPX. And why not take this even further and add a breadcrumb system instead of the slashes, you’ll end up with something like this:

You often also have websites that are multilingual (especially in Belgium) so instead of using /nl/, /fr/, /en/ or ?lang=en we can display a flag icon of the current language.

Here’s where the windows7 explorer principle will come in. If we click on the language flag, we can quickly switch between languages, and when we click on the arrow before Home you can select another item in that level from the dropdown.

And now if we take the idea really far … Let’s add the possibility to query your page. Give a selection to show the latest 10 items (where applicable) or show latest 20 items, you can add the possibility to sort those items .. I think you can go quite far with this :)

Control

How would all of this be controlled? Should it be controlled? A possibility would be to use the sitemap.xml as a basis for the breadcrumb system. And then implement a second, language.xml file for the language dropdown. I, personally, would prefer to be in control instead of the browser generating it all for you.  That way, it’s still up to the webmasters if they want to use this function or not.

Conclusion

Would this be an improvement for me? No! For the common user? I believe so. But there’s a point where it will be to difficult, so how far can we really go? How will we handle id’s? Here too, we could choose to just handle this in the background, users don’t necessarily need to be faced with this. But then how do we allow users to share links? We could use a button and convert all links into short links… (http://goo.gl/123) … And I believe we should always have the possibility to switch back to the full path, like the Windows7 explorer does. Suffice it to say that there is a lot to think about and plenty of room for discussion.

Bear in mind that this is a concept … I don’t see any of these suggestions happening any time soon, especially not while browsers are at war with each other and standards aren’t yet where they need to be. Something huge like this should be a unified effort, not a nice-to-have feature in one browser trying to gain on the competitors. So google; nice job starting this! But invite your peers and explain to them the reasons why and the importance for the user.

Join the discussion

As for our little concept, … What do you think? Should everything stay as it is? Is there room for improvement? Let’s start the discussion here, who knows, maybe some good can come of it. ;-)

Switch to our mobile site