BlogBlog

Posts tagged with: Development

Vote for me for SXSW!

Monday, August 19, 2013 5:45 PM

Vote_My_Session

Voting opens today for presentations for South by Southwest Interactive 2014. I’ve submitted a proposal entitled “Surviving as a Developer in a BYOD World” and I would love your support for presenting at SXSW Interactive in 2014! Vote here: http://panelpicker.sxsw.com/vote/25088! The full presentation abstract is below:

It’s enough to make a developer want to throw in the towel. The days of creating a specific application for a specific user on a specific device are gone. Today, people are accessing apps from multiple devices with the expectation that they will perform the same on each. Not to mention, their expectations are increasingly high. As developers, how do we manage this demand and keep the code bases contained from an architectural standpoint so that we don’t completely lose our minds? This talk will cover architectural patterns that can help with sharing code in multiple places, as well as how to take the best of all the buzzword processes (Agile, waterfall, TDD, etc.) and create one process that will help ensure success. We’ll talk about which technologies to follow and how you can expand your repertoire to be able to make good recommendations for technology solutions to get the best results on multiple platforms. - See more at: http://panelpicker.sxsw.com/vote/25088

 
By: shane
Comments

Comments

Be the first to comment on this post

4500+ Downloads!

Tuesday, June 11, 2013 7:21 PM

What I Eat ScreenshotI am truly overwhelmed by the response to What I Eat! In just over a month since I released What I Eat to the Windows Phone Store, there have been 4,683 downloads of the app. I’ve released two minor updates in response to feedback and it is truly humbling that a simple food journal has met such a need. Thank you all for your response and please send me feedback if you’re interested in other features!

If you haven’t tried it, check it out!

 
By: shane
Comments

Comments

Be the first to comment on this post

Moving to Azure

Sunday, December 30, 2012 8:01 PM

Windows Azure Logo

Wow. It’s hard to believe that it’s been two months since I last wrote something on here. In the interim, I’ve been some minor architecture work under the covers here at s-church.net. I moved the site to ASP.NET MVC 4 and .NET 4.5 and upgraded to Entity Framework for database access. The site is also now hosted on the new Windows Azure Web Sites with a SQL Azure database. I was very pleasantly surprised as to how easy it was to get up and running on Azure. Publishing the completed site to Azure was as simple as downloading the publish profile for my Azure site and then selecting that profile as the destination from the Publish command in the Visual Studio 2012 Web Application project menu. The publish process updates the database connection string as necessary to connect to the associated SQL Azure data store.

I’m also in the process of building a couple of new Windows Phone apps using the Azure Mobile Services backend. It’s not quite as straightforward to use Azure Mobile Services in Windows Phone 7.5 because I have to use the REST interface directly instead of the packaged clients available for Windows Store, Windows Phone 8, and iOS apps, but it’s still a big step forward from the Microsoft Sync Framework backend that I’ve used in the past. Sync Framework requires a dedicated server where I can do binary installs, which is quite a bit more expensive from a hosting perspective.

Once completed, the whole setup should be considerably cheaper than the hosting combination of Amazon Web Services and CrystalTech/The Small Business Authority that I’ve been using for over a year now and should also be more reliable since everything is co-located again.

 
By: shane
Comments

Comments

Be the first to comment on this post

Review - Using PhoneGap Build Beta

Wednesday, September 5, 2012 1:28 PM

Adobe PhoneGap Build BetaMy most recent blog post on the EffectiveUI Blog just went live. The post is a review of my experiences using the PhoneGap Build beta for an iPad prototype.

Recently I was asked to build a prototype for a sales proposal here at EffectiveUI to enable the client to see what the finished design would behave like on a real iPad. We had provided an initial demo to the client through FieldTest; however, they wanted to see examples of what the actual interactivity would look and feel like on a real device. The client also added an additional requirement that the prototype be able to work completely offline. The eventual architecture for this application was to be a hybrid mobile Web and native application, much like I described in this MSDN Magazine article and in this blog post. …

Read the rest of the post at the EffectiveUI Blog.

 
By: Shane
Comments

Comments

Be the first to comment on this post

Building Stirling Money

Thursday, May 24, 2012 3:38 PM

ScreenshotTransactionsBeing my first fully native Windows Phone 7 application, Stirling Money provided me lots of opportunities to learn more about the platform. I had written a check register application for Windows Mobile 6 and wanted to take the opportunity to update it to the new Windows Phone platform. Windows Phone 7 is a radical departure from Windows Mobile from both the user’s perspective and the developer’s perspective. Building applications for the older Windows Mobile platform utilized the Microsoft .NET Compact Framework, SQL Server Compact, and a more traditional, battleship gray, Windows Forms user interface (UI). In contrast, Windows Phone 7 uses Silverlight and XAML for the UI and LINQ to SQL to access a local database.

Getting Started

To get started in Windows Phone 7, the first thing I had to do is force myself to forget everything I had learned over almost 12 years of developing mobile applications for the Microsoft Pocket PC/Windows Mobile platform. Windows Phone 7 is such a radical departure that everything I had learned about building UIs and the underlying application architecture went completely out the window. Anyone who has taken the time to become an expert in a given field can tell you just how hard that can be, and it was no different for me. I found myself having to really consciously force myself out of my old Windows Mobile development patterns, but once I got to that point, I was actually very pleasantly surprised at how easy it was to build an attractive interface that performed really well and ran rings around anything I had ever done on the older Windows Mobile platform.

The first big thing that I discovered is that there three invaluable, free toolkits that really ease the development of a Windows Phone application:

The Microsoft Silverlight Toolkit provides a whole host of native Silverlight controls for Windows Phone that you can drag and drop into the designer and use the Visual Studio properties window to manipulate. The Coding4Fun Toolkit provides more controls that really should have been built into the main framework if you ask me such as AboutPrompt, ProgressOverlay, RoundButton, and many more.

Building the UI

Even with all of these controls, building a UI in XAML is a lot like learning a foreign language. It’s just enough like XML and HTML that I’m familiar with, but with its own twists to throw me off. Data binding in XAML is particularly different than in ASP.NET or the older Windows Forms, so that was probably the biggest difference to get used to. The concept of using a view model in order to make all of the properties available to the UI was familiar to me because I use it all the time in my ASP.NET MVC development, but the binding syntax in XAML and exactly which NotifyPropertyChanged event the binding ends up listening to took some figuring out. I ended up with a number of properties in my view models that looked like the code below, with multiple NotifyPropertyChanged events, in order to get all of the related properties on the page to update when I needed them to.

private ObservableCollection<AccountViewModel> _accounts;
public ObservableCollection<AccountViewModel> Accounts
{
    get { return _accounts; }
    set
    {
        if (_accounts != value)
        {
            _accounts = value;
            if (_accounts != null)
            {
                _accounts.CollectionChanged += delegate
                {
                    NotifyPropertyChanged("Accounts");
                    NotifyPropertyChanged("TotalBalance");
                    NotifyPropertyChanged("NoDataVisibility");
                };
            }
            NotifyPropertyChanged("Accounts");
            NotifyPropertyChanged("TotalBalance");
            NotifyPropertyChanged("NoDataVisibility");
        }
    }
}

The other thing that I learned in the process is that the XAML editor in Visual Studio 2010, while much improved over previous editions, has some quirks when using static resources inside the phone:PhoneApplicationPage.Resources tag. Editing data templates in that tag doesn’t give the WYSIWYG display that editing a template inside a control does, so I often found myself editing ListItem templates inline so I could see the results in the designer and then moving the template to the Resources section once I had the design solidified.  I was pretty amazed at the amount of markup required for seemingly simple tasks. For example, one single row in the list view above required the following markup:

<DataTemplate x:Key="transactionsItemTemplate">
        <StackPanel>
            <toolkit:ContextMenuService.ContextMenu>
                <toolkit:ContextMenu>
                    <toolkit:MenuItem x:Name="menuItemEdit" Header="edit" Tag="{Binding TransactionId}" Click="menuItemEdit_Click"/>
                    <toolkit:MenuItem x:Name="menuItemDelete" Header="delete" Tag="{Binding TransactionId}" Click="menuItemDelete_Click" />
                </toolkit:ContextMenu>
            </toolkit:ContextMenuService.ContextMenu>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="5"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Rectangle Grid.Column="0" 
                           Grid.Row="0" 
                           Grid.RowSpan="2" 
                           Margin="0,2,0,2"
                           Fill="{Binding TransactionColor}"/>
                <CheckBox IsChecked="{Binding Posted, Mode=TwoWay}" 
                           Tag="{Binding TransactionId, Mode=TwoWay}"
                           Grid.Row="0"
                           Grid.Column="1"
                           Grid.RowSpan="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Center"/>
                <TextBlock Text="{Binding CheckNumber}" 
                           FontSize="{StaticResource PhoneFontSizeNormal}"
                           Padding="0,0,10,0"
                           Grid.Row="1"
                           Grid.Column="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"
                           Visibility="{Binding CheckNumberVisibility}"/>
                <TextBlock Text="{Binding Location}" 
                           FontSize="{StaticResource PhoneFontSizeMediumLarge}"
                           Margin="0,0,0,0"
                           Grid.Row="0"
                           Grid.Column="2"
                           Grid.ColumnSpan="2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"/>
                <TextBlock Text="{Binding Category}" 
                           FontSize="{StaticResource PhoneFontSizeNormal}"
                           Margin="0,0,0,0"
                           Grid.Row="1"
                           Grid.Column="3"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"/>
                <TextBlock Text="{Binding Amount, StringFormat=\{0:C\}}"
                           FontSize="{StaticResource PhoneFontSizeMedium}"
                           Grid.Row="0"
                           Grid.Column="4"
                           Grid.RowSpan="2"
                           Margin="5,0,5,0"
                           TextAlignment="Right"
                           VerticalAlignment="Center"/>
        </Grid>
    </StackPanel>
</DataTemplate>

Building and Accessing Data

Database support on the phone is provided through LINQ to SQL on top of SQL Server Compact 3.5.  Having used the Microsoft Entity Framework extensively in some of my recent work at EffectiveUI, using LINQ to SQL was relatively easy to pick up, though it does have some differences from the Entity Framework syntax that got me a bit in the early going. After that, it was simply a matter of translating from the database model to the view models and everything else just worked, which was way easier than writing the ADO.NET code and scripting the database creation that was required in Windows Mobile.

ScreenshotBackupThe other interesting complication was that Windows Phone does not sync files directly with the desktop. The only solution to allow the user to backup and/or restore their data from the phone is to sync with a cloud service such as SkyDrive. Fortunately the Microsoft Live SDK makes this very easy.  The following markup is all of the XAML needed to add the Sign in/Sign out button to the page:

<my:SignInButton ClientId="00000000400C1EB8" 
    Scopes="wl.signin wl.basic wl.offline_access wl.skydrive_update" 
    Branding="Skydrive" 
    Name="buttonSkyDriveSignIn" 
    SessionChanged="buttonSkyDriveSignIn_SessionChanged" />

After that, the C# code to handle the SkyDrive session changes was also very simple. All I had to do is listen for the SessionChanged event and check to see if the session status that was reported was Connected as shown in the snippet below.

private void buttonSkyDriveSignIn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
    if (e.Status == LiveConnectSessionStatus.Connected)
    {
        _session = e.Session;
        _model.IsSignedIn = true;
        _client = new LiveConnectClient(_session);
        _client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_GetCompleted);
        _client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_PostCompleted);
        _client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(_client_UploadCompleted);
        _client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(_client_DownloadCompleted);
        _progress.Text = "Loading...";
        _progress.IsVisible = true;
        _client.GetAsync("me/skydrive/files?filter=folders", "me/skydrive/files?filter=folders");                
        _model.InfoBoxText = "Signed in.";
    }
    else
     {
         _client = null;
         _model.IsSignedIn = false;
         _model.InfoBoxText = "Not signed in.";
     }
}

Building a Trial Mode Application

Another place where the Windows Phone tools really shined is in building a trial feature into the application. Unlike in the past, where a developer had to deal with all of the registration algorithms themselves, Microsoft does a great job of providing these checks for the developer along with the hooks into the Windows Phone Marketplace to convert from trial to paid. The code to check to see if the application is running on a trial license is very simple as shown below:

private void DetermineIsTrial()
{
#if TRIAL    
    // return true if debugging with trial enabled (DebugTrial configuration is active)    
    App.IsTrial = true;
#else
    var license = new Microsoft.Phone.Marketplace.LicenseInformation();
    App.IsTrial = license.IsTrial();
#endif
}

This method is called when the application is loaded or is activated after the user switched to a different task and set in a static variable in the main app class so that I can check for trial functionality anywhere where that check is needed.

To convert the user to a paid user from the “Buy Now” button, I only have to execute the following code to launch the Marketplace app directly to my application page. If they purchase the application while there, the DetermineIsTrial method will be called when my application is reactivated and the user will automatically see the full functionality.

private void Button_Click(object sender, RoutedEventArgs e)
{
    MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
    marketplaceDetailTask.Show();
}

Conclusion

Being my first fully native application for Windows Phone 7, I was really pleasantly surprised as to how easy it was to build an attractive, performant app that took advantage of local database storage and cloud backup. Stirling Money took approximately 16 hours of total development time for the first release into the Windows Phone Marketplace. My next project is building a side by side comparison of building a fully-native Windows Phone application and building the same application functionality with PhoneGap/Apache Cordova and doing a comparison of the two approaches in addition to the approach of building a mobile web application within a native shell that I discussed in my article, Develop Hybrid Native and Mobile Web Apps, in the March 2012 issue of MSDN Magazine.

As of this writing, Stirling Money has been certified and published to the Windows Phone Marketplace, although it is not currently searchable yet. When it becomes available, it will be at this link. Prior to that, there is more information on my Windows Phone Software page. I will be publishing an additional post when the application goes live in the Marketplace.

 
By: Shane
Comments

Comments

Be the first to comment on this post

Mobile Web, Hybrid, or Native Mobile – A New Question

Monday, April 23, 2012 2:17 PM

Continuing on my recent thread about decision making for choosing a mobile web, hybrid, or native mobile application architecture, I’ve added another question to consider for the decision tree:

  • Does your application need to take advantage of push notifications?

After a discussion with a client last week, I ended up adding this question to my list. The client had already implemented a hybrid mobile application based on ASP.NET for Android and iPhone and wanted to have all of the registration take place through a web form, but I quickly noticed that the registration processes are very different between Android, iOS, and Windows Phone. Not only are the processes different, but the central application server needs to know what type of device it is to successfully send a push notification. Once the device is registered for push notifications, the basic mechanics of sending and receiving notifications are similar on each of the devices.

That being said, my first dive into the world of push notifications has suggested that the best approach for building push notifications would be to build all of the registration and message handling functionality as native mobile code, even within the context of a hybrid app.  Push notifications are definitely a disqualifier for a pure mobile web solution, but don’t necessarily push all the way into a fully native mobile solution.

More reading:

Windows Phone 7 Push Notifications

Android Cloud to Device Messaging

iOS Push Notifications

 
By: Shane
Comments

Comments

Be the first to comment on this post

Mobile Web, Hybrid, or Native Mobile – How Do You Choose?

Thursday, April 5, 2012 2:19 PM

MobileWebContinuumQuestion 

Since my article in MSDN Magazine, “Develop Hybrid Native and Mobile Web Apps,” came out, I’ve received a lot of questions on how to decide what kind of mobile application to build: mobile web, hybrid, or native mobile? This is a really thorny question and one that doesn’t have a well-defined answer. I’ve spent a lot of time over the past week discussing how to go about answering this question with some of the members of the sales team at EffectiveUI and I’d like to share some of my process in the hope that it will help others with these decisions and spark a conversation to continue to refine the decision-making process.

I’ve just had a new post published on the EffectiveUI blog about these thoughts and I’d love to hear what you think.

 
By: Shane
Comments

Comments

Be the first to comment on this post

Using the ASP.NET Web API Beta

Monday, April 2, 2012 3:21 PM

Over the last week, I was building some data services for a demo project for our non-profit subsidiary, EffectiveSC, and we decided to use this quick project as an opportunity to get familiar with the ASP.NET Web API beta that is part of the ASP.NET MVC 4 beta.  My first impressions of the Web API are generally very positive.  I was able to get a basic Create-Read-Update-Delete (CRUD) service up and running using the appropriate HTTP verbs (PUT, GET, POST, DELETE respectively) in just a couple of hours and the service automatically translated my model to JSON or XML based on the Accepts header in the incoming request.

You can add the ASP.NET Web API to an existing project by running the following from the NuGet Package Manager console:

PM> Install-Package AspNetWebApi

or create a new project with the ASP.NET MVC 4 Web Application template installed with the ASP.NET MVC 4 beta.

If you create a new project, the Web API template creates a new controller, ValuesController, that inherits from the new ApiController class.  This new class looks something like this:

public class BadgeController : ApiController
{
    // GET /api/badge
    public IEnumerable<EarnedBadge> Get()
    {
        RelationalDataModel data = new RelationalDataModel();
        return data.EarnedBadges;
    }

    // GET /api/badge/5
    public EarnedBadge Get(long id)
    {
        ...
    }

    // POST /api/badge
    public void Post(EarnedBadge value)
    {
        ...
    }

    // PUT /api/badge/5
    public long Put(EarnedBadge value)
    {
        ...
    }

    // DELETE /api/badge/5
    public void Delete(int id)
    {
        throw new HttpResponseException(HttpStatusCode.MethodNotAllowed);
    }
}

In my case, I was sending a EarnedBadge object as my model.  In each of the methods, I simply performed the required query operations against my Entity Framework Code First data store and the framework took care of all of the serialization.  The EarnedBadge object was defined as:

public class EarnedBadge
{
    [Key]
    public long EarnedBadgeId { get; set; }
    [Required]
    public long ProviderId { get; set; }
    [Required]
    public long BadgeId { get; set; }
    [Required]
    public long UserId { get; set; }
    [Required]
    public DateTime EarnedDateTime { get; set; }
    public string Note { get; set; }
}

While this is a pretty simple object, the serialization resulted in the following results for JSON and XML respectively:

{        
    "EarnedBadgeId":123456789,        
    "ProviderId":123456789,        
    "BadgeId":123456789,        
    "UserId":123456789,        
    "EarnedDateTime":"2012-03-28T00:54:06.843",        
    "Note":"string"    
}

and

<?xml version="1.0" encoding="utf-8"?>
<EarnedBadge>    
    <EarnedBadgeId>123456789</EarnedBadgeId>    
    <ProviderId>123456789</ProviderId>    
    <BadgeId>123456789</BadgeId>    
    <UserId>123456789</UserId>    
    <EarnedDateTime>2012-02-18T00:54:06.843</EarnedDateTime>
    <Note>String</Note>
</EarnedBadge>

I did use the JSON.NET formatter as described by Henrik Nielsen in order to format the dates into ISO-8601 format which is a little easier for JavaScript-based clients to consume. From my perspective, one of the nicest features of using the ASP.NET Web API is the control it gives over the HTTP response messages, especially for exceptions. The new HttpResponseException allows me to control the HTTP status codes that are sent when errors occur such as the HTTP 405 Method Not Allowed for the Delete method in the example above.  This allows me to build the service in a truly RESTful fashion and to send meaningful error messages back to the client.

Another really impressive feature is the built in OData query support.  Any IEnumerable or IQueryable object that is returned by the service is automatically queryable using the OData query string parameter syntax which makes building paging and searching of data sets really easy.

The one feature that I really like in WCF’s REST implementation that isn’t available yet in the ASP.NET Web API is the auto-generated service API documentation.  The ASP.NET Web API team has confirmed that this feature will be available in the final release.  It appears that, for most of the service work that I do at EffectiveUI, the Web API will be the way to go moving forward.  A good discussion of the ASP.NET Web API vs. WCF can be found at iDesign and it largely mirrors my my own thoughts on the comparison.

I hope my initial thoughts and experiences prove useful and I’d love to hear how others are using this new tool.

 
By: Shane
Comments

Comments

Be the first to comment on this post

MSDN Magazine: Develop Hybrid Native and Mobile Web Apps

Friday, March 2, 2012 10:04 AM

MSDN Magazine: Develop Hybrid Native and Mobile Web AppsMy article on building hybrid native and mobile web applications has been published in the March issue of MSDN Magazine.

Mobile applications are all the rage these days. There are currently three major mobile platforms: Apple’s iOS  (iPhone and iPad), Google’s Android , and Microsoft’s Windows Phone , and countless variations within these platforms for the developer to consider. Focusing on any one of these platforms leaves 50% or more of the market unable to use your application, but the cost of building and maintaining the same application on each of the platforms quickly becomes problematic. A web application is another option, but one that leaves the experience diluted and leaves the developer without access to many of the native hardware capabilities. 

In one of my recent projects at EffectiveUI, I spent a lot of time thinking about how to solve this conundrum in a way that provides the best possible user experience while still being cost effective and maintainable. My solution was an application that is a hybrid of a native application and a mobile web application. I had the opportunity to share this solution, and provide a tutorial for building it, in an article for MSDN Magazine , “Develop Hybrid Native and Mobile Web Apps .” I truly believe that this approach is a “best of both worlds” solution that leaves the developer and end user in a better place.

I hope that my approach to this problem helps you in building your applications and I’d love to hear any feedback that anyone might have.

The main text of this post is also cross-posted on the EffectiveUI blog.

 
By: Shane
11 Comments

Comments

  • Ruurd Eijzinga 3/15/20123:48 AM Great article, is there a version for vs2010 ?
  • Shane Church 3/15/20127:48 AM @Ruurd: All of the ASP.NET MVC and Windows Phone 7 code samples in the article are for Visual Studio 2010. The Android project requires Eclipse and the Android SDK and the iOS code requires Apple OS X and XCode.
  • Ruurd 3/15/20128:20 AM sorry, but I get these errors EffectiveUI.MSDN.Web.csproj' cannot be opened. The project type is not supported by this installation. EffectiveUI.MSDN.Phone.csproj' cannot be opened. The project type is not supported by this installation. I am running vs2010 sp1
  • Shane Church 3/15/20128:48 AM You will need the ASP.NET MVC 3 components for the Web project from http://www.asp.net/mvc. You will also need the Windows Phone 7.1 SDK for the Phone project from http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27570.
  • Kushil Abeyguna 3/25/20123:51 PM Good article. I think many people already have been developing hybrid (HTML5/JavaScript running in a native wrapper) mobile application using open source frameworks such as PhoneGap (which supports six mobile platforms). But I never thought of developing these native shells by myself. This is a good eye opener for most people like me as they would have never thought that their favorite frameworks do a "similar" thing to the above in their native wrappers. Good work indeed. I do not have to stick to a bridging framework like PhoneGap anymore.
  • Shane Church 3/27/20129:18 AM Kushil, (cross-posted from blog.effectiveui.com) Comparing this solution to one like PhoneGap (now Apache Cordova) is a matter of degree. To me, the big difference in the solutions is that Cordova is designed to allow a HTML/JavaScript developer to build a device native application. For that to happen, some of the HTML and JavaScript have to be deployed to the device itself and there remains a dependency on the Cordova JavaScript APIs for native hardware access. On the other hand, the solution I present in the article takes a cross-platform mobile web application and provides it with access to native functionality as needed. The hybrid technique that I describe in the article provides a much finer level of control over the user experience when compared to Cordova and also has the advantage of being accessible on devices that do not have the native application installed. As I stated in the article, none of these approaches are inherently better than the others and you really need to make sure that you keep the business and end user goals in the forefront when choosing a technology stack for a mobile application.
  • ALex 3/29/20121:25 AM Hi Shane, this seems like a very useful approach! Thank you. Having to write just 1 Web Application and still have access to the ressources of the device can save a lot of time. But I am wondering if this approach could also enable the webapplication to be accessible offline? What do you think?
  • Shane Church 3/29/20123:49 PM Alex, Depending on how you architect the site, you could likely make large portions of the site available offline using the HTML5 ApplicationCache interface (http://www.html5rocks.com/en/tutorials/appcache/beginner/). It really depends on how dynamic the data in the site is as to how much you could make available offline. I think it would be extremely challenging to make the entire content of anything other than a completely static site available offline. More likely, you could use the HTML5 ApplicationCache interface to speed loading of portions of your app by caching images and CSS files on the user device. I hope this helps!
  • ALex 3/30/20125:58 AM Thank you very much. I think the approach you are using and the new things that are coming like SPA on mvc 4 (http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2159) will be very powerful!
  • Mark L 4/16/20129:35 PM Hi Shane, I've just downloaded the sample code from your article, but the Android code doesn't compile as it appears to be missing a referenced library. I get this error: Project 'EffectiveUI.MSDN' is missing required library: 'C:\Users\Shane.Church\Documents\Cartegraph\httpmime-4.1.2.jar' Any chance of posting an updated sample code package that includes this library? Or am I being a numb nuts and it's already there? "
  • Shane Church 4/17/20121:28 PM Mark, The httpmime-4.1.2.jar is part of the Apache HttpComponents project at http://hc.apache.org/index.html. You can download the HttpClient 4.1.3 (GA) release binaries which include httpmime-4.1.3.jar and update the reference in Eclipse.

Angled Table Headers in HTML5 and CSS3

Friday, February 17, 2012 4:09 PM

The original design compI got the design comp above for one of my projects at EffectiveUI and immediately thought, “How am I going to be able to do that in HTML and CSS?'”  The table headers are generated dynamically by system defined sections and could be different for different groups of users, so using an image for the table header was impractical.  I knew CSS3 gave me some new options using 2D transforms, but browser support was uneven.  Another problem in this design that looks like a really minor feature is the carrot under the “QuickNav” text.  Fortunately, the requirements of this project are that we are just supporting the latest versions of IE, Firefox, Chrome, and Safari, so CSS3 2D transforms it is.

My initial attempt didn’t go so well as you can see below.  Not only were the browser implementations of the 2D transforms uneven, but the documentation available online was less than complete as well. 

DxGAngledHeaders1

So all of my headers didn’t line up with their columns and the text was way out of whack too.  It turns out that the browsers calculate the position of an element first, then transform it, so I had to adjust the positioning of the elements to end up where I wanted them.  After some playing with the Skew() and Rotate() CSS3 2D transform methods, I discovered that I needed a little extra markup in each <th> cell to get the display to show up correctly.  Even with that being said, the end markup is still very clean to generate the table:

<div class="quick-nav-container">
    <h4>QuickNav</h4>
    <a class="close" href="#">x</a>
    <div class="quick-nav">
        <table>
            <thead>
                <tr>
                    <th></th>
                    <th class="skew"><div class="odd"><span>All</span></div></th>
                    <th class="skew"><div class=""><span>General</span></div></th>
                    <th class="skew"><div class="odd"><span>Typography</span></div></th>
                    <th class="skew"><div class=""><span>Colors</span></div></th>
                    <th class="skew"><div class="odd"><span>Buttons</span></div></th>
                    <th class="skew"><div class=""><span>Form Elements</span></div></th>
                    <th class="skew"><div class="odd"><span>Windows</span></div></th>
                    <th class="skew"><div class=""><span>Utilities</span></div></th>
                    <th class="skew"><div class="odd"><span>Images</span></div></th>
                    <th class="skew"><div class=""><span>Iconography</span></div></th>
                    <th class="skew"><div class="odd"><span>Layout Grids</span></div></th>
                    <th class="skew"><div class=""><span>Page Templates</span></div></th>
                    <th class="skew"><div class="odd"><span>Media</span></div></th>
                    <th class="skew"><div class=""><span>Misc.</span></div></th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td class="project-name">EffectiveUI DxG</td>
                    <td class="odd"><a href="/Search/SearchByProject?projectName=EffectiveUI%20DxG">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=1">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=2">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=3">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=4">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=5">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=6">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=7">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=8">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=9">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=10">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=11">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=1&amp;sectionId=12">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=1&amp;sectionId=13">&#187;</a></td>
                </tr>
                <tr>
                    <td class="project-name">Test Project</td>
                    <td class="odd"><a href="/Search/SearchByProject?projectName=Test%20Project">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=1">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=2">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=3">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=4">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=5">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=6">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=7">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=8">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=9">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=10">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=11">&#187;</a></td>
                    <td class="odd"><a href="/Search/QuickNav?projectId=2&amp;sectionId=12">&#187;</a></td>
                    <td class=""><a href="/Search/QuickNav?projectId=2&amp;sectionId=13">&#187;</a></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

As you can see in the code above, I used no images to achieve this effect.  The X close button in the upper right is a simple anchor tag with the border-radius property set to make it appear to be a circle.  The most interesting pieces to note for the angled headers are the <th class=”skew”> tags and the <div> and <span> tags contained within.  Those div and span tags are the extra markup needed to make all of the 2D transforms play nice with each other to generate the 45 degree angled headers. 

The CSS used to generate the table is as follows:

.quick-nav-container {
    background-color: #666666;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    position: absolute;
    z-index: 100;
    padding: 30px 14px 14px 14px;
    display: none;
}

.quick-nav-container h4 {
    position:absolute;
    color: #FFFFFF;
    font-size: 14px;
    font-weight: bold;
    width: 112px;
    top: 0px;
    left: 0px;
    text-align: center;
    padding: 8px;
}

/* creates triangle */
.quick-nav-container h4:after {
    content:"";
    position:absolute;
    bottom:-10px; /* value = - border-top-width - border-bottom-width */
    left:56px; /* controls horizontal position */
    border-width:10px 10px 0; /* vary these values to change the angle of the vertex */
    border-style:solid;
    border-color:#666666 transparent;
    /* reduce the damage in FF3.0 */
    display:block; 
    width:0;
    z-index: 1;
}

.quick-nav-container a.close {
    position: absolute;
    top: 4px;
    right: -12px;
    width: 16px;
    height: 16px;
    text-decoration: none;
    color: #333333;
    background-color: #FFFFFF;
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    border-radius: 8px;
    display: block;
    text-align: center;
    font-weight: bold;
    font-size: 14px;
}

.quick-nav {
    position: relative;
    background-color: #FFFFFF;
    font-size: 10px;
    padding: 20px 90px 20px 20px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
}

.quick-nav a {
    color: #333333;
    text-decoration: none;
    font-size: 14px;
}

.quick-nav table th.skew {
    height: 60px;
    width: 40px;
    position: relative;
    vertical-align: bottom;
}

.quick-nav table th.skew > div {
    position: relative;
    top: 0px;
    left: 30px;
    height: 100%;
    transform:skew(-45deg,0deg);
    -ms-transform:skew(-45deg,0deg); /* IE 9 */
    -moz-transform:skew(-45deg,0deg); /* Firefox */
    -webkit-transform:skew(-45deg,0deg); /* Safari and Chrome */
    -o-transform:skew(-45deg,0deg); /* Opera */    
    overflow: hidden;
    border-top: 1px solid #CCCCCC;
    border-left: 1px solid #CCCCCC;
    border-right: 1px solid #CCCCCC;
}

.quick-nav table th.skew span {
    transform:skew(45deg,0deg) rotate(315deg);
    -ms-transform:skew(45deg,0deg) rotate(315deg); /* IE 9 */
    -moz-transform:skew(45deg,0deg) rotate(315deg); /* Firefox */
    -webkit-transform:skew(45deg,0deg) rotate(315deg); /* Safari and Chrome */
    -o-transform:skew(45deg,0deg) rotate(315deg); /* Opera */        
    position: absolute;
    bottom: 15px;
    left: 1px;
    display: inline-block;
    width: 100%;
    text-align: left;
}

.quick-nav table td {
    width: 40px;
    height: 35px;
    text-align: center;
    vertical-align: middle;
    border: 1px solid #CCCCCC;
}

.quick-nav table td a {
    display: block;
    width: 100%;
    text-align: center;
}

.quick-nav table td.project-name {
    width: auto;
    text-align: right;
    font-weight: bold;
    border: none;
    padding-right: 8px;
}

.quick-nav table .odd {
    background-color: #E8E8E8;
}

The most important sections are highlighted above in the selectors for “.quick-nav table th.skew,” “.quick-nav table th.skew > div,” and “.quick-nav table th.skew span.”  This is where the rotation and absolute positioning happens to make the rotation happen correctly.  For the carrot below, “QuickNav,” I used the speech bubbles technique described by Nicolas Gallagher at http://nicolasgallagher.com/pure-css-speech-bubbles/.  The final result is below, pixel for pixel perfect with the design comp and a new technique that I will definitely be keeping in my back pocket for future projects.

The completed angled headers

 
By: Shane
10 Comments

Comments

  • Andy 2/23/20123:23 PM Thanks for sharing this! The lack of support in older browsers may eliminate this from my list of options, but it was nice to be able to have a quick starting point that I could use to show this option to the rest of my team. For anybody reading this that wants to just take the code and play around a bit, make sure you add "border-collapse: collapse" to the table and "padding: 0" to the th elements. I'm thinking Shane must have those defined in another spot in the CSS and that threw me for a loop for a second when I put together a test file. Anyway, thanks again!
  • Shane Church 2/23/20123:54 PM @Andy: Thanks for the comments. Due to the kinds of layouts that we routinely build at EffectiveUI, I typically use Eric Meyer's Reset CSS (http://meyerweb.com/eric/tools/css/reset/) to reset any browser defaults, so that is where the border-collapse:collapse" and "padding:0" elements that you mentioned are defined.
  • Shala 8/24/201212:57 AM Skew is a nonstandard function, e.g. with Firefox 14 it does not work. However there are the standard functions skewX and skewY, if you replace all occurrences of scew with skewX and remove the second argument (which is 0deg always anyways) it works perfectly well.
  • Chrerops 5/7/20174:04 AM Secure Progesterone Hormone Replacement Low Price Mastercard Nevada Brand Propecia Best Buy Discount Clobetasol Saturday Delivery Store Price Baton Rouge Propecia Itch Skin Clonidine Overnight Kamagra Vs Viagra [url=http://byuvaigranonile.com]viagra[/url] Celebrex Online No Prescription
  • Kennlewbrien 6/16/201711:37 AM Comprare Levitra Generico [url=http://buy-levitra-10mg.buylevi.com]Buy Levitra 10mg[/url] Priligy Oder Viagra Propecia Herz [url=http://dapoxetine-online.priliorder.com]Dapoxetine Online[/url] Viagra A Los 40 Anos Foro Cialis 10 [url=http://cial40mg.com/buy-cheap-cialis-on-line.php]Buy Cheap Cialis On Line[/url] Zithromax Dose In Children Cialis Occhi Rossi [url=http://real-viagra-online.via100mg.com]Real Viagra Online[/url] Levitra Food Propecia Atopico [url=http://viacheap.com]viagra[/url] Clomid Jeulin Viagra By Mail [url=http://kamagra-pharmacy.kamagpills.com]Kamagra Pharmacy[/url] Cialis Generic On Line United Pharmacies Propecia [url=http://xenical.ccrpdc.com/buy-generic-xenical.php]Buy Generic Xenical[/url] Ed Meds In Canada
  • Kennlewbrien 6/19/20178:04 PM Buy Bactroban Uk [url=http://lasix.ccrpdc.com/buy-online-lasix.php]Buy Online Lasix[/url] Amoxicillin 500 Viagra Preiswert [url=http://levitra-online.buylevi.com]Levitra Online[/url] Cialis Netpharm Amoxicillin Typical Dose [url=http://cial40mg.com/cheap-cialis-no-rx.php]Cheap Cialis No Rx[/url] Prix De Xenical 120 Mg Canadianmeds 24hr [url=http://buy-online-kamagra.kamagpills.com]Buy Online Kamagra[/url] Mail Order Stendra Internet Cod Only Next Day Delivery Celecoxib 200 Mg Price [url=http://dapoxetine-purchase.priliorder.com]Dapoxetine Purchase[/url] Viagra Online Auf Rechnung Viagra Canadian [url=http://via100mg.com]Buy Viagra[/url] Buy Generic Levitra Uk Compare Viagra To Generic [url=http://viacheap.com]viagra[/url] Tab generic isotretinoin website cod accepted
  • ShanAgow 11/30/20178:31 PM Lexapro Mail Order Us Pharmacy Kamagra Oral Jelly Wiki Cialis With Prescription [url=http://costofcial.com]cialis[/url] For Sale Generic Legally Dutasteride Mastercard Accepted Store Chicago Keflex Online
  • ShanAgow 11/30/20178:31 PM Lexapro Mail Order Us Pharmacy Kamagra Oral Jelly Wiki Cialis With Prescription [url=http://costofcial.com]cialis[/url] For Sale Generic Legally Dutasteride Mastercard Accepted Store Chicago Keflex Online
  • Briguitty 1/28/20185:38 AM Cheapest Indian Prices For Nizagara Cialis O Levitra [url=http://cial20mg.com]cialis price[/url] Generic Levaquin France With Free Shipping With Doctor Consult Levitra Pas Cher
  • ThaBroope 2/1/20187:26 PM Women Viagra Pills Generic Finasteride Drugs Propecia Effetti Collaterali Di Finasteride [url=http://tadalaffbuy.com]cialis[/url] Amoxicillin The Right Dose Forseniors Tadalis Sx Achat En Ligne

What does Industry Knowledge mean?

Friday, February 10, 2012 2:59 PM

MeetingThis week for our all-staff meeting at EffectiveUI, our CEO gave a presentation on what we’ve learned from the customer experience research that we have been doing in order to continue to improve the experiences that our customers have with us and to strengthen those relationships.   She used a word cloud of terms that our customers had used to illustrate both what we, as a company, are doing well, and what areas our customers perceive a need for improvement in.  One of the phrases in the areas for improvement that stuck out to me was “industry knowledge.”  She explained that our customers were looking for us to show more knowledge of their particular industry so that we could help guide them more effectively.  This got me thinking more on what “industry knowledge” means for a software developer.

One of this things that I’ve said at numerous interviews in the past is how I think that Computer Science is a great generalist’s degree.  Having a degree in Computer Science is like having a degree in problem solving.  I can say with 100% certainty that I’ve never solved a computer problem for the sake of solving a computer problem.  Any problem that I’m addressing is directly related to the needs of the business and the computer is simply a tool to accomplish that goal.  I have to be able to understand the business problem in order to be successful.

In my career, I’ve developed software for the nuclear environmental cleanup, laboratory operations, time and attendance tracking, financial services, mine safety, telecommunications, real estate, and municipal management industries.  All of those different industries span a career of just 14 years (counting my internship during college).  In each project, I find myself needing to rapidly learn the business of my client in order to develop software that actually works for them. 

Going into each of these projects, I usually know almost nothing about the industry or the business model.  For example, I was asked in my interview at the Mine Safety and Health Information if I had a mobile device, continuous miner, and conveyer belt in a mine, what could the mobile device tell me about the continuous miner and conveyor belt.  Having never had any contact with any mining equipment, I had a hard time coming up with a very detailed answer, but I asked a lot of questions to try to figure out what might be useful.  If I can’t understand the conversation, I have no hope of understanding the problem well enough to build a solution.  I have to be conversant in my client’s language in order for me to understand them and for them to trust my ability to deliver the solution that they need. 

With all of that being said, I will never be the subject matter expert that my client is.  I will always have to rely on them to some degree to be able to tell me if I’m pointing in the right direction.  So how do I gain the industry knowledge that customers are asking for and demonstrate to them that I truly care about them and their business? 

First, I listen and I ask a lot of questions.  I have learned to be assertive about asking questions about terms, acronyms, and interactions that I don’t understand. I’m not shy about interrupting a customer if need be to ask them to explain a term or a concept that I don’t understand or I am not familiar with.  I paraphrase the answers to make sure that I truly understood what they were trying to communicate.  Through these questions I learn more about the company, the industry, and the business problems.

Second, I draw pictures.  Diagrams are a software engineer’s best friend when it comes to understanding complex systems and business models and the relationships between them.  Drawing a diagram of the problem space really helps me see the bigger picture.

Third, I read a lot.  I read on a broad range of topics, both work related and not, to be able to understand a wide range of problems and ideas.  Having this breadth of knowledge helps me see parallels between the customer’s current problem and others that might be related.  I can say that I’ve solved a similar problem before or that I’m familiar with a similar concept, easing the customer’s concerns about lack of knowledge in their particular space.

Finally, I liberally search online.  There is definitely a skill to locating the right information online and building a search to find it.  It’s taken a lot of practice in critical thinking and information analysis to be able to separate the really useful information from the sheer volume of other noise online.  The best result is usually not the first one.

This ongoing learning process about new problems and industries is one of my favorite things about being a software engineer.  I consider myself very fortunate to be in a position where I get the opportunity to be constantly learning new things and taking on new projects.  It’s important to me that my customers feel that I understand their business, their problems, and value them as a customer and learning their business is critical to accomplishing this.

 
By: Shane
Comments

Comments

Be the first to comment on this post

MSDN Magazine

Monday, December 5, 2011 2:42 PM

MSDNMagazineSmallLogoA few weeks ago, I submitted an abstract of an article on the Cartegraph mobile prototype that I worked on for EffectiveUI to MSDN Magazine.  The concept is about addressing the costs of building a mobile application for all of the rapidly proliferating mobile platforms (iPhone, iPad, Android, Windows Phone) by building the application primarily as a web application using ASP.NET MVC 3 and jQuery Mobile while still being able to leverage native hardware features like the camera, GPS, or accelerometer.  A few minutes ago I got a phone call from Dr. James McCaffrey of Microsoft Research and author of MSDN Magazine’s monthly Test Run column.  The magazine editors liked the abstract, had asked him to review my submission from a technical perspective and he had a few clarifying questions that he wanted to ask.  He really liked the idea and is recommending to them that they move forward with the idea toward publication.  He commented that the abstract was really well written and also offered some advice about how to catch the readers with the concept in the first few sentences of the article.  Hopefully, with any luck, I’ll have a byline in MSDN Magazine here in a few months.

 
By: Shane
2 Comments

Comments

  • Ryan Comingdeer 2/29/20124:21 PM I read your article today in the March MSDN issue. I love the concept of MVC 3 powering mobile apps. Today I do most of my web apps in MVC 3 and I do a ton of Mobile apps using Phonegap and JQuery Mobile. However, one very important note that you didn't mention in your article was that if you develop the app the way you suggested, Apple will NOT approve the app to the public iTunes store. You would be fine on Windows and Android but the Apple team does not allow an app to be just a browser pointing to a website. We have had this issue a number of times with PhoneGap even if the files reside in the app. For some reason, Apple wants to make sure the app is utilizing some portion of Native code before it gets approved. Very sad, but very true. Have you been able to work around this issue?
  • Shane Church 3/2/201210:00 AM Ryan, With this proof of concept application, we didn't go as far as publishing to the app store. A modification that could be made to make it pass Apple's scrutiny would be to make the login page native on the Apple platform.

Agile Development Best Practices

Friday, November 11, 2011 1:36 PM

CartegraphLogoI spent Monday through Thursday in Dubuque visiting the Cartegraph offices again.  We were out there again to talk through common agile software development process mistakes, discussing the mistakes that they were making and how to improve their process. 

Some of the high level points we were highlighting were:

  • It’s about getting real software in the hands of users as soon as possible
  • Avoid “water-scrum-fall”
  • Start by building what you know
  • Allow for feedback & course correction
  • Don’t lose sight of the big picture
  • Don’t do product owner by committee
  • Estimate using relative story points
  • Don’t confuse tasks with stories
  • Don’t spend too much time on architecture
  • User experience (UX) matter and needs to be an integral part of each sprint
  • Agile/scrum is not an obligation

I really think the first and last points are probably the most important for most development organizations.  I realize that agile and/or scrum is the big buzzword for development methodology at this point, but the reality is that agile isn’t a fit for every organization.  There are a number of cultural issues that can make agile development unsuccessful in a given organization and it is important to have the self-awareness within the organization to recognize and correct those shortcomings or choose a different methodology that suits the organization better.

 
By: Shane
Comments

Comments

Be the first to comment on this post