Andy Crouch - Code, Technology & Obfuscation ...

Debugging Object Lists

Man Sitting At Deak Looking At Monitor

Photo: Austin Distel - Unsplash

Something that I wish I had written for Visual Studio over the years was an object list debugger. Data Tables in ADO.Net had the DataSet visualizer which allowed you to see the contents. You were able to copy those contents out to Excel if need be and it was genuinely useful.

Something that I coded up some time ago was a class that takes a list of Entity objects and creates a Data Table from it. I developed it to use within a Table Gateway implementation that I created to improve bulk database insert times. As a side note, you really can not beat the speed of the SQlBulkCopy utility class for inserts on large datasets. Perhaps I will write a post on those topics soon.

I was recently tracking down an intermittent bug. The issue was obviously down to some data passed to a processing routine. The idea came to me to use my EntityDataTableFactory class to dump out objects at debug time. I didn’t really have time to create a polished solution. But, my theory worked and by plugging in my factory, I was able to inspect the data in the DataSet visualiser.

See the optional visualiser option when debugging and results below. The visualiser is available when you hover over a Data Table variable.

Visual Studio Debugging Code


Visual Studio Dataset Visualisation

The EntityDataTableFactory class will work on any strongly typed object List<T> type. You need to declare a table to store the resulting Entity table to and then you can use the DataSet visualiser. Using this to inspect the object list takes a couple of lines to set up. But, I find it is easier to use than Watch values and the property viewer.

I have condensed the code into a single namespace below in case you find it useful yourself.

using EntityListViewer.ExtensionMethods;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Reflection;

namespace DataUtilities
{
    public interface IEntityDataTableFactory
    {
        DataTable CreateDataTableFrom<T>(List<T> entityList) where T : class;
    }

    public class EntityDataTableFactory : IEntityDataTableFactory
    {
        public DataTable CreateDataTableFrom<T>(List<T> entityList) where T : class
        {
            if (entityList.IsNullOrEmpty())
                return new DataTable();

            DataTable entityDataTable = CreateDataTableFor(entityList);

            const int MinimumExpectedColumns = 1;
            if (entityDataTable.Columns.Count.IsLessThan( MinimumExpectedColumns))
                return new DataTable();

            foreach (var entity in entityList)
            {
                GenerateDataRowFrom(entity, ref entityDataTable);
            }

            return entityDataTable;
        }

       private DataTable CreateDataTableFor<T>(List<T> entityList) where T : class
        {
            Type classType = entityList.First().GetType();

            List<PropertyInfo> propertyList 
                = classType
                     .GetProperties()
                     .Where(p => p.GetCustomAttributes(typeof(NotMappedAttribute)).Any() == false && 
                                 p.GetCustomAttributes(typeof(DatabaseGeneratedAttribute)).Any() == false)
                     .ToList();

            const int MinimumPropertyCount = 1;
            if (propertyList.Count < MinimumPropertyCount)
                return new DataTable();

            string entityName = classType.UnderlyingSystemType.Name;
            DataTable entityDataTable = new DataTable(entityName);

            foreach (PropertyInfo property in propertyList)
            {
                DataColumn column = new DataColumn();
                column.ColumnName = property.Name;

                Type dataType = property.PropertyType;

                if (IsNullable(dataType))
                {
                    if (dataType.IsGenericType)
                    {
                        dataType = dataType.GenericTypeArguments.FirstOrDefault();
                    }
                }
                else
                {   
                    column.AllowDBNull = false;
                }

                column.DataType = dataType;

                entityDataTable.Columns.Add(column);
            }

            return entityDataTable;
        }


        private void GenerateDataRowFrom<T>(T entity, ref DataTable entityDataTable) where T : class
        {
            Type classType = entity.GetType();

            DataRow row = entityDataTable.NewRow();
            List<PropertyInfo> entityPropertyInfoList = classType.GetProperties().ToList();

            foreach (PropertyInfo propertyInfo in entityPropertyInfoList)
            {
                if (entityDataTable.Columns.Contains(propertyInfo.Name))
                {
                    if (entityDataTable.Columns[propertyInfo.Name].IsNotNull())
                    {
                        row[propertyInfo.Name] = propertyInfo.GetValue(entity, null) ?? DBNull.Value;
                    }
                }
            }

            entityDataTable.Rows.Add(row);
        }

        private bool IsNullable(Type type)
        {
            if (type.IsValueType.IsFalse()) 
                return true; 

            if (Nullable.GetUnderlyingType(type).IsNotNull()) 
                return true; 

            return false; 
        }
    }

    public static class ExtensionMethods
    {
        public static bool IsNull(this object obj)
        {
            return obj == null;
        }

        public static bool IsNotNull(this object obj)
        {
            return obj != null;
        }

        public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
        {
            return enumerable.IsNull() || !enumerable.Any();
        }

        public static bool IsLessThan(this int number, int value)
        {
            return number < value;
        }

        public static bool IsFalse(this bool bln)
        {
            return bln == false;
        }
    }

}

I’d be interested to hear your thoughts on better ways to debug within Visual Studio. Please share them with me via twitter or email.

The i-Stay Fineline Laptop Bag

i-Stay Fineline Laptop Bags

Photo: Andy Crouch

I work remotely a lot of the time. But, as my role has developed I travel more and carry my office with me. I am always trying new laptop bags in an effort to find the balance between space and weight.

For many years I have used STM bags. Before that Pakuma which, unfortunately, have ceased trading. I have tried all kind of messenger bags, briefcases and backpacks.

For a long time, especially while I rode a motorbike, I settled on backpacks. They are functional but at a cost. I find that using them damages clothing, especially wool based clothing.

I decided to try a messenger type bag again recently and after much research, I have opted for an i-Stay Fineline. This is a fairly standard laptop and tablet bag. Given its slim nature, it has a number of compartments and pockets. It takes a laptop to 15.6” and a tablet up to 12”. I can easily get a power brick in along with pens, moleskin and various charging cables. The outer flap has a large zipped pocket and the rear has a velcro fastened flap for magazines or paperwork. All in all a slim, neat and waterproof bag.

The standout point on the bag though is the strap. If you have used a messenger bag with a material strap you will know they are no good at staying on your shoulder. As you walk, it moves and slips and you are forever pulling the bag back onto your shoulder. The i-Stay has a rubber shoulder strap which goes nowhere. If you run with a full bag, it doesn’t move. It is the bags USP and it works.

This isn’t meant to be any kind of endorsement for the bag but it is one of the better slim laptop bags I have used. If you don’t need to carry the kitchen sink with you on your daily commute, you should check it out.

I’d love to hear your recommendations on laptop bags and which you use. Please share them with me via twitter or email.

Microsoft Has Purchased Github

Microsoft PC Showing Getting Ready Message

Photo: Johny vino - Unsplash

So the news has been confirmed that Microsoft has brought GitHub for $7.5 billion. Rumours first started to circulate late last week. The deal was officially disclosed yesterday.

I have been around both the Open Source and Microsoft communities for over 20 years. The reactions are predictable, in some cases quite funny but also unfair. Obviously, from the Microsoft side, there is nothing but general praise and excitement. From the OSS side there seem’s to be two main camps:

  • Those who were around for the Steve Ballmer driven onslaught on Linux. They remember the “cancer” comment. They remember the sponsorship of SCO while they tried to sue various Linux companies and developers. Worse yet are the younger generation who have been fed the war stories of old greybeards during which the details have been elaborated over time.

  • Those who totally get that Github is a rare unicorn. They built a great product at the right time for the right user base that had a need. Users of Github who have used it to power fantastic projects and power great products.

I for one think that the deal is good. Github, while suffering numerous (and normal) growing pains have been rewarded for their hard work. Microsoft picks up some amazing talent and the projects hosted on Github get continuity and the resources to power it for years to come. The also get an experienced and highly influential leader in Nat Friedman.

Fun times ahead.

What are your thoughts on Microsoft buying Github? Please share them with me via twitter or email.

Pixel 2

Picel 2

Photo: Andy Crouch

After 2 solid years of use my Nexus 5x finally died. No warning, no signs, it just died. I would argue that 2 years for a phone is not that long. I appreciate I am on it a lot and am an above average use type user. Then again, I am getting older and my expectations are perhaps excessive.

So I upgraded to a Pixel 2. This was a phone that I was actually excited to get rather than just an upgrade. But, I have to be honest and say that after some initial use I am disappointed.

First the good. The thing I love about the Google phones is stock Android. You get the latest version of Android almost as soon as it is released. Their launcher is far better than any others I have tried. The phone itself is very well built and the lack of physical buttons on the front makes it very slick. On the side, you just have power and volume. The performance I have found to be excellent and it comes with 64gb of storage. On the rear is a 12.2-megapixel camera and flash.

Now the not so good. First up, only one USB C connection. I am sure that USB C is going to dominate at some point but it doesn’t yet. No headphone jack. This is a massive issue and a pain I know felt by iPhone users. But, they have Airpods. Google released Buds but they have flopped and flopped hard. This seems to be one of the less harsh reviews. The next issue is the USB C to phono converter they supply. It’s about 1.5 inches which makes the phone about 7 inches long when plugged in. You need deep pockets to accommodate that. It makes it really uncomfortable when you are sitting down so you are forced into buying a good pair of Bluetooth headphones.

Charging is very quick but only if you use the official charger. If you use a converter to make USB C fit in any standard USB port then it charges so slowly you might as well not bother.

Finally, due to its size, the phone is hard to use one-handed. If you try to type single-handed you find you mishit keys and write gibberish.

On the whole, the phone is good but it’s not great. It had the potential to really show how great an Android device can be. Unfortunately, they allowed Samsung to do that instead and given their horrendous UI that is a shame.

I’d love to hear your thoughts on the Pixel and on alternatives worthy of looking at. Please share them with me via twitter or email.

Online vs Offline Shopping

Woman Looking At Food On Market Stall

Photo: Unsplash

This is a very opinionated piece. If I offend I do not mean to but you have been warned.

The high street as we know it will not survive.

The writing has been on the wall for a long time. But, I still hear people moaning about the impact that technology is having on the sector. How shops are not as good as they used to be and how they are more expensive and how few of them there are.

I hate shopping and I am a technologist. I am probably the worst person to comment on this. I love the way that technology has opened up choice and reduced cost. As a consumer, they are the two most important factors when I need to shop. Online retailers get that by:

  • Not having a physical presence on the high street. They limit themselves to warehouses (which are mostly automated as far as they can be). This reduces overheads.

  • They are (mostly) cheaper than the high street. Reduced overheads, bulk buying and automation all lead to savings for the customer.

  • They are available 24/7. I can shop when I want or need to. I am not limited by retailers opening hours. (Which in the UK is still governed by the church. Really, people, it is a 24/7 economy in 2018!)

No matter how much high street retailers can buy in bulk, they do not automate and they have overheads. Those overheads are for staff and premises. I am surprised that none of the big UK supermarkets has experimented with Robotics. This appears to be the answer to the staff issue. Automate the restocking process and having self-serve tills would reduce their wages bill. I am not convinced that they would actually pass on the savings to customers. I am sure the shareholders would have something to say about that. They are always looking at the short term annual profit rather than longer-term survival.

The Self service tills are a good case in point. All UK Supermarkets and a lot of the high street shops now offer them. They allow a customer to take their purchases to a till to scan and pay for them. They have been going in one form or another in the UK for about 10 years and they are still awful. I mean they really suck. If I was the designer of these things I would cringe that I made them so bad. They are slow, prone to go wrong and panic. As soon as it is not possible to determine what needs to be done it summons a human. They are unable to verify for age restrictions and so most shops have to have a cashier on hand per 4 self-serve tills. That’s right, someone designed a solution to cashiers and it still requires a cashier. Let that sink in.

The other point worth considering on self-serving tills is that you do not save money as a customer. The company makes you scan your own goods. They effectively making you a cashier for the duration of the transaction. Yet who profits? Not the consumer but the retailer. Even though they do not pay someone to help complete your transaction you still save no money. Again, let that sink in.

I have a lot more to say about choice and cost but this piece is turning into a rant which was not it’s purpose.

Next to choice and price, I and a lot of other shoppers value time. Time is limited for people. They would prefer to spend it when not working with their families and friends. Here also retailers get it so very wrong. Why on a Tuesday night at 6 pm do they have only 3 tills open (out of 24)? Their overheads once again. Evening pay is more expensive than during the day.

The trouble is that no one has looked to change things from within the industry. It is taking Amazon to rethink the shopping experience. A technology company. Their shop in Seattle has no cashiers and no tills. That’s right. You walk in with an app on your phone and pick up what you want and walk out. Your goods are just charged to your Amazon account. No time wasted waiting, No trying to ensure a badly designed machine is weighing your cookies right. Just in and out. I know of at least 3 UK supermarkets that are working on similar technology. But, I wonder whether their extended technology development cycles will be their downfall. Will Amazon make it’s expected entry into the UK market? Will it just be what we have all been waiting for?

I know it will be for me.

I’d love to hear your thoughts on retail and the impact that technology is having. Please share them with me via twitter or email.