Tuesday, August 26, 2014

Solomon, the architect

Two junior developers who started working for the company at the same time, had been quite competitive with each other from the get-go. They had once been assigned to the same team, but because of the constant bickering, which had put a serious amount of stress on the team, one of them was pulled off the project and reassigned.

A good year later, just the two of them were assigned to a new smallish, but interesting in-house project. When management assigned them to the same project again, they had just been shuffling resources around, and had no idea of the history these two had. An architect was also assigned to the project, but this was not more than a formality. As soon as the enterprise architecture diagram was updated and the paper work was out of the way, he would do an official hand over, but he would only occasionally check in on the project from then on.

The Friday morning after the hand over, the architect was making small talk with one of the project managers in the coffee corner. His agenda for the day was almost empty - exactly how he liked it on Fridays. He planned on making the rounds this morning to check in on projects he was involved with, to attend a meeting at noon, and to spend the afternoon reading up on micro services, for then to go home early. While he charged the coffee machine with another coffee pod, he heard an uproar that had to be coming from the other side of the floor. He couldn't quite make out what it was about, but he recognized the voices immediately: the two juniors.

He hurried over to the source of the noise. Prying eyes looked curiously over their monitors, ignoring the architect as he passed by. He found the two juniors standing next to the white board, yelling at each other, gesturing vigorously, crossing out parts of the drawings. The architect broke up the fight, and commanded them to get in the meeting room right away. Startled at first, but red-faced just a few seconds later, they shuffled towards the meeting room, not saying one more word, staring at their shoes.

The architect closed the door behind him, and started questioning them. What was this all about? He learned they had a big disagreement on how they should design a part of the new system. The architect, after hearing them out, thought he understood both their solutions. Given the information he had at that time, he thought both solutions were good enough for now - each made trade-offs, and only time would tell them more.
"There are still dozens of possible alternatives out there. I should try to show them how to come to a consensus together," he thought. "Before I do that, I'm curious to discover their incentives though, so let me try something here."

He told them that he liked both of their solutions, but that he couldn't decide  which was the better one. Instead, he would take random parts of each solution and throw them together, to come up with a hybrid solution. This way, nobody loses.

Junior number one seemed relieved. He nodded and glanced at his partner. To his surprise, his partner didn't look very happy. Junior number two blurted out that he'd rather see his own solution in the bin, than to give up conceptual integrity, just because two people can't agree.

With that, the architect learned that junior number one had fallen into the trap of making it personal, and was trying to save face. Number two however, was wise enough to favor conceptual integrity over getting his way. The architect complimented the kid, and acknowledged that sometimes giving in might be the wise thing to do - not always, you have to pick your battles. Then he rolled up his sleeves, picked up a bunch of post-its and a pen for both of them and said that it was time for them to "fight the problem together instead of fighting each other". But not before he made another coffee.

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.

Source