Monday, October 16, 2017

Async in C#

Tips

A thread is a relatively heavy weight structure. 1 thread takes 1M of Stack Space. A task is NOT a thread. You can have multiple tasks running on a single thread (such as UI thread).

Task.Delay() is like Thread.Sleep(), but it is a Task that won't complete for a specified amount of time.

The keyword async is not part of the method signature. For example, it doesn't show up in interfaces. It is convention to add Async to the end of a method name though. This tell the reader it is async.

Return Task, not void.

await

Frees thread to do other things such as update UI, etc. Before await is called the stack trace is in the method you called it from which makes sense. The potentially surprising thing is that the line after the await does NOT have the same stack trace. It is now in the same thread, but clearly not in the same calling method anymore. This is because the compiler creates a state machine when the code is complied. It's building what would have been done by hand before we had the keyword await in C#.
  • await frees a thread while we wait for an operation to complete. For example, handle another request in web scenario, update UI thread in desktop scenario. 
  • It does NOT block the thread, it actually frees the thread to do something else. 
  • The execution is stopped until the task is complete. 
  • When the task is complete the thread gets focus and execution continues. This is similar in concept to a callback after something is complete.

Exception Handling

If there is an exception in an async method it will be thrown and can be caught as if it was not an async method. For example, a simple try-catch.

Tuesday, October 10, 2017

Free resources for Parallel Programming

Below is a list of free resources for parallel programming with .NET.

Microsoft's main site for all things parallel

Parallel Programming in the .NET Framework


Parallel Programming with Microsoft .NET: Design Patterns for Decomposition and Coordination on Multicore Architectures.




Passing data to a Task using parameter to avoid race condition

Requirements

Consider the scenario where you want to pass the current value of i to a new task that gets created in a for loop. We want each task to have a unique value of i (0...9).

The wrong approach (closures)

In general, it is a bad idea do use closures to pass data to a task when the value will change before the task starts. Below is a classic race condition such that the value of i is not read until the task starts, but before most of the tasks start all the tasks have been created. This will result in gotParamNow being equal to 10 (or any value really, but not what we intended).

for (int i=0; i<10; i++)
{
Task.Factory.StartNew( () =>
{
int gotParamNow = i;
}
);
}

The right approach (parameter)


If you want to pass data when the Task is CREATED (not when started as it would do when using closures) then you can pass the data to the StartNew method as shown below.

for (int i=0; i<10; i++)
{
Task.Factory.StartNew( (arg) =>
{
int gotParamNow = (int)arg;
},
i
);
}

In the code above the value i changes over time, so we want to pass it to the StartNew method so that when the task starts the data has the value that was passed to it and will result in each task having a unique value of i passed to it and thus gotParamNow will be unique as well.

Task Cancellation

Intro

When doing speculative work (starting multiple thread and only caring about the first result that comes back) these thread can take up valuable resources such as cpu or are long running, etc. We can just let these threads run to completion, but that won't free up the resources until they are done. Ideally once we have the result we want to cancel the threads once we don't need them to run anymore.

Cooperative Model

Creator passes a cancellation token, starts the task, later signals cancel, etc
Task monitors the token, if it is cancelled then it performs the cleanup and throws an exception.

Status on Task is set to "Canceled"


var cts = new CancellationTokenSource();
var token = ctx.Token;

Task t = Task.Factory.StartNew( () =>
{
try{
while (...)
{
// check for cancellation at start of each iteration
if (token.IsCancellationRequested)
{
// clean up
// NB: Make sure this exception bubbles up (as shown here) to the caller.
token.ThrowIfCancellationRequested();
}

// do the stuff would normally do here
...
}
}
catch (OperationCancelledException)
{
throw;
}
catch (Exception ex)
{
// handle exception
}
}, 
token // allows .NET to set status appropriately
);

// this may be invoked by a menu, keystroke, or other reason.
// This will trigger the canelling of the task.
// This would typically not be in the same location as the rest of the code here.
if (some condition occurs) {
cts.Cancel();
cts = new CancellationTokenSource(); // If need to re-run
}

try 

t.Wait(); // throws exception if cancelled
}
catch (AggregateException ae) {
ae = ae.Flatten();
foreach(var ex in ae.InnerExceptions)
{
if (ex is OperationCancelledException)
// do something (ignoring it now)
else
// handle exception (ex.Message will get error message)
}

}

Note: By passing the same token to several tasks will cause all the tasks to be cancelled when cts.Cancel() is called.

Caveat: Once Cancel() has been called on a task, the token passed to the Task cannot be used again once its status has been changed to Canceled. If you re-run the task you will need to create a new token as shown above. A good place is right after Cancel() is called.

Alternative approach

Use a global variable and check it to see if the task has been canceled. The trick in either implementation is to get the right level of polling. Too often will have performance implications and too little and cancelling won't be quick enough and waste resources.

Reference

Content is based on Pluralsight video called Introduction to Async and Parallel Programming in .NET 4 by Dr. Joe Hummel. 

Monday, October 9, 2017

Writing Better User Stories - Part 3 (The right amount of detail)

Ideally a user story should be more than a quarter of a sprints velocity. If this is the case then user stories should be able to be finished during a sprint in most cases. If the team is having trouble completing user stories it may be that they have too much or too little detail. Below are some techniques for determining what the right level of detail is for a story.

Too Little Detail

If a story does not have enough detail you may find that there are too many unknowns and result in there being a lot of questions to product owner during the sprint. The delay here is during the sprint and development and is very visible. The answers can delay the development or increase the complexity of the story as well.

Too Much Detail

If a story has too much detail you may find that the team has tried to remove all uncertainty from the user story and that new functionality is taking longer to deliver from the point the request for new functionality was made. The delay in deliver here is hidden by spending lots of time refining the story BEFORE it is brought into the sprint. This shows in areas like acceptance criteria with too much detail, or all screen designed completed, or not allowing a story into a sprint if it has an uncertainty. If all creativity has been removed from the developer there is probably too much detail.

The Sweet Spot

Ask the team "Did you get just enough detail to complete this iteration's user stories and was that information provided just in time?" in the retrospective. This will help in future stories. Strive to get the right level of detail "on average", not every story.

Detail should be provided "Just enough and Just in time" because too early and the information will be out of date by the time the team works on the user story. The will likely cause delays in the sprint or waste time reworking a story.

Analysts job with Agile is to provide the information Just in Time since there is not large chunk of analysis done at the start of the project. This is in contrast to traditional waterfall methods where there is an initial stage where the analyst figures out all the details upfront. This means that the chances that the analyst will get the level of details or get something wrong increases. This means some (a small number) stories will be affected, but not likely all of them. However, this is better than building in delays, padding, etc into every story.

The idea is striving for perfection when moving this fast will not be effective. Consider something like Fedex that has 2 day delivery. They expect that a low percentage of packages will not be delivered as expected. The alternative is to not have 2 day delivery and guarantee 5 day delivery instead, or increase the number of staff, planes, vehicles, etc. These would affect the price of the product as well as reduce the overall benefit that most people experience just so we get 100%. The same can be said for Agile projects.






Friday, October 6, 2017

Writing Better User Stories - Part 2 (Splitting Stories using SPIDR)

Benefits of taking time to split stories


  • Deeper understanding of the feature
  • Can be delivered in a sprint which keeps velocity more consistent which makes it easier to pull in the right amount of work into a sprint
  • Shows progress
  • Smaller chunks are easier to understand
  • teams are motivated to finish a small story and feel a sense of accomplishment when they do.

Bad Ideas


  • Doing development in one sprint and testing in another sprint.
  • Having the entire team present when splitting every story.

Using SPIDR to Split Any Story (5 ways)

The goal is not to split stories into the smallest story possible and produce lots of small stories. Instead the goal is to split the story as few times as possible such that it can comfortably be completed in a sprint.

Spike (S) 

a research activity intended to build knowledge (not deliver functionality). Use cases are times when a team cannot decide between different ways of implementing something, or a new technology is being used. Use it only as a last resort (after the other 4 approaches have been tried).

Paths (P)

A path becomes a story
Consider the paths through a story and split each path into its own story. Draw a simple flow chart and look for the conditional or places user has to decide a path to go down (Credit Card or paypal for example). Looking for the word OR may also aid in identifying different paths. Look for paths that will deliver value for the users.

A complex step becomes a story
Sometimes the complexity is not in the different paths, it is actually in just one step in the feature. In this case it may make sense to combine several paths into one path if such that they comfortably fit into a sprint. Then take the one step that is complex make it a separate story. For example, maybe the step that is complex in a shopping cart checkout is Confirming the order in which this case maybe a story for just confirming the order makes sense or even may need to be broken down into multiple stories if it doesn't fit into a sprint.

Interfaces

Split a story across multiple user interfaces (mobile OS, browser) or data interfaces. The could mean separate stories to support iOS, Android, Windows phone, etc. Or it could mean separate stories for each type of browser such as a story for Edge, another for Chrome, and another for Firefox, etc. The reality of browser differences is that usually one browser will have an issue. So, the user stories can be split into Troublesome browser and non-troublesome browser stories.

Complex User Interface
If the user interface is complex is complex it can be broken down into two stories. In the first story the goal would be to just get the data on the screen and not worry about design. The focus is to make sure it is wired up to the backend. The second story would be going back and refining the user interface to be fancy and work in a certain way.

File Formats
If you have a service that needs to import data in XML, JSON, and CSV then you can break out each format into a story. The first one would have the largest estimate because the extra work needs to be done for the importing, while the other stories would just really be about parsing different formats.

Data (D)

Develop an initial story that supports only a subset of the data. Consider how different aspects of data can be used for a particular story. Think of this is how to make AI smarter by adding in more scenarios or data sources. If making recommendations, one user story could be I want the feature to make recommendations that consider x. Another story could be I want the feature to make  recommendations that consider y. Each user story may not be enough to release or be really useful to user, but it is a step towards the releasable product that has lots of value.

Rules (R)

Relax business rules or technology standards or industry standards in an initial user story. Subsequent stories can tight up the rules.Other functional stories can be added and completed before the rules are tightened to allow more feedback on the larger solution. Sometimes rules show up as non-functional requirements such as performance.

Context

You don't need to try all 5 ways to split stories. Just start with the way that you think will likely work and if that works then you are done. If it doesn't then try another way and if that works then you are done. Continue until you have successfully split a story into smaller stories that fit comfortably in a sprint.

Caveat

Some stories cannot be split, but they are fundamentally large and rare. Using SPIDR will make it possible to split nearly all stories

Monday, October 2, 2017

Writing Better User Stories - Part 1 (Using Story Mapping)


Stories are not simply a replacement for a requirements specification. It is meant to be an interactive, regular, shorter process.

Focus on One significant thing


Focus the meeting on a single significant objective (that will take a few months to do). This allows us to plan at a quarterly focus which also typically works well for management.

Don't do story writing workshop every sprint. It is a bad idea to do so.

Minimum Viable Product (MVP) is a good thing to focus on because it promotes feedback early.

Minimum Marketable Feature (MMF) is a subset of functionality that users need, but it is enough to be valuable to users when released.

Who should be in story writing workshops

Product Owner presents the significant objective
Scrum Master or Coach to facilitate the meeting and keep it run smoothly and effectively
Any other person that will be involved in the development such as Developers, Tests, Technical Writers, DBAs, Designer, Architects. Don't leave people out this is the time where everyone learns about the story. This will allow questions to be answered, new perspective brought in, and more new and innovative solutions will likely be produced.

An exception to this is when multiple teams are involved. In this case a subset of each team may be useful to keep the size of the meeting smaller and more manageable. An alternative would be to break the story down further so that each team can have their own sub-objective and meeting and the full team would be included in these smaller story writing workshops.

Users and Stakeholders can be invited and probably should be. However if it becomes too distracting or side-tracks the workshop because they are arguing over priority of stories then it may be better to leave them out. Alternatively, reassure them that the workshop is about understanding the user story workshop, and discussing it does not prioritize it over another story.

Visualize relationship between stories

A story map is quite useful for visualizing how stories relate. This is typically describing a sequence of stories connected with THEN.

For example:



Then add Alternatives below sequence at the position where it is in the sequence. Or keyword is used to connect it in the sequence. The higher priority items should be at the top, and low at the bottom.



This is helpful for identifying missing stories. To do so, ask the following questions while reviewing the story map. Ask these questions for each type of user in the user story.

  1. What will a user most likely want to do next?
  2. What mistakes could a user make here?
  3. What could confuse a user at this point?
  4. What additional information could a user need.
Subsequently you can then break story map into releases such that each horizontal line is a new version. It can be useful to label each version as well.


Reference:

Better User Stories - an excellent series on writing better user stories.