The Apple iPad .. A little of Meh!

Ok, so I have had my iPad for a little over a month now and have used it often. During this time I have been able to formulate my thoughts on it and come to the conclusion that its a OK device, but not revolutionary or magical as the commercial would try to make you think. The fact of it is its no more then a enlarged iPod touch. Features and functionality that we have been use to for several years now. The device is optimized for reading IMHO and that is pretty much what I use it for. When I break it down to what I like about the platform it really is only the blog/pdf reading capabilities and even at that I still like paper books (I know a hold out) as I find with the iPad I shift back from portrait to landscape quite often or pinching to expand/reduce enough to break my reading flow. However what I do not like about the platform seem to be far greater.

1. I feel like i am getting absolutely screwed for my 3G access with Rogers.

2. When I want to download an application that is greater then 20mb it will not do so (even though I have lots of bandwidth) without either tethering or connecting to a wifi network. Both of those options may not be available when I want to get the piece of software I purchased.

3. Most of the applications that are available ‘Are the Suck’. Lets be honest here if they want to report 250,000 apps on the store they should also report 248000 pieces of shit also up there.

4. You have to pay for that crap application to actually verify that you paid for an absolutely craptastic application. Most do not give enough detail or allow some trialware to make sure that you are happy with your purchase.

5. Games that want to reach in my pocket and scoop out the last available cents. Last night I downloaded an update to a game that I had purchased. On starting the game I get a you should by the game at .99 cents now as its going up to 1.99 in a week. No option to go to no thanks, and continue. Either purchase or go to their website.

6. Suffice it to say I do not believe the iPad in itself is a great game platform. Do not get me wrong, there are some great things that can be done however for me the platform is not only the game but the interaction with the game. 2 things turn me off 1) the size of it is too big to hold for long durations of time while twisting, turning or tilting that the novelty just wears off. 2) as playing goes on the screen becomes more sticky/difficult to do fluid motions. Fingers get moist and eventually dragging becomes encumbered ensuring that I am not having the most optimal playing experience.

So I will continue to use my iPad for reading when I do not have a book available but otherwise I will be discontinuing my 3G service with Rogers come the end of this month. I will also stop purchasing applications from the store until there is a better way to confirm that what I order is what I really want.

Sage SalesLogix Real time Sync Issue

2 windows service components handle message synchronization for the Sage SalesLogix Mobile platform. The connector and Real-Time sync engine handle the synchronization process in different ways. Firstly the synchronization data is created and passed through the connector for all synchronization scenarios. The real-time engine is responsible for detecting and notifying a users device that new data (that has been identified in a watch) exists in the main database. If we look as the connector as the right hand, and the real-time sync as the left hand there is a time were the right does not know what the left is doing. This occurs specifically when you initiate the full sync on the device (initial load) and real-time is enabled. Since real-time is is initiated and the full sync has started and can take some tome to process it is possible that the real-time can disrupt the load process. This happens because the when a real-time sync occurs it looks into the queue to see if another sync is occurring and cancels it with the assumption that the current state of the database is newer and the changes will rollup, with the hope of reducing bandwidth requirements. In most scenarios this would be a good thing except for the initial load where having the load canceled is not such a good thing.

To get around this issue ensure that your admin does not turn on real-time sync for a given user until their initial load is completed. This will allow the connector to work undisturbed and get the load data onto the users device.

– mark

Meeting by the Lake

Having a beer, sitting in the sun by the lake I met with Barnaby Jeans, a Microsoft Senior Development Evangelist. It was an adhoc meeting after Cory Fowler, my web developer introduced us virtually.

It is a beautiful sunny day here in Cambridge, and in the relaxed setting of the lake the conversation jumped from subject to subject. It was great to speak with Barnaby and for me he provided some insight to some of the technologies that I had yet to GROK in a meaningful way. I really like that the conversation had nothing to do with the purchasing a product, or pushing a specific solution but an open and frank communication, much of the time were I was leading and Barnaby was just listening, and absorbing my thoughts. Those who now me personally understand how frank I can be.

I have had one misconception that I wanted to clear up here with regards to Microsoft Azure. Up to this point I had this notion that Azure changes some of my development processes and that the code we write would need to target Azure specifically. I am very pleased to see that this is not a true statement and its quite possible to host a 3.5/4.0 framework based web up unchanged (except for web config changes to point to the DB).

So this left me with Azure being more of a deployment/IT thing then specifically a development concern. Some of the current products I work on cannot still host within Azure (Barnaby will get back to me) due to some legacy COM infrastructure but from a new development side the platform became a little more compelling.

Now I have to work out the dollars and cents and ensure that from business standpoint the hosting/communication costs and SQL costs justify a move over to Azure for our website.

I appreciate Barnaby’s time and look forward to further conversations. Of late I have been having a bit of concern on execution especially around  the new platforms that are coming out from the competitors, but I am still pretty much a Microsoft Stack guy.

IPad Intial Thoughts

I Picked up an IPad the second day it was available in Canada. It really did not give my purchase much thought other then a simple wish for a competing MS os based table be available. I really believe that moving forward NUI will drive the innovation of application development. What we percieve as strange methodologies now will take over as natural extensions on how we view and manage data. So, given that really the only compelling product that could give me a glimpse of different ways of interaction (specifically touch) was the IPad I plunked down the more then 1000 bucks. I have also signed up the the Rogers 3G service which in my opinion is pricey with 6GB of total downloads per month , but it looks from all indications that carriers are all moving to a bandwidth cap. So I have had this device for several weeks now, bought a few apps/games, uploaded a bunch of PDFs and setup a RSS reader. Each night when I am done writing code, meeting with customers or what ever the day has brought I turn on the IPad and catch up on my Blog reading and ocassionaly read some content from the PDFS. From a reading experience the IPad is very nice, easy on the eyes and natural from page turns, resize of the document and switching from landscape to portrate. For me me really that is currently the basis in which I use this device. I have still not gotten into the development of applications for the IPhone or IPad even though I have purchased some books and signed up to the Apple developer program. I think currently I still have the initial barrier of having to code in Objective-c. From that standpoint I really home that some of the MS based oems get their shit in gear and release a compelling slate. What I guess I do not understand, is why it seems from a first glance that the inital adopters HP,… chose to build on a windows 7 based OS instead of a mobile OS such as the one that is being used for the WP7 devices. From a memory and performance standpoint it seamed at least to me to be a more compelling answer. I guess for now I will hope for a great device to be introduced that will give us the tools to build compelling .net/silverlight – cloud/local storage solutions … but I wont wait long if execution continues to fail.

There’s a Service for That

A question came up yesterday with regards to how to create SalesLogix ids within the Web Framework. In the legacy client and our external development we would generally call a provider Stored procedure that would give us the Id. The code might look as the following

List<string> list = new List<string>();

using (
       var cmd = new OleDbCommand(string.Format("slx_dbids('{0}', {1})", table, count), 
       connection)
)
{

   var r = cmd.ExecuteReader();

   while (r.Read())
   {
      list.Add(r.GetString(0));
   }

    r.Close();
 }

return list;

Now within the SalesLogix web client infrastructure it is a actually easier if you know where to look.

The framework exposes a service – SalesLogixEntityKeyGenerator. You can get access to this service using the following code;

SalesLogixEntityKeyGenerator generator = 
ApplicationContext.Current.Services.Get<SalesLogixEntityKeyGenerator>(false);

 

Once you have access to the generator it its very easy to get a set of keys;

List<string> keys = new List<string>(generator.GenerateIds(typeof(IHistory), 1));

 

There you have it.

Visual Studio Quick Hint

I really like Visual Studio 2010. I have been using it for a couple of weeks and its growing on me nicely. I have been playing around with the Parallel extenstions and other .net 4.0 things but yesterday I found that there is a new ‘quick’ feature that I have wished for and just found out it was there. Get this you can now copy project references from one project to another one. Yup, nothing special but a time save none-the-less.

I’ve seen the ‘Dynamic’ Light

Hey did you hear, VS 2010 is released and production worthy. We at BITtelligent did not wait long to start to put it into our daily work flow and I have to say I am quite impressed and happy that we did. In in the IDE side, but more so in the C#4 language improvements.

We are working on a large project with a different complexity challenges. The project is loosely based on a current implementation that is in production. That being said there are instances of where system settings are retrieved from the database to determine the process flow.

so code exists such as

if (cbool(container.settings.LocateValueFromSetting(“aaaa aaaa aaaa”)) = true

Now for me the intent is lost in the complexity of the check. This means more comments and a harder time for someone to grok my code.

Its quite possible to wrap the settings type with either proxy or add extension methods to allow for a better maintainability.

code such as;

ProxyClass proxy = new ProxyClass(settings);
if (proxy.ShouldExecuteSomeCode())
{

}
- or - 
public static bool ShouldExecuteSomeCode(this SpecialDataSet settings)
{
   return Convert.ToBoolean(settings.FindSettingBySettingName("Should Execute Some Code"));
}

Now this code needs to be repeated for each and every setting value and that seems to me to be a pretty heavy handed way of coding up the solution.

Enter dynamic.

Since I was looking for the most efficient and manageable way to provide settings access I moved into using a dictionary<string, object> as my local storage mechanism.  and for explanation purposes the following code is included;

 public class DynamicSettingClass : DynamicObject 
    {
        Dictionary<string, object> _values;

        /// <summary>
        /// Initializes a new instance of the DynamicSettingClass class.
        /// </summary>
        /// <param name="values"></param>
        public DynamicSettingClass(Dictionary<string, object> values)
        {
            _values = values;
        }

        /// <summary>
        /// Initializes a new instance of the DynamicSettingClass class.
        /// </summary>
        public DynamicSettingClass()
        {
            _values = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);    
        }

        public void AddSettingValue(string key, object value)
        {
            if (_values.ContainsKey(key))
                _values[key] = value;
            else
                _values.Add(key, value);

        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            string keyName = FormattedName(binder.Name);
            if (_values.ContainsKey(keyName))
            {
                result = _values[keyName];
                return true;
            }

            return base.TryGetMember(binder, out result);
        }

        private static string FormattedName(string name)
        {
            if (name.IndexOf('_') > 0) name = name.Replace('_', ' ');
            return name;
        }

    }

What this class enables is the ability to address each of the setting values as a property of our object instead of as a collection item.

Now the secret sauce is in the TryGetMember, and Formatted name. Within the TryGetMember we are provided important information in the binder object but for our sample the most important is the name property. From it we can derrive the targeted setting we are looking for. I add a little preprocessing to the key value as settings values can contain spaces, so a little token replace is required. The final outcome is that I can use this utility class to enhance the readability of my code and reduce the amount of lines to write to get the experience for all of my setting requirements.

so to now access the setting using the following code I would do the following;

dynamic simpleSettings = new DynamicSettingClass();
simpleSettings.AddSetting("Should_Execute_Some_Code", true);

if (simpleSettings.Should_Execute_Some_Code)
{
}

This seems to be a simpler syntax for accessing my settings list but really having to call the AddSetting method seems incomplete. So we can finally and a little more ‘magic’ to our settings class;

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        string keyName = FormattedName(binder.Name);
        AddSettingValue(keyName, value);
        return true;
    }

With this little snippet the round tripping is now possible with our Dynamic property example;

simpleSettings.Should_Execute_Some_Code = true;

if (simpleSettings.Should_Execute_Some_Code)
{
}

So this completes this post. I hope it helps you out in seeing the power of the DynamicObject’s power.

DevTeach Initial Thoughts

I have had in the past a reservation in attending conferences. In general I set lofty expectations and feel somewhat let down when they do not come to fruition. If I am to put my life on pause, leave my family and put my customers on hold for a week, with an investment cost greater then just the fee, transportation or hotel, I believe the content that is presented should be not some re-hash of what I can get on the web after 5 minutes of Goggling or Binging (is that the term).

I decided to cut away from this hesitation and this year attend the DevTeach conference (It is still on). I had heard good things, and the speakers were recognizable and notable. It was also a bonus as it was quite literally 30 minutes down the highway from my house. I felt so compelled initially that I even booked a room at the delta where I believe the conference was taking place so that I could spend some afterhours time with some of the other attendees enjoying a frosty beverage.

Just after arrival I was able to sit down and spend the balance of the evening with Peter Richie, Rob Windsor, Mario Cardinal, K. Scott Allen, Donald Belcham, Kelly Cassidy, Erik Renaud,  and Rob Daigneau. A great bunch of guys and they all seem passionate about their Tech.

After a very lousy night of sleep, I decided to abandon my decision to stay in the hotel for the duration of the conference and booked out during lunch, actually before, I wanted to get into a session on architecture put on by Michael Stiefel but was unable.

The first day for me was somewhat of a let down and I think it was due to the fact that I started off by going to some of the tooling session (language C#, V.net, Keynote, and VS for Architects). Except for a few notables these sessions for me were nothing more then marketing and a rehash of pre-canned content that has been available on the web, not much substance, and definitely no wow factor or call to action.

Both of the presenters in those sessions are very likable, and I believe great people for our community as a whole. I just felt that after the commitment that the attendees the payback was minimal. That being said I like where Sharepoint development is going and the slight overview of how to create sharepoint customizations in 2010 was good.

I am getting ready to head back to the conference for Day 2 and hope that If I change my ways (no more ms tooling sessions) the content will be engaging and provide the value I so really seek. The saving grace so far is the promise that all the sessions are being recorded, giving me the chance to view the ones that I cannot attend, at home, in the office at a time when they are not disruptive to my business practice.

Time for a coffee and a car ride,

2010 – The year for debt reduction

I have been on a course of reducing debt over the last few years. More purchases using cash, paying most bills as quick as possible. But like most Canadians (Americans as well) I carry some credit card debt. My interest rate for my cards was quite reasonable so I had gotten somewhat use to using them to make mostly online purchases. Over the last little while my rate had jumped several percentage points. I was upset, however I decided that I could live with an increase for now. However today on my latest credit card statement the rate was bound to jump another 2%. I can absolutely understand when the cost of debt is high or that the account is in poor standing that interest rates would reflect those realities, however neither is the case here since the current overnight lending rate in Canada is 1/4 percent and my credit card account is always been in good standing. I am not going to speculate on why this is happening, when I spoke to the representative on the phone I was told that lots of accounts were going up and that the actual base rate was almost 20%. I have decided out of principal that I can no longer deal with the vendor and be cancelling my credit card (paying off the remaining balance). After this we will be down to one household card, just enough for those emergency requirements/needs. I suspect I am one of the fortunate ones that can afford to pay off and close out an account but I wonder how many others will do the same when faced with this reality.

Sage SalesLogix Mobile Pick Lists (BlackBerry)

When working with Sage mobile from time to time you will find that there is missing functionality that you expected to be there but is not. One such piece of functionality involve pick lists and recently worked on a project that required ‘must exist in list’ functionality. By the way did I say how much I like using Eclipse when I have to do java development. Well I do.

Must Exist In List

MustExistInList is a property of Sage Saleslogix web and Lan client picklist. This ensures that the end user cannot enter any free form text into the pick list edit area. This property however has yet to make it up to the mobile implementation. Since the property does not exist and it is not possible to introduce new controls into the form building process I had to take a more intermediate step. The first thing to remember is that most of the controls that exist on the BlackBerry device start as a HorizontalFieldManager.

Generally the following layout for each control is followed

< Label Field > + < Seperator Field > +  < Edit Field >

however with the lookups and picklists the following layout is followed

<Label Field> + < CMPImage > + < Seperator > + < Edit Field >

Now I was not completely sure on the layout of the control, so to help me on a way I wrote a simple helper method that did nothing more then to iterate through the embedded fields on the HorizontalLayoutManager and inform me of the embedded class names.

Once I had this information in hand I built out a pick list adapter method. I should have created a full adapter to allow for future expansion however sometimes KISS should be honored especially if under the gun to deliver in short order.

Its a simple method but effective in providing the functionality.

public static void setPicklistEditable(CMPPickList field, boolean editable ) {
    HorizontalFieldManager manager =  (HorizontalFieldManager) field;
    EditField edit = (EditField)manager.getField(3);
    if (edit != null) {
        edit.setEditable(editable);
    }
}


Note that the index for the field is 3 even though there is 4 embedded controls as arrays in java are 0 based .