Tuesday, August 19, 2014

Thinking No Computers

The other day I happened to see a curious exchange in one of our businesses. The cashier swapped a torn, but carefully restored by taping it together again, Euro bill for a new one with the manager. Inquisitive, I asked the manager what he was planning to do with that Euro bill. "Once a month, I take all those ripped up or badly worn bills to the National Bank, and trade them for new ones. All you need is one piece of the bank note for them to give you a newly printed one."

While he started taking care of some other paper work, my mind started racing towards how the National Bank made this system work. I had noticed before that bank notes have an identifier on each side. I figured the National Bank probably stores the identifier of each note they trade, so people don't go ripping up bank notes with the intent of trading them twice. That seems easy enough, no?

Once the manager finished up his paperwork, I wanted to confirm my idea and asked if he knew how that system worked. How do they avoid people cheating? "It's really simple actually, you need to own more than 50% of a bill for it to be tradable."

Well... that's a much simpler solution. No need to store all the traded notes somewhere, you probably don't even need a computer at all.

I catch myself regularly defaulting to wanting to solve problems using computers. While taking a step back and thinking of how it would be done without, often exposes a simpler model. Sometimes you will realize that you don't need a computer at all. If not that, you get to steal from models that have been molded and battle tested for years.

Look at existing organizational structures and search for boundaries. You might find that aligning your software with existing boundaries makes the pieces of the puzzle fit. Learn how departments communicate; passing forms, by phone or by email. Maybe it shows that you need synchronous communication with strong consistency based on a formal protocol or that you might just get away with asynchronous communication with a less strong schema. Go through paper work, formulas, legislation, research papers, books and what not, and that hard to crack nut might become a bit softer. Look at where people are making decisions and how they are deciding on them, do you spot the patterns?

People have been solving problems for hundreds of years, tinkering with and perfecting models, way before computers were a commodity. Natural selection made sure only the strongest made it this far. Those solutions didn't stop working all of a sudden, nor should they be discarded as a whole. A great deal of them will likely survive another few hundred years, in one form or the other. 

Sunday, June 8, 2014

Paper notes: A Study and Toolkit for Asynchronous Programming in C#

The .NET framework mainly provides two models for asynchronous programming: (1) the Asynchronous Programming Model (APM), that uses callbacks, and (2) the Task Asynchronous Pattern (TAP), that uses Tasks, which are similar to the concept of futures.

The Task represents the operation in progress, and its future result. The Task can be (1) queried for the status of the operation, (2) synchronized upon to wait for the result of the operation, or (3) set up with a continuation that resumes in the background when the task completes.

When a method has the async keyword modifier in its signature, the await keyword can be used to define pausing points. The code following the await expression can be considered a continuation of the method, exactly like the callback that needs to be supplied explicitly when using APM or plain TAP.

Do Developers Misuse async/await?
  1. One in five async methods violate the principle that an async method should be awaitable unless it is the top level event handler.
  2. Adding the async modifier comes at a price: the compiler generates some code in every async method and generated code complicates the control flow which results in decreased performance. There is no need to use async/await in 14% of async methods.
  3. 1 out of 5 apps miss opportunities in at least one async method to increase asynchronicity.
  4. 99% of the time, developers did not use ConfigureAwait(false) where this was needed.
The async/await feature is a powerful abstraction. asynchronous methods are more complicated than regular methods in three ways. (1) Control flow of asynchronous methods. Control is returned to the caller when awaiting, and the continuation is resumed later on. (2) Exception handling. Exceptions thrown in asynchronous methods are automatically captured and returned through the Task. The exception is then re-thrown when the Task is awaited. (3) Non-trivial concurrent behavior.

Each of these is a leak in the abstraction, which requires an understanding of the underlying technology - which developers do not yet seem to grasp.

Another problem might simply be the naming of the feature: asynchronous methods. However, the first part of the method executes synchronously, and possible the continuations do as well. Therefore, the name asynchronous method might be misleading: the term pauseable could be more appropriate.


Sunday, June 1, 2014

Not about the UI and the database

When you ask an outsider which components an average application consists of, he will most likely be able to identify the user interface and the database. He will also recognize that there is something in between that takes the input from the user interface, applies some logic and persists the result in the database.

In the past, trying to make sense of what goes on the middle, we started - with the best intentions - layering things. Each layer had its own responsibility and would build upon previous layers. Although there was a layer for business logic, we never really succeeded in capturing the essence. In the end we would still be orchestrating database calls, but now we would be forced to go through a bunch of indirections in the form of anemic layers and objects.

Some people saw these designs for what they were, broke free and started optimizing for the shortest path - from user interface to database with the least amount of effort. By aiming to serve the common denominator and by putting their trust in dark magic, frameworks popped up that would allow you to slap together an application in a matter of hours.

The problem with these frameworks is that they leave you with very little room for your own, and you often end up jumping through hoops when you need to deviate from the path carved out for you.

That's not the only problem though - applications are a lot more than a user interface and a database. What lives between those two is more than a technical necessity - it's a place where you get to build a model of the problem you are solving. The model gives you an opportunity to learn from and to communicate with domain experts, peers and users. And that's exactly where most businesses make the difference, not by having a fancy user interface or a carefully designed database schema, but by really understanding and by being absorbed by the problem they are solving. It's the user interface and the database that are the necessary evil we bring upon ourselves by solving problems using computers.

The state that lives in your database is a side effect - the result of the model's behavior. The user interface tries to make it as easy as possible for users to drive and use the model.

Although the user interface and the database are important, it's the model that is the heart and soul of your application.

(*) Disclaimer: all these drawings are simplistic by design.