Development and Chekhov’s Gun

“Remove everything that has no relevance to the story. If you say in the first chapter that there is a rifle hanging on the wall, in the second or third chapter it absolutely must go off. If it’s not going to be fired, it shouldn’t be hanging there.”

  • Anton Chekhov 

Chekhov’s gun is a fascinating literary principle that we should be applying to software and app development. In literary terms, Chekhov’s gun means that you should only introduce elements into the story if they are relevant in the story. Similarly, when we develop systems, we need to consider where it adds to the user experience, which is part of a user-centred design.

As any great storyteller can relate, it isn’t enough to give the facts. The reader is on a journey with you and how you lead them determines how they feel about this journey. The same principle applies to system development. How we conduct our user through our systems determines the way they relate to our systems. This journey is something that Apple has managed to master, from the iPod to the iPhone, and users enjoy the experience because it is simple for them. 

Does this mean that all we have to do is create simple interfaces for our users to be happy? Not exactly. The User Experience journey applies to all aspects of our system, including a user’s first exposure to our company and services; and the ability to provide feedback. It is of no use to say to customers your opinions matter and never do anything about their views.

Do you understand what your average user is trying to achieve in a particular session? If you don’t have a clear understanding of this, it becomes harder to remove the elements that have no relevance. This need for insight is why User Research should be an essential part of any development process since it helps give you more knowledge of the user’s behaviour. This knowledge will only get you so far, and it is up to you to use it to improve the user interactions with your system. 

Passing variables from C# MVC Controller to AngularJS using Razor

I wanted to pass some data from my MVC but didn’t want to go the hassle of creating a separate WebAPI call and Angular service, so I used the Angular module’s value method. Then I could inject those variables individually into any controller or services that I wanted to.

HomeController.cs

1
2
3
4
5
6
7
8
public ActionResult Index()
{
  return View(new MyModel {
    Id = Guid.NewGuid(),
    Name = "My Name",
    Value = 42
  });
}

Index.cshtml

1
2
3
4
5
6
7
8
9
10
11
@section scripts {
 <script src="~/Scripts/angular.js"></script>
 <script src="~/App/app.js"></script>
 <script>
 angular.module('myApp').value({
 id: '@Model.Id',
 name: '@Model.Name',
 value: @Model.Value,
 });
 </script>
}

App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(function () {
    angular.module('myApp', []);
 
    angular.module('myApp').controller('myController', myController);
    myController.$inject = ['id', 'name', 'value'];
 
    function myController(id, name, value) {
 
        var vm = this;
 
        vm.id = id;
        vm.name = name;
        vm.value = value;;
    }
})();

It is also possible to inject the data as one object by doing the following:
Index.cshtml

1
2
3
4
5
6
7
8
9
10
11
@section scripts {
  <script src="~/Scripts/angular.js"></script>
  <script src="~/App/app.js"></script>
  <script>
  angular.module('myApp').value('mydata', {
    id: '@Model.Id',
    name: '@Model.Name',
    value: @Model.Value,
   });
 </script>
}

App.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(function () {
    angular.module('myApp', []);
 
    angular.module('myApp').controller('myController', myController);
    myController.$inject = ['mydata'];
 
    function myController(mydata) {
 
        var vm = this;
 
        vm.id = mydata.id;
        vm.name = mydata.name;
        vm.value = mydata.value;;
    }
})();

If Triathlons were organised like Bad Software Projects

So you decide to sign up for a triathlon and you get told you will be swimming 100m, cycling 20kms and running 5kms – which you figure is okay. You can do that even though you are not the best swimmer out there 100m isn’t that far. So you start training getting ready for the big race, you are lean, mean and mentally prepared for the challenges ahead. You have mapped out how long each of the legs will take, you should make it home comfortably, your training has gone well, you have never been fitter. Continue reading

AngularJS and $httpBackend

I was helping out someone with their first attempt at an AngularJS website and they sent me the html and javascript file. The problem was that they used a web service to which I don’t have access so I needed a way to simulate that web service. I thought about writing my own version of the MVC web service but that seemed like overkill for what should just be a quick project. What I did find was $httpBackend which you can use to mock $http call with, the documentation for $httpBackend is here

The code is also on JSFiddle

Continue reading

Amoq – Liberating Funiture

The redesign of Amoq’s website is finally finished and live, check it out here: Amoq.co.za
The site is built using Drupal 6 and makes extensive use of JQuery and JavaScript to create a more interactive experience. In the next couple of weeks or so their online shop will be live, so you can get their cool products directly from them.

C# Bindable Dictionary

I came across this BindableDictionary at StackOverflow and I thought I would improve on it and here is the result:

 
    public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IBindingList, IRaiseItemChangedEvents
    {
        public SortedList<TKey, TValue> _Source = null;
 
        private ListChangedEventHandler listChanged;
 
        private bool raiseItemChangedEvents = false;
        private bool raiseListChangedEvents = true;
 
        [NonSerialized()]
        private PropertyDescriptorCollection itemTypeProperties = null;
 
        [NonSerialized()]
        private PropertyChangedEventHandler propertyChangedEventHandler = null;
 
        [NonSerialized()]
        private int lastChangeIndex = -1;
 
        #region Properties
        #region IBindingList
        //Gets whether you can update items in the list. 
        bool IBindingList.AllowEdit
        {
            get
            {
                return true;
            }
        }
 
        //Gets whether you can add items to the list using AddNew. 
        bool IBindingList.AllowNew
        {
            get
            {
                return false;
            }
        }
 
        //Gets whether you can remove items from the list, using Remove or RemoveAt. 
        bool IBindingList.AllowRemove
        {
            get
            {
                return true;
            }
        }
 
 
        //Gets a value indicating whether the IList has a fixed size. (Inherited from IList.)
        bool System.Collections.IList.IsFixedSize
        {
            get { return false; }
        }
 
        //Gets a value indicating whether the IList is read-only. (Inherited from IList.)
        bool System.Collections.IList.IsReadOnly
        {
            get { return true; }
        }
 
        //Gets whether the items in the list are sorted. 
        bool IBindingList.IsSorted
        {
            get
            {
                return false;
            }
        }
 
        //Gets a value indicating whether access to the ICollection is synchronized (thread safe). (Inherited from ICollection.)
        bool ICollection.IsSynchronized
        {
            get { return false; }
        }
 
        //Gets or sets the element at the specified index. (Inherited from IList.)
        object System.Collections.IList.this[int index]
        {
            get { return _Source[_Source.Keys[index]]; }
            set { _Source[_Source.Keys[index]] = (TValue)value; }
        }
 
        //Gets the direction of the sort. 
        ListSortDirection IBindingList.SortDirection
        {
            get
            {
                return ListSortDirection.Ascending;
            }
        }
 
        //Gets the PropertyDescriptor that is being used for sorting. 
        PropertyDescriptor IBindingList.SortProperty
        {
            get { return null; }
        }
 
        //Gets whether a ListChanged event is raised when the list changes or an item in the list changes. 
        bool IBindingList.SupportsChangeNotification
        {
            get { return true; }
        }
 
        //Gets whether the list supports searching using the Find method. 
        bool IBindingList.SupportsSearching
        {
            get { return false; }
        }
 
        //Gets whether the list supports sorting. 
        bool IBindingList.SupportsSorting
        {
            get { return false; }
        }
 
        //Gets an object that can be used to synchronize access to the ICollection. (Inherited from ICollection.)
        object ICollection.SyncRoot
        {
            get { return null; }
        }
        #endregion
 
        #region IDictionary
        //Gets a value indicating whether the ICollection<(Of <(T>)>) is read-only. (Inherited from ICollection<(Of <(T>)>).)
        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
        {
            get { return ((ICollection<KeyValuePair<TKey, TValue>>)_Source).IsReadOnly; }
        }
 
        //Gets or sets the element with the specified key. 
        public TValue this[TKey key]
        {
            get
            {
                return _Source[key];
            }
            set
            {
                bool bAdded = false;
                if (_Source.ContainsKey(key))
                {
                    bAdded = true;
                }
                _Source[key] = value;
                if (bAdded)
                {
                    if (this.raiseItemChangedEvents)
                    {
                        HookPropertyChanged(value);
                        OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, _Source.IndexOfKey(key)));
                    }
                }
            }
        }
 
        //Gets an ICollection<(Of <(T>)>) containing the keys of the IDictionary<(Of <(TKey, TValue>)>). 
        public ICollection<TKey> Keys
        {
            get { return _Source.Keys; }
        }
 
        //Gets an ICollection<(Of <(T>)>) containing the values in the IDictionary<(Of <(TKey, TValue>)>). 
        public ICollection<TValue> Values
        {
            get { return _Source.Values; }
        }
 
        #endregion
 
        //Gets the number of elements contained in the ICollection. (Inherited from ICollection.)
        //Gets the number of elements contained in the ICollection<(Of <(T>)>). (Inherited from ICollection<(Of <(T>)>).)
        public int Count
        {
            get { return _Source.Count; }
        }
 
        #endregion
 
        #region Methods
        #region IBindingList
        //Add function not implemented use other Add function instead
        //Adds an item to the IList. (Inherited from IList.)
        int System.Collections.IList.Add(object value)
        {
            throw new NotImplementedException();
        }
 
        //Adds the PropertyDescriptor to the indexes used for searching.
        void IBindingList.AddIndex(PropertyDescriptor property)
        {
        }
 
        //Adds a new item to the list. 
        object IBindingList.AddNew()
        {
            return null;
        }
 
        //Sorts the list based on a PropertyDescriptor and a ListSortDirection. 
        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
        }
 
        //Determines whether the IList contains a specific value. (Inherited from IList.)
        bool System.Collections.IList.Contains(object value)
        {
            if (value is TKey)
            {
                return _Source.ContainsKey((TKey)value);
            }
            else if (value is TValue)
            {
                return _Source.ContainsValue((TValue)value);
            }
            return false;
        }
 
        //Copies the elements of the ICollection to an Array, starting at a particular Array index. (Inherited from ICollection.)
        void ICollection.CopyTo(Array array, int arrayIndex)
        {
            ((ICollection)_Source).CopyTo(array, arrayIndex);
        }
 
        //Returns the index of the row that has the given PropertyDescriptor. 
        int IBindingList.Find(PropertyDescriptor property, object key)
        {
            throw new NotImplementedException();
        }
 
        //Returns an enumerator that iterates through a collection. (Inherited from IEnumerable.)
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        //Determines the index of a specific item in the IList. (Inherited from IList.)
        int System.Collections.IList.IndexOf(object value)
        {
 
            if (value is TKey)
            {
                return _Source.IndexOfKey((TKey)value);
            }
            else if (value is TValue)
            {
                return _Source.IndexOfValue((TValue)value);
            }
            return -1;
        }
 
        //Inserts an item to the IList at the specified index. (Inherited from IList.)
        void System.Collections.IList.Insert(int index, object value)
        {
            throw new NotImplementedException();
        }
 
        //Removes the first occurrence of a specific object from the IList. (Inherited from IList.)
        void System.Collections.IList.Remove(object value)
        {
            if (value is TKey)
            {
                Remove((TKey)value);
            }
        }
 
        //Removes the IList item at the specified index. (Inherited from IList.)
        void System.Collections.IList.RemoveAt(int index)
        {
            _Source.RemoveAt(index);
        }
 
        //Removes the PropertyDescriptor from the indexes used for searching. 
        void IBindingList.RemoveIndex(PropertyDescriptor property)
        {
        }
 
        //Removes any sort applied using ApplySort. 
        void IBindingList.RemoveSort()
        {
        }
        #endregion
 
 
        #region IDictionary
        //Adds an item to the ICollection<(Of <(T>)>). (Inherited from ICollection<(Of <(T>)>).)
        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)_Source).Add(item);
 
            if (this.raiseItemChangedEvents)
            {
                HookPropertyChanged(item.Value);
                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, _Source.IndexOfKey(item.Key)));
            }
        }
 
        //Adds an element with the provided key and value to the IDictionary<(Of <(TKey, TValue>)>). 
        public void Add(TKey key, TValue value)
        {
            _Source.Add(key, value);
 
            if (this.raiseItemChangedEvents)
            {
                HookPropertyChanged(value);
                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, _Source.IndexOfKey(key)));
            }
        }
 
        //Determines whether the ICollection<(Of <(T>)>) contains a specific value. (Inherited from ICollection<(Of <(T>)>).)
        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
        {
            return ((ICollection<KeyValuePair<TKey, TValue>>)_Source).Contains(item);
        }
 
        //Determines whether the IDictionary<(Of <(TKey, TValue>)>) contains an element with the specified key. 
        public bool ContainsKey(TKey key)
        {
            return _Source.ContainsKey(key);
        }
 
        //Determines whether the IDictionary<(Of <(TKey, TValue>)>) contains an element with the specified key.
        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)_Source).CopyTo(array, arrayIndex);
        }
 
        //Returns an enumerator that iterates through the collection. (Inherited from IEnumerable<(Of <(T>)>).)
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return _Source.GetEnumerator();
        }
 
        //Removes the first occurrence of a specific object from the ICollection<(Of <(T>)>). (Inherited from ICollection<(Of <(T>)>).)
        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
        {
            int index = _Source.IndexOfKey(item.Key);
            if (index != -1)
            {
                if (this.raiseItemChangedEvents)
                {
                    UnhookPropertyChanged(item.Value);
                }
                ((ICollection<KeyValuePair<TKey, TValue>>)_Source).Remove(item);
                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
                return true;
            }
            return false;
        }
 
        //Removes the element with the specified key from the IDictionary<(Of <(TKey, TValue>)>). 
        public bool Remove(TKey key)
        {
            int index = _Source.IndexOfKey(key);
            if (index != -1)
            {
                if (this.raiseItemChangedEvents)
                {
                    UnhookPropertyChanged(_Source[key]);
                }
                _Source.Remove(key);
                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
                return true;
            } return false;
        }
 
        //Gets the value associated with the specified key. 
        public bool TryGetValue(TKey key, out TValue value)
        {
            return _Source.TryGetValue(key, out value);
        }
        #endregion
 
        //Removes all items from the IList. (Inherited from IList.)
        //Removes all items from the ICollection<(Of <(T>)>). (Inherited from ICollection<(Of <(T>)>).)
        public void Clear()
        {
 
            if (this.raiseItemChangedEvents)
            {
                foreach (TValue item in _Source.Values)
                {
                    UnhookPropertyChanged(item);
                }
            }
 
            _Source.Clear();
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
 
        private void Initialize()
        {
 
            // Check for INotifyPropertyChanged
            if (typeof(INotifyPropertyChanged).IsAssignableFrom(typeof(TValue)))
            {
                // Supports INotifyPropertyChanged
                this.raiseItemChangedEvents = true;
 
                // Loop thru the items already in the collection and hook their change notification.
                foreach (TValue item in _Source.Values)
                {
                    HookPropertyChanged(item);
                }
            }
        }
 
        //Send change notification
        protected virtual void OnListChanged(ListChangedEventArgs e)
        {
            var evt = listChanged; if (evt != null) evt(this, e);
        }
 
        public void ResetBindings()
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
 
        public bool RaiseListChangedEvents
        {
            get { return this.raiseListChangedEvents; }
 
            set
            {
                if (this.raiseListChangedEvents != value)
                {
                    this.raiseListChangedEvents = value;
                }
            }
        }
        #endregion
 
        #region Events
        #region IBindingList
        event ListChangedEventHandler IBindingList.ListChanged
        {
            add
            {
                listChanged += value;
            }
            remove { listChanged -= value; }
        }
        #endregion
        #endregion
 
        #region constructor
        public BindableDictionary()
        {
            _Source = new SortedList<TKey, TValue>();
            Initialize();
        }
 
        public BindableDictionary(IComparer<TKey> comparer)
        {
            _Source = new SortedList<TKey, TValue>(comparer);
            Initialize();
        }
        #endregion
 
 
        #region Property Change Support
 
        private void HookPropertyChanged(TValue item)
        {
            INotifyPropertyChanged inpc = (item as INotifyPropertyChanged);
 
            // Note: inpc may be null if item is null, so always check.
            if (null != inpc)
            {
                if (propertyChangedEventHandler == null)
                {
                    propertyChangedEventHandler = new PropertyChangedEventHandler(Child_PropertyChanged);
                }
                inpc.PropertyChanged += propertyChangedEventHandler;
            }
        }
 
        private void UnhookPropertyChanged(TValue item)
        {
            INotifyPropertyChanged inpc = (item as INotifyPropertyChanged);
 
            // Note: inpc may be null if item is null, so always check.
            if (null != inpc && null != propertyChangedEventHandler)
            {
                inpc.PropertyChanged -= propertyChangedEventHandler;
            }
        }
 
        void Child_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (this.RaiseListChangedEvents)
            {
                if (sender == null || e == null || string.IsNullOrEmpty(e.PropertyName))
                {
                    // Fire reset event (per INotifyPropertyChanged spec)
                    ResetBindings();
                }
                else
                {
                    TValue item;
 
                    try
                    {
                        item = (TValue)sender;
                    }
                    catch (InvalidCastException)
                    {
                        ResetBindings();
                        return;
                    }
 
                    // Find the position of the item. This should never be -1. If it is,
                    // somehow the item has been removed from our list without our knowledge.
                    int pos = lastChangeIndex;
 
                    if (pos < 0 || pos >= Count || !_Source.Values[pos].Equals(item))
                    {
                        pos = _Source.IndexOfValue(item);
                        lastChangeIndex = pos;
                    }
 
                    if (pos == -1)
                    {
                        UnhookPropertyChanged(item);
                        ResetBindings();
                    }
                    else
                    {
                        // Get the property descriptor
                        if (null == this.itemTypeProperties)
                        {
                            // Get Shape
                            itemTypeProperties = TypeDescriptor.GetProperties(typeof(TValue));
                        }
 
                        PropertyDescriptor pd = itemTypeProperties.Find(e.PropertyName, true);
 
                        // Create event args. If there was no matching property descriptor,
                        // we raise the list changed anyway.
                        ListChangedEventArgs args = new ListChangedEventArgs(ListChangedType.ItemChanged, pos, pd);
 
                        // Fire the ItemChanged event
                        OnListChanged(args);
                    }
                }
            }
        }
 
        #endregion
 
        #region IRaiseItemChangedEvents interface
 
        /// <include file='doc\BindingList.uex' path='docs/doc[@for="BindingList.RaisesItemChangedEvents"]/*' />
        /// <devdoc>
        /// Returns false to indicate that BindingList<T> does NOT raise ListChanged events
        /// of type ItemChanged as a result of property changes on individual list items
        /// unless those items support INotifyPropertyChanged
        /// </devdoc>
        bool IRaiseItemChangedEvents.RaisesItemChangedEvents
        {
            get { return this.raiseItemChangedEvents; }
        }
 
        #endregion
 
    }

Olivia Morgado Photography

Although this is not a new website, I finally got around to adding this site to my portfolio, which I should have done a while ago. I did this website for a very talented photographer and cinematographer Oliva Morgado and you can check out her website here. We took the design provided by Makers of Stuff and created a Drupal template for Olivia, then built the website so that Olivia could maintain her own images and categories.

 

WordPress 3.3.1 – Edit Meta Menu Widget

Okay, first thing I learnt while trying to set up this new website is how to edit the Meta Menu Widget in WordPress 3.3.1

One ways is to just remove the widget from Appearances > Widgets. Being that I didn’t feel like copying the links I actually wanted into a new widget I went in search of the php code that was behind the widget. I saw online references to widgets.php in the wp-includes folder but in 3.3.1 this does not contain the actual code for the Meta Widget. The php code for that widget is now located in default-widgets.php also found in the wp-includes folder. Search for the following to find the correct class:

class WP_Widget_Meta extends WP_Widget {

just below that on line 286 in default-widget.php is the function that builds the widget:

function widget( $args, $instance ) {

removing the <li>…</li> entries will remove the menu item, for example removing this line:

<li><?php wp_loginout(); ?></li>

will remove the Log out and Log in links.

Welcome to our new site.

Hi,

Finally I got around to doing something more with my site, until now it has been very much the case of the cobbler’s children having no shoes! I am starting to rectify that and what you see here is the start of that process. Of course, as always, other things especially paying things will take priority but