Thursday, August 01, 2013

Why innovators should not watch "Dragon's Den"

1. It is generally depressing - at the very best greedy rich and publicity-savvy will take advantage of ignorant naive and desperate.
2. Somebody else's bright (or not so bright) idea will affect your creative process, and maybe not in a good way.

P.S. Why innovators should watch "Dragon's Den":
1. If you weren't aware before - shark-infested waters are out there. Both judge- and contender-type people do exist in the real life - and you will encounter them, more likely than not.
2. Somebody else's bright (or not so bright) idea will affect your creative process, and maybe in a good way.

Friday, May 10, 2013

Why Business Analysts should understand ACID*

Good programmer should understand business domain. Really good programmer should understand business needs. Even mediocre Business Analyst must be interested in the technology at least at the same scale as being knowledgeable in business. The guy who handles you a 90-page specification saying: "Here is layout of our buttons - make them work" and disappears until Business Acceptance Testing stage - is just a very wrong person for the job.
Unless your project is a reinvention of a door bell, a lot of analysis is required after spec is done. Writing a specification of what a screen should do is a mere interpreter's job - translate language of business (either from customer's words or from general domain knowledge) to language which developers can comprehend. The real analysis should be applied to understand and predict how things will work when instead of humans (slow, inconsistent) or previous programs (outrageously old and poorly written) our new shiny application will take the load.
I struggled the most with this disconnect between BA's and developers while dealing with transactional data flows - be it database or service calls. A sequence of multiple interconnected actions requires a thorough inventory of all possible outcomes and analysis of subsequent scenarios. In 90% cases these decisions are outsourced to developers and if they don't know any better they make decisions which make sense only from the technical point of view.
The strategy of dealing with the outcome of the transactional process is a business decision, not technical. As a developer I always go for proper rollbacks or configurable re-attempts - but it could very well be what business doesn't need or even doesn't want (it may not even be possible - and you are fighting a half-day brain paralysis). This misunderstanding of business need will result either in an outright wrong logic (which is fixable) or in an over-engineering and significant waste (which will linger around for a long-long time).

So, please, please, Business People - don't roll your eyes when your techies will be asking for your preference between asynchronous callbacks and pub-sub patterns. They feel disturbance in a Force, but just having trouble expressing it in a humane way - be patient (and know your stuff).
Update: Starbucks concurs

*ACID - as from technology, not pharmacology.

Monday, April 29, 2013

Uncomfortable during the interview?

Imagining your interviewer naked may be a bad idea sometimes. No, wrong - it is always bad idea. Try this instead:


You know what to do with it, you just can not do worse.

P.S. Also these would be a great questions to fire in return: Interview Questions for Potential Employers

Sunday, April 28, 2013

ASP.NET + No-SQL. Part I - RavenDb

RavenDb is great native LINQ no-SQL database which is under active development. It has enormous community support and loads of resources which can help you get started (I wish they had this open course at my time).
Below is the code I ended up with after some time of polishing and tweaking and which finally worked for me. For a quick-start convenience I am providing the instructions in sequential steps.

1. Download and install RavenDB Client nuget package from Hibernating Rhinos.

2. Add "RavenDb" connection string to your web.config file. It is not necessary to use this name but if you'd ever consider AppHarbor hosting with one of the RaveDb add-ons, the deployment script will automatically place correct connection string if it will find "RavenDb" key. And we love automation.

3. The core access class for the Raven API is Document Store. It is expensive to create but it is thread-safe so we can use one singleton instance of it throughout our application life cycle. To achieve that we place the following code in out Global.asax.cs file:

private const string RavenSessionKey = "OpenHouseRaven.Session";
private static DocumentStore documentStore;

public WebApiApplication()
{
    BeginRequest += (sender, args) =>
        HttpContext.Current.Items[RavenSessionKey] = documentStore.OpenSession();
    EndRequest += (sender, args) =>
    {
        var disposable = HttpContext.Current.Items[RavenSessionKey] as IDisposable;
        if (disposable != null) disposable.Dispose();
    };
}
protected void InitializaeRavenDbStore()
{
    documentStore = new DocumentStore { Url = ConfigurationManager.ConnectionStrings["ravenDb"].ConnectionString };
    documentStore.Initialize();
}
public static IDocumentSession CurrentRavenSession
{
    get { return (IDocumentSession)HttpContext.Current.Items[RavenSessionKey]; }
}


Add call to InitializaeRavenDbStore() to the end of Application_Start method which should be already there. In this code we initialized DocumentStore class, provided infrastructure to store Raven Document Session and altered WebApiApplication constructor, attaching handlers to BeginRequest and EndRequest events to properly create and dispose the Session object for each request.

4. Next is repository class which will encapsulate all database interaction. Raven is natural with LINQ and generics, so repository can be created to handle specific type.

public class RavenRepository<T>
{
    protected IDocumentSession ravenSession;

    public RavenRepository(IDocumentSession session)
    {
        ravenSession = session;
    }
    public virtual T Find(string id)
    {
        if (string.IsNullOrEmpty(id)) return default(T);
        var item = ravenSession.Load<T>(id);
        return item;
    }
    public virtual IEnumerable<T> FindAll(Func<T, bool> predicate)
    {
        return predicate == null
                    ? ravenSession.Query<T>()
                    : ravenSession.Query<T>().Where(predicate);
    }
    public virtual List<T> InsertOrUpdate(List<T> list)
    {
        foreach (var entity in list)
        {
            ravenSession.Store(entity);
        }
        ravenSession.SaveChanges();
        return list;
    }
    public virtual void Delete(string id)
    {
        if (string.IsNullOrEmpty(id)) return;
        T entity = Find(id);
        ravenSession.Delete(entity);
        ravenSession.SaveChanges();
    }
}

The Raven Document Session object is being injected into the class for better testability. And we love testability.

5. And now the code which all above was preparing us for - the usage:

var repo = new RavenRepository<Person>(WebApiApplication.CurrentRavenSession, null);
var existing = repo.FindAll(p => p.Name == "Smith").FirstOrDefault();


Pretty simple construction with few small tricks - I hope it will save you some start time.

Thursday, April 04, 2013

The story of my life

Tuesday, March 26, 2013

New site address

New domain - www.laboremus.ca

Bookmark it - quite possible the blog can be moved from the Blogger platform.

Friday, March 15, 2013

Moving...

Considering the most recent Google developments I think it is for the best to move out of the Google-powered platform. It is truthfully disappointing to see the corporation with proclaimed motto "Do not be evil" turning more "Resistance is futile" side.
Weird it may sound but out of big three - Apple, Google and Microsoft, the latter seems to be most adequate in terms of user-respect conduct and a friendly way to do business (maybe had been beaten enough throughout all these years). It was a disappointment to encounter Google customer service (which is kind of half-expected) and even business account management (totally surprising). It fits perfectly the "screw-you-if-your-revenue-is-less-that-10-digits"-type of snooty service provider but not the "Don't be Evil" VP-of-Ethics-powered.
Concerning the quality of the products I have my own opinion, all the same - far not to the Google advantage...

Wednesday, March 13, 2013

Why I like being in this trade

It's worth it just for the joy of appreciating the humour and craft of the content of the following page (including the URL):

http://warmcrocconf.net/itsover/thankyou.aspx

NB: I just stumbled upon it - I have never heard about it before, I don't understand (yet) what is it about - but it made me very curious. Your experience may vary.

Monday, February 25, 2013

The best most awesome "Site Is Down" graphics

And the prize goes to the Capital One. The image draws a sympathy and instead of some other weirdness it says "We fought bravely and will get up before you count to ten".

Wednesday, January 30, 2013

5 Agile Project Management Techniques You Can Start Using Today


Awesome post from "Joel from Canada" (I did not know that Mark Twain is the grandfather of Agile)!

5 Agile Project Management Techniques You Can Start Using Today

And #1 is: "Don't call it Agile" - that's what she said :)

And yes, I know that I am slow to catch up.

Tuesday, January 29, 2013

A story of Google Nexus 4 adventures told in RIM stock prices



Chart may contain liberally interpreted data :)

Sunday, January 27, 2013

You have no time

I intended to write a post about an evolution of "cool kids" in IT industry. You know: how they used to be - you could only be observing them from afar because what they did required far more knowledge and training than you had (like being an Olympic champion, voodoo master or writing Assembler-360 voice-recognition systems). And how they are still so far away now, doing what you don't dare, because you are too busy earning money, building your resume or indulging some time-consuming habits like muscle-growing or soap opera watching. 
Inspirational people from Toronto Code Retreat can show you that the other word can exists and cool kids are just around the corner. I am procrastinator and can account for a dozen of "what if" moments every year of my life. And it is OK if you have plenty of time ahead of you. Like if you are 7 years old. Right after that you get too old for this shit, you have no time. We have no time. We should be out there starting and failing new enterprises, being laughed at or patronized at user groups and enjoying every moment working with great people who are capable of amusing us every day.
So get up and do fun stuff. I will follow, I am just a bit tied up at the moment earning money and worrying about my diet.

Friday, January 25, 2013

Building specification-compliant RESTful interface. Part I - WebAPI.

The best thing about the latest Microsoft trends starting with MVC1 is the turn back to the HTTP roots. I came to web development through ASP.NET 1.0 WebForms which successfully shielded me from all these response codes, charsets and headers. With MVC I had to understand how the HTTP actually works (RTFM finally!). WebForms mindset has pretty much locked me out from the cool "third-party" concepts. It is much easier to understand Ajax (not in the form of the UpdatePanel) or Node.js after been exposed to ASP.NET MVC.
But enough of that and let's get to our interface.
For implementation to be HTTP spec-compliant you should supply appropriate header values and status codes to the responses returned from you MVC actions or Node.js methods and throw nice HTTP-compliant exceptions if something went wrong.

Below is representation of API interface tied to HTTP method with a URL sample:

Create a new entity POST /myservice/locations
Retrieve entity (by Id) GET /myservice/locations/1500
Update an entity PUT /myservice/locations/1500
Delete an entity DELETE /myservice/locations/1500

The client-side code for both WebAPI and Node.js consumer is the same:
    function Add(json) { 
        $.ajax({ 
            url: API_URL, 
            data: json, 
            cache: false, 
            type: 'POST', 
            contentType: 'application/json; charset=utf-8', 
            statusCode: { 201: function (data) {  model.Sale().Id(data.Id);  }  } 
        }); 
    } 

    function Update(id, json) { 
        $.ajax({ 
            url: API_URL + id, 
            data: json, 
            cache: false, 
            type: 'PUT', 
            contentType: 'application/json; charset=utf-8', 
            success: function () { //success; } 
        }) 
         .fail(  function (xhr, textStatus, err) {  //failure; });       
    } 

    function Delete(id) { 
        $.ajax({ 
            url: API_URL + id, 
            cache: false, 
            type: 'DELETE', 
            contentType: 'application/json; charset=utf-8', 
            statusCode: { 204: function () { //success; }  } 
        }); 
    } 


  Server-side code in WebAPI implementation:

 private static readonly ISaleRepository repo=new SaleRepository(); 

        public IEnumerable<Sale> GetAllSales() { 
            return repo.GetAll(); 
        } 

        public Sale GetSale(int id)  { 
            Sale item = repo.Get(id); 
            if (item==null) { 
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)); 
            } 
            return item; 
        } 

        [HttpPost] 
        public HttpResponseMessage CreateSale(Sale item) { 
            item = repo.Add(item); 
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, item); 
            string uri = Url.Link("DefaultApi", new {id = item.Id}); 
            response.Headers.Location=new Uri(uri); 
            return response; 
        } 

        [HttpPut] 
        public void UpdateSale(int id, Sale item) { 
            item.Id = id; 
            if (!repo.Update(item)) { 
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)); 
            } 
        } 

        [HttpDelete] 
        public HttpResponseMessage DeleteSale(int id) { 
            repo.Remove(id); 
            return new HttpResponseMessage(HttpStatusCode.NoContent); 
        } 


Some additional considerations:
  • Note that there is no error-handling logic in the Controller class to make it more readable and reduce the cyclomatic complexity. All burden of the error-handling is offloaded to the Repository class.
  • By default the RC release assumes actions to accept GET or POST requests, so for our Update implementation it would throw the error "The requested resource does not support method PUT" unless the appropriate action is decorated with the good old [HttpPut] attribute (it worked differently in Beta version).
  • Bear in mind that Json.NET date converter can accept a wide range of date formats but can fail the default JavaScript one, created by new Date() statement - use overridden MediaTypeFormatter for tough cases.
  • Mike Stall's post is the best so far I found which in brief format describes WebAPI's intestines.

Next I will be looking into the Node.js implementation, which should be a bit more straightforward.

Wednesday, January 23, 2013

Expelled: No Intelligence Allowed (metaphorically speaking)

Have you ever seen companies which are in the growing mode and looking for a way to formalize their development process? Usually it is described as "bringing some structure in" - the management realizes that "cowboy coding" ("Agile" they called it) spontaneously adopted from the very beginning now limits their ability to expand.
Unfortunately Agile is often perceived as chaotic and uncontrolled alternative to more disciplined and planned (perceivable) approaches. It could be challenging to convince people that agile team has to adopt very strict rules and rigorously follow them on a daily basis. Enforcing the discipline is every member's duty, while in the more traditional process Project Manager is perceived as a keeper of justice.
With that demand comes another danger for the Agile adaptation: people start feeling threatened - their work (and slack) is exposed and scrutinized. One of XP Toronto presenters said that "if organization (reportedly) went through a change and didn't loose anybody in a process, then nothing has really changed". Sounds rough but seems reasonable. Most threatened are obviously those who hold formal positions of relative power closely working with developers. Take the architect for example. The appointed Architect is constantly challenged to prove his/her knowledge and abilities in order to keep the team's respect. More traditional approaches would allow Architects to barricade in ivory tower and reduce communication to directives. It is Evolution, folks, versus the Intelligent Creation as both theories understand it *.

* N.B. I am in no way taking sides in the actual "Expelled: No Intelligence Allowed" controversy. I have my own interpretation of both theories and keep it to myself.

Saturday, January 19, 2013

Coffee Script for the Microsoft Soul

So the CoffeeScript... It looks cool, it sounds cool, it kind of makes sense, it's everything but one - it is impossible to understand how to get started. It literally took me 6 hours before the world has heard my first "Hello". After perfectly designed, scrupulously executed and very visually appealing Knockout.JS tutorials (kudos! kudos!) it was the most bitter disappointment. All resources I went through jumped straight to the code of wicked cleverness and elegance but were missing one tiny small simple thing - to show how the damn CoffeeScript reference syntax should look like in the HTML page!...
I am not that Node.js-inclined yet and  and for long miserable hours I began regretting to belong to an inferior race of .NET developers. Unlikely light shed from IBM: the truly My First Cup of CoffeeScript. At least I've seen some code working.
Now about the tools. At the time I am stuck with Visual Studio 2010 on Windows XP (so no Visual Studio 2012 for me!). "Cool stuff can be done only with cool tools" says I and looks for non-Microsoft alternatives. Unfortunately WebStorm did not work well for me. The code got a proper syntax highlight but that's about it - I couldn't make it compile and community offered me to learn Node.js, command-line tools and Voodoo craft. Thankfully to an  excellent Mindscape plugin Visual Studio 2010 got coffinated without a hitch (did not get highlighting yet). At least now I am finally on the road.

Continuous deployment and stuff - pay attention!


Google's software and especially processes are not under that much scrutiny from the community and it obviously takes its tall. As soon as your code has stepped out of the cradle it is not about how cool and clever it is but rather reliability and what follows. In the long run the process is what counts, and there old dogs like Microsoft beat Google, even if the latter gets away easy where the former is been chewed.
Numerous successes of Google are widely publicized and known. But dude, open seven Chromes, close them all and take a look at your RAM. Or try to engage Google's Account Manager to buy (as in "pay money"!) one of their services. Or build a product which uses one of their Lab API's and then be informed they played with it enough, got tired and shut it down. And they killed Kenny!
Yet another Gmail glitch can speak to the lack of a proper processes in place. The problem is around for almost a week and it is either the product is not that ubiquitous or Google does simply has no capacity to turn around that fast. With the thousands of servers the glitch made its way with all cool tools of the day - Continuous Delivery, Continuous Integration and what-not - sloppy-executed, negligently-tested, poorly-managed.
Hordes of coolest kids can ride their colorful campus on Segways and it does not matter without a good old tiresome pernickety testers and malevolently censorious product managers.

Monday, January 14, 2013

So that's it for!

Twitter! The comprehension of this media of communication eluded me until now. But I finally got what people need it for - accidentally stumbling upon the @KileyCuoco's Twitter (let's say that I was in a process of researching The Big Bang Theory's continuation perspectives). I can see how it could create a feeling of complicity with somebody's life and being a part of some kind of inner

I better go and Tweet this.


Picture courtesy of sustainablejournalism.org


© 2008-2013 Michael Goldobin. All rights reserved