Gotchacode

A Guide To Your Digital Life.

Simple State Machine Framework in C#

| Comments

This blog post covers a very simple, light weight, yet flexible state machine framework in C# .Net.

Souce code on Github

Download NuGet package

Concept

State : The state of a stateful entity. Represented by IState

Stateful entity : An entity that has a defined state. Represented by IStatefulEntity

Context : A context in which a state machine executes a transition. It is simply a set of configuration and data that governs the execution of a state machine. Represented by IStateMachineContext

Transition handler : A component that handles a transition of a stateful entity between a source state to target state. Represented by ITransitionHandler

Usage

Start by creating an entity that represents a state.

1
2
3
4
5
6
7
    public class ServiceTicketState : IState
    {
        public string Code { get; set; }
        public string Name { get; set; }
        // ...
    }

Now, create a stateful entity by implementing IStatefulEntity interface. For exmaple:

1
2
3
4
5
6
public class ServiceTicket : IStatefulEntity<ServiceTicketState>
{
    public ServiceTicketState State { get; set; }
    public string Name { get; set; }
    // ...
}

Next comes transition handlers. A transition hadler is created by implementing ITransitionHandler interface. Below is an example of a generic transition handler that can be used to abstract common functionalities in our Service Ticket example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    public class GenericTransitionHandler : ITransitionHandler<ServiceTicket, ServiceTicketState>
    {
        public virtual string TransitionKey { get { return ""; } }

        public virtual ServiceTicket Execute(ServiceTicket entity, ServiceTicketState nextState, IDictionary<string, object> argumentsMap = null)
        {
            entity.State = nextState;
            return entity;
        }

        public virtual ServiceTicket ValidateTransition(ServiceTicket entity, ServiceTicketState nextState, IDictionary<string, object> argumentsMap = null)
        {
            return entity;
        }

        public virtual void BeforeTransition(ServiceTicket entity, IDictionary<string, object> argumentsMap = null)
        {

        }

        public virtual void AfterTransition(ServiceTicket entity, IDictionary<string, object> argumentsMap = null)
        {

        }
    }

Next and final step is to create a ‘context’ by implementing IStateMachineContext interface. This interface declares following methods that need to be implemented to create a context.

1
2
3
ICollection<StateTransition> GetTransitions();
IDictionary<string, ITransitionHandler<T,M>> GetTransitionHandlersMap();
ICollection<M> AllStates();

Implementation approach is left to the user. It could from just hard coding for simple cases to database backed storage and retrieval for more advanced cases.

Here is an example implementation (hard coded for simplicity)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public ICollection<StateTransition> GetTransitions()
    {
        ICollection<StateTransition> map = new List<StateTransition>();
        // Define all possible transitions, and its source and target states
        map.Add(new StateTransition("?", "Transition_New", "New")); // ? means null or undefined state
        map.Add(new StateTransition("New", "Transition_Open", "Open"));
        map.Add(new StateTransition("Open", "Transition_Close", "Closed"));
        map.Add(new StateTransition("Closed", "Transition_ReOpen", "Open"));
        map.Add(new StateTransition("?", "Transition_Cancel", "Cancelled"));

        return map;
    }

    public IDictionary<string, ITransitionHandler<ServiceTicket, ServiceTicketState>> GetTransitionHandlersMap()
    {
        IDictionary<string, ITransitionHandler<ServiceTicket, ServiceTicketState>> map = new Dictionary<string, ITransitionHandler<ServiceTicket, ServiceTicketState>>();
        // create a map of all available transitions and their respective transition handlers
        map.Add("Transition_New", new NewTransitionHandler());
        map.Add("Transition_Open", new OpenTransitionHandler());
        map.Add("Transition_Close", new CloseTransitionHandler());
        map.Add("Transition_ReOpen", new OpenTransitionHandler());

        return map;
    }

    public ICollection<ServiceTicketState> AllStates()
    {
        List<ServiceTicketState> states = new List<ServiceTicketState>();
        // create a list of all possible states
        states.Add(new ServiceTicketState() { Code = "New", Name = "New Ticket" });
        states.Add(new ServiceTicketState() { Code = "Open", Name = "Ticket Open" });
        states.Add(new ServiceTicketState() { Code = "Closed", Name = "Ticket Closed" });
        states.Add(new ServiceTicketState() { Code = "Cancelled", Name = "Ticket Cancelled" });

        return states;
    }

Now ServiceTicket entity can be transitioned through state machine. Create an instance of StateMachine as follows.

1
2
        IStateMachineContext<ServiceTicket, ServiceTicketState> context = new ExampleStateMachineContext();
        StateMachine<ServiceTicket, ServiceTicketState> StateMachine = new StateMachine<ServiceTicket, ServiceTicketState>(context);

And request a transition as shown below.

1
2
3
4
5
6
        ServiceTicket serviceTicket = new ServiceTicket()
        {
             Name = "An example service ticket"
        };

        StateMachine.RequestTransition(serviceTicket, "Transition_New");

And thats it. Your state machine is ready to handle transitions on the Service Ticket example entity.

Setup a Local Gitignore Without Messing Up Project

| Comments

A lot of us use Git for Version Control. If you have used git, you must be aware of .gitignore files. It contains the list of all file and directories you want git to ignore so that it would nevet get committed. But if you work in multi person team. You might not have liberty to change the projects gitignore. What to do then?

Well, the solution is pretty simple. Say you are using any IDE like Pycharm or Netbeans. They always create some files to create track of your projects. Something like .ropeproject

So in order to make git ignore it, Go to : cd .git/info/

You see there is a file called exclude. Fill it up with the files and directories you want it to ignore, just like the gist below:

And it is done. Now you never have to worry about your editor messing up your commits.

How to Use Facebook Page Albums as Image Source in Django

| Comments

Lot of companies use Facebook for marketing their products. Facebook is mainly built around images. In fact the whole ecosystem is fueled by images. In order to scale for the vast user base of Facebook, they have done a really good job.

So what if you don’t want to use your own storage for uploading images and want to use Facebook for Images? It would be so cool, right? There are two benefits:

  • You don’t have to spend anytime setting up an app or service to deal with images. Believe me it is a real tough problem to solve given the size and count of images. You can’t put a bar on either of these two.
  • It gives your users a much user friendly way. They upload images just once on Facebook and it auto-magically appears on your website. Facebook almost never gets down so there is very good chance you will get a 99.9% uptime.

So, In order to fix this problem last year I created a Ajax based plugins to fetch images from Facebook album. It asked user to enter album URL and name. But there was an issue with this approach. In order to get access to Facebook graph database it has to get access tokens and each access token only last two months. Plus, it collapsed when it faced IE, since there is unsolvable CORS issue with IE < 9 (our 50% client base for that project).

It was a tough problem to solve. But i finally found some good articles and projects on Internet. One such project was django-fbgallery. It used a really neat approach to get the Facebook images server side and renders it the page purely server side. It not only solved the IE issue, but also the quality and speed of image loading became instant.

But there was an issue with this app, it used URLS to render the albums and spoiled the pretty URLS that you would like for pages in Django. So I took the core part of the app ( the Facebook interaction part) and made a sweet CMS plugin out of it.

Here is the code to make it all work:

Facebook.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from django.conf import settings
from django.core.cache import cache
import urllib2, urllib
import django.utils.simplejson as json
from django.template import defaultfilters


fql_url = 'https://api.Facebook.com/method/fql.query'
cache_expires = getattr(settings, 'CACHE_EXPIRES', 30)

def get_fql_result(fql):
    cachename = 'fbgallery_cache_' + defaultfilters.slugify(fql)
    data = None
    if cache_expires > 0:
        data = cache.get(cachename)
    if data == None:
        options = {
            'query':fql,
            'format':'json',
        }
        f = urllib2.urlopen(urllib2.Request(fql_url, urllib.urlencode(options)))
        response = f.read()
        f.close()
        data = json.loads(response)
        if cache_expires > 0:
            cache.set(cachename, data, cache_expires*60)
    return data

def display_album(album_id):
    """Display a Facebook album

    First check that the album id belongs to the page id specified
    """
    fb_id = settings.FB_PAGE_ID
    fql = "select aid, name from album where owner=%s and aid='%s'" % (fb_id, album_id)
    valid_album = get_fql_result(fql)
    if valid_album:
        fql = "select pid, src, src_small, src_big, caption from photo where aid = '%s'  order by created desc" % album_id
        album = get_fql_result(fql)
        #album_detail = [item for item in valid_album]       
        return album

I asked user to enter the album ID and name, then rendered the album using the plugin here:

cms_plugins.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from django.utils.translation import ugettext_lazy as _
from Facebook import display_album

from models import FacebookGallery

class FacebookGalleryPlugin(CMSPluginBase):
    model = FacebookGallery
    name = _("Facebook Album Gallery")
    render_template = "cmsplugin_fbgallery/album.html"

    def render(self, context, instance, placeholder):
        album = display_album(instance.album_id)
        context.update({
          'object': instance,
          'album': album,
          })
        return context

plugin_pool.register_plugin(FacebookGalleryPlugin)

You could choose whatever template you want. It’s entirely upto you.

Here is the image of this plugin live in action:

The plugin is open sourced here: cmsplugin-fbgallery . Feel free to contribute and ask questions.

Migrating to Octopress

| Comments

Finally after much ado, I am moving Gotchacode to Octopress. There are various reasons for doing it. I am listing some of them here:

  • There is absolutely no good theme if you are running a technical blog.
  • Syntax highlighting is pathetic.
  • I can’t write post in my text editor.
  • There is no source control.

But I will miss blogspot too. The integrated analytics was best in class and so was the SEO.

Music, Movies and Life

| Comments

I love watching Movies and I love Music. They are almost inseperable part of life. I love the way they could touch and move your life more than you could imagine. I remember watching “The Social Network” almost 50 times in college. It served as a push to write more code and do awesome in life.

Well, it might sound really strange but for last 10 years or so. I just let life flow in the natural way. I failed quite sometimes, achieved success as well. Made some long lasting friends, lost some people I felt who were my friends.

The great thing is that in all these experiences, I realised that what is the true purpose of my life. They say, there are just two important days in your life.

The day when you are born, and the day you find out why?
I think I just found out the purpose of my life. It’s not something I would want to disclose and claim I am going to achieve. It is the way my thinking changed and the choice of life I am going to make.

Also, I would love to thank the wonderful readers of this blog - which initially started casually just to empty my mind on topics I felt were relevant at that time. For sure there are some not so good posts as well. But again, this blog is just me writing what comes in my mind. And if some of those helps someone or guide someone. Why not?

Happy New Year 2014

| Comments

A very happy new year to all the readers of this blog. To start with, I would try to publish a post at least once a week so that it may satisfy your appetite on a regular basis. Also, I am meditating about something new on this blog. It will be revealed when the time comes. With that said, have an amazing start to the year.

Using HTML5 localStorage Into Your App, Check ldb.js

| Comments

Last night, I was hacking on a small utility library for use when using HTML5 localStorage. When you work with localStorage, it often gets into repetitive state when use use same command again and again. This library just abstracts the process and makes things easier for you. It would work on all modern browsers.

/**
* Ldb.js
* Copyright(c)2013 Vinit Kumar
* MIT Licensed
*/

var Ldb = function () {};

/**
* [check Checks for localStorage support on the browsers]
* @return {[String]} [status of localStorage Support]
*/
Ldb.prototype.check = function () {
if (!localStorage) {
return 'Please use a Modern browser, your browser does not support localStorage yet';
} else {
return 'Bingo, your Browsers supports localStorage, phew!';
}
};

/**
* [get Gives the data stored in the key]
* @param {[String]} key [Key to retrive the data stored in localStorage]
* @return {[JSON]} [The JSON data stored | Error message saying no data stored with that key]
*/
Ldb.prototype.get = function (key) {
if (localStorage.getItem(key)) {
return JSON.parse(localStorage.getItem(key));
} else {
return 'No such key exists, Are you sure you have saved data with the key?';
}
};

/**
* [set Saved data in the localStorage database]
* @param {[String]} key []
* @param {[JSON]} value [The JSON data that gets stored in the localStorage]
*/
Ldb.prototype.set = function(key, value) {
if (typeof (value) === 'object') {
var stringValue = JSON.stringify(value);
localStorage.setItem(key, stringValue);
return 'Successfully saved your data to the key' + key +' key!';
}
};

/**
* [remove description]
* @param {[String]} key [Key for the data to be deleted]
* @return {[String]} [Status message for the remove operation]
*/
Ldb.prototype.remove = function(key) {
if (localStorage.getItem(key)) {
localStorage.removeItem(key);
return 'Successfully removed data with the key'+ key +' !';
} else {
return 'No such key exists, nothing to remove';
}
};



This is all code for the utility as of now. More features are going to flow in coming weeks. Also, you can just install it using ‘npm install ldb’ or ‘bower install ldb.js’. The code is Open Sourced here. https://github.com/vinitkumar/ldb.js

How to Focus and Learn One Thing Perfectly?

| Comments

In Software development, there are so many things to learn. Especially, if you are web developer there are so many things to learn. Should you learn Rails, Django or .NET? Or should you learn Angular, Backbone or Ember?

It is a very tricky question and has been puzzling me for quite sometime. But some time back, it kind of dawned on me that I should just try and own one technology at one time. Say if it’s Django try and learn everything about Django. Become the best in your company at Django. The benefits are two fold:
- You will have a stable career and you will be happy with the quality of your work.
- You can use that understanding of that technology with understanding and learning other technologies really fast.

Another problem that I sometime face is lack of motivation to learn if something gets really tough. I learned that instead of setting a super tough goal, I should rather split it up and own it one by one. First of all, it gives me a sense of achievement and confidence. Also, my whole effort would be on completing that goal with best of my abilities.

The things I said above is not rocket science, but if you are at my stage of learning. It might be useful to you.


With that said, May the Force be with you!

                ____                  
_.' : `._
.-.'`. ; .'`.-.
__ / : ___\ ; /___ ; \ __
,'_ ""--.:__;".-.";: :".-.":__;.--"" _`,
:' `.t""--.. '<@.`;_ ',@>` ..--""j.' `;
`:-.._J '-.-'L__ `-- ' L_..-;'
"-.__ ; .-" "-. : __.-"
L ' /.------.\ ' J
"-. "--" .-"
__.l"-:_JL_;-";.__
.-j/'.; ;"""" / .'\"-.
.' /:`. "-.: .-" .'; `.
.-" / ; "-. "-..-" .-" : "-.
.+"-. : : "-.__.-" ;-._ \
; \ `.; ; : : "+. ;
: ; ; ; : ; : \:
; : ; : ;: ; :
: \ ; : ; : ; / ::
; ; : ; : ; : ;:
: : ; : ; : : ; : ;
;\ : ; : ; ; ; ;
: `."-; : ; : ; / ;
; -: ; : ; : .-" :
:\ \ : ; : \.-" :
;`. \ ; : ;.'_..-- / ;
: "-. "-: ; :/." .' :
\ \ : ;/ __ :
\ .-`.\ /t-"" ":-+. :
`. .-" `l __/ /`. : ; ; \ ;
\ .-" .-"-.-" .' .'j \ / ;/
\ / .-" /. .'.' ;_:' ;
:-""-.`./-.' / `.___.'
\ `t ._ / bug
"-.t-._:'





What Is Information Overload and What to Do About It?

| Comments

Each one of us uses one Social Network or another. It was fine in the earlier days when it was connecting you to your long lost friend, colleague or someone you knew. But do we realize what it is doing to us now?

We are being subjected to information overload and that too in the worst form. There are endless stories about all the stuff that doesn’t even matter to us. We are being fed so much about our friends that we are not even interested to know about them anymore. Sharing every crap that happens in your life is a common norm and anyone who doesn’t stick to it is dated. 

Well, that fact is, we should just shut this information overload and take control of our life. We don’t really need to be subjected to this and become depressed and deprived people. Life has better meaning than all of it. We are born to do great things in life and not being sucked into this emotional and depressing wormhole that these Social Networks are creating.

With that said, not all of the Social Networks are bad. Some of them like Twitter and Google+ gives us the option to minimise the intrusion of this excess information. So take a stand and control what kind of information gets to you. Clean up your friends and following list. Follow only those person and group you are really passionate  about. Pick up some nice offline activity, meet some nice people , play some music, watch sunrise or sunset, start running etc. There are so many nice things to do. So just shut up laptop/tablets/smartphones and get some life people!

Happiness Driven Development

| Comments

Software development could be a very tiring and demanding process. Putting 80 hour weeks running after a goal that may or maybe not be achieved and then getting into depression is not right.

One should optimise his work and workplace for happiness. Setup small easy goals that you could really achieve and celebrate it every time. It is good to be ambitious but it is insanely stupid to make super tough goal with out some real practise.

Start small,  reach your goal and next time try to do it more efficiently. People say that ‘Failures are the pillars of success’ , I would humbly disagree. It is these small successes that are pillars of some big successes. Look around yourself. Just take chess for example: Someone doesn’t becomes a grandmaster because he had been defeated by every other grandmaster. Likewise don’t obsess with failure. Better start winning by doing something nice today however small it maybe.

Failure is a good thing to do some self evaluation and getting better where it’s needed.  Treat it as a unit test, so that you know what tests are failing and what you could do to solve them. Solve them and come out with flying colors.

Life is way too small to waste and be sad and depressed.
Think about it! :)