Apr 30, 2015

Impossible User Flows, Patterns and Code

Product Development Iteration
After an initial spurt of development and v1 of a product, software engineering processes and product life cycles kick in. We move into an iteration phase where a product undergoes continuos improvements and changes to serve its customers and their changing needs. Processes of scrum and agile steadily fit the product to its current and future customer needs. A product at that point has matured so to say even though it might still be in its infancy with regards to business goals.

Business logic and technical debt
Such a mature product needs processes for development. They have complex business logic and every line of code that is changed is tied to some business purpose. Little things start taking a long time to implement and technical debt takes the blame. Many time the product development slows down to a point where a major refactor or rewrite becomes inevitable. Companies solve this problem by adding more developers and building stronger QA teams. Most such companies that survive are making enough revenue to be able to support this growth. They become a big company so to say at that point.

There are no edge cases in code
Having seen pretty simple products reach this kind of complexity and slow down, I believe the iterations break the patterns with which the v1 was developed. Iterations happen in the form of supporting one edge case over other and because of time constraints many of those result in hacks in code that harden the product. In code there are no edge cases. The code might execute as many times for the edge case as for a happy scenario and nothing changes for it. On the other hand, edge cases are not that important hence don't justify the time they require to fix the pattern.

Patterns of the product
Product flows do have patterns. It is very difficult to see those because we see the needs coming one part at a time. Also, there are lot of missing links, things the user can never do that we never see hence never code for. We could place use case feasibility  vs Product into a 2 x 2 as follows:

1. Feasible use cases + Product supports
2. Feasible use cases + Product does not support
3. Infeasible use cases + Product supports
4. Infeasible use cases + Product does not support

The iterations of product generally revolve around #2 above. But when we try to build a pattern for our use cases lot of #4 also falls within that premise. There is also the part of #2 that is way down in priority.

Such scenarios are often seen in onboarding flows. The reason is that registration and login is such a simple process that v1 is put in place fairly quickly without thinking much about future scenarios. Most of the time using some external libraries or gems. Thereafter in every iteration, the new needs are implemented. Here are some of the scenarios that creep into onboarding flows -
  • Forgot password
  • Forgot user name
  • User name validation
  • Access codes
  • 3rd party authentication
  • User type customizations
  • Partner customization
  • Marketing campaign tracking
  • Campaign specials
  • Special URLs
  • Authentication via passcodes
  • Mobile app notifications
  • Web to mobile app flows
The business logic around these can be tremendously complex although the basic use case remain simple. Let us think of some of the use cases which are infeasible in onboarding -
  • Using access code as password
  • 3rd party authentication using local authentication
  • Tracking partner campaigns
  • Authentication via user name and password in URLs
  • Customization for base product
  • Web to mobile app flow on desktop
  • ...you get the point!
Advantages of supporting impossible flows
When we combine the feasible and the infeasible flows including the flows that are way down in priority, we start seeing the pattern of the product. When we see that, we can break things down into functions and components and their responsibility. We can make a list of factors that affect their behaviors. The thought process of looking at the iterations of the product changes. We start prioritizing changes in the product patterns instead of user needs and edge cases.

Product pattern design
In conclusion, failing to maintain the product pattern design will lead to increased technical debt and slow down. On the other hand over focus on product patterns and technical debt will also lead to slow down. Product design should consider patterns an integral part of it. Priorities should be based not only on business needs but should consider product patterns. Some slow down that can improve the pattern will result in much faster iterations in the long run. Think improving a screen vs improving a UI component. One affects a much needed business change, the other improves the overall product. Similarly thinking of functions, components and external factors will simplify flows greatly. Implementing all those additional use cases that no one asked for and that no one will ever use, will actually improve iteration speed and make the products simpler.

Jan 30, 2015

Suggesting a new story type: "Irritant"

In the scrum world, we typically divide our stories in to bugs, features and chores. I find this classification limiting and that it does not address all the work that should be implemented to deliver an awesome product.

The problem here is not that any task cannot be classified into one of these categories. The problem is that these categories are typically owned by different people. The product mainly focus on features, QA focus on bugs and chores is a catch all, generally used to plan refactoring like tasks.

There is one group of people who have no place in these categories and they are the product end users. These are the little, little things through out the application which are neither features, nor bugs, nor chores but make a big impact on how the users perceive your product. I am calling these as 'Irritants'.

Irritants are those confusing messages, the non highlighted action button, the convoluted menu structure, the UI redundancy or lack of it and all those little things which make using the product that much more painful.

I find products filled with irritants all along everyday. Some of our most popular products today will disappear in the months and years to come mainly because of their failure to address this key story type. We focus on pixel perfect designs, micro second load times and debate on using Java vs PHP, but what really will delight our users I believe is removing these 'Irritants'.

Jul 26, 2014

Thought exercise: Artificial Intelligence

The only part that I understand about Artificial Intelligence is an attempt to create computers that can think and learn like humans or animals. AI has been in talks for many decades now and sci-fi movies stretch our imagination with the possibilities of AI. 

Being a programmer for over a decade now, I realize computers are pretty dumb and they need to be fed with every bit of work that they do. The permutations and combinations they can thus handle are for all practical purposes almost always very limited.

When I think of how our brain thinks, recollects, remembers and analyzes, I feel our microprocessor is fundamentally different than that of a computer. Things which are really simple for computers, like math, is quite complicated for humans. And things such as image processing which is quite simple for humans, is much difficult for computers.

Which leads me to thinking that may be AI might require a completely different kind of microprocessor. The assembly level instructions for an AI processor would need to be fundamentally different than what it currently is. 

We think everything in terms of images or flashes. An image big or small is the same thing for our mind. We can instantly associate one with the other. An image could be made up of thousand other images and we can instantly separate out and connect those with all the other images we have. We don't learn numbers and alphabets as ascii codes but as images and their variations.

The processor than which would create AI would need to have its basic instructions in the same paradigm. A bit in todays microprocessor would be equivalent to an image in an AI processor. There is no concept of bitmaps in an AI processors. All images then are fundamentally vector images or an image bit.

The second fundamental element we would need in this AI processor is the ability to infinitely link images to other images and parts thereof. Hence when we search for something, we don't do a linear search but a multi dimensional search which goes deep into this network of interconnected images.

Moreover vision is just one of the many senses that we think with. The AI processor in a similar manner would need to process sound, taste, smell and touch, each as fundamentals bits of our AI microprocessor. With these low level AI instruction sets available to us, programming an intelligent being would thus become increasingly fathomable.

Silicon brought a breakthrough in binary computing. Probably we need to look at some other source to bring this breakthough in AI computing. If the computing power keeps increasing at its current rate, we should be able to reach that tipping point pretty soon when we are able to construct the babbage engine of AI. I believe that should open an entirely new horizon in computing era, a step into true artificial intelligence.