Friday, 26 June 2020

Guflow added support for timeout in signal APIs

Just released version - 2.0.5 of Guflow has added the support for timeout in signal APIs. Now with minimum efforts you can support the human interactions in your workflows. Following example uses timeout API to ensure that user should confirm her email address within 12 hours to activate the account:

public class UserActivateWorkflow : Workflow{
  public UserActivateWorkflow(){
     ScheduleLambda("SendLinkInEmail").WithInput(_=>{Id=Id})
      .OnCompletion(e=>e.WaitForSignal("EmailConfirmed").For(Timespan.FromHours(12)));
     
     ScheduleLambda("ActivateAccount").AfterLambda("SendLinkInEmail")
      .When(_=>Signal("EmailConfirmed").IsTriggered());
     
     ScheduleLambda("ActivationFailed").WithInput(_=>{ Reason="Link timedout"})
      .AfterLambda("SendLinkInEmail")
      .When(_=>Signal("EmailConfirmed").IsTimedout())
  }
}

Timeout is supported for all the wait for signal APIs: WaitForSignal, WaitForAnySignal and WaitForAllSignals. You can read more about them here.

Feature highlights:

1. Though default implementation of "wait for signal" APIs should be sufficient for real world scenarios but Guflow also support customization.

2. Signal APIs automatically adjust the wait time to cater for the downtime of the workflow host. e.g. in above example wait APIs will adjust the wait time to 11 hours if workflow host was down for 1 hour just after executing the Lambda function "SendLinkInEmail". It means user will really have 12 hours to confirm email and timeout will not be automatically inflated because your workflow host was down.

3. Like rest of of APIs, signal APIs too store their state in Amazon SWF which means your workflow host is stateless and you have the flexibility to upsize/downsize/upgrade in production.

4. You can also use alternative style to detect trigger and timeout for the signals as shown in the following example:

public class UserActivateWorkflow : Workflow{
  public UserActivateWorkflow(){
     ScheduleLambda("SendLinkInEmail").WithInput(_=>{Id=Id})
        .OnCompletion(e=>e.WaitForSignal("EmailConfirmed").For(Timespan.FromHours(12)));
   
     ScheduleLambda("ActivateAccount").AfterLambda("SendLinkInEmail")
        .When(_=>Lambda("SendLinkInEmail").IsSignalled("EmailConfirmed"));
     ScheduleLambda("ActivationFailed").WithInput(_=>{ Reason="Link timedout"})
      .AfterLambda("SendLinkInEmail")
      .When(_=>Lambda("SendLinkInEmail").IsSignalTimedout("EmailConfirmed"))
  }
}

Last few releases of Guflow were targeted to enhance signal handling capability. You can use signals for the following three purposes:

Hope you'll like the new feature.

Monday, 4 February 2019

Manual approvals with serverless lambda functions are simple with Guflow

Latest release of Guflow will now let you easily implement support for manual approvals using serverless lambda functions. Here is a very simple example showing "WaitForAnySignal" API:

Other APIs that you can use for waiting for signals are: WaitForAllSignals and WaitForSignal. These APIs will help you to move your workers from activities to serverless lambda functions.

You can call these APIs anywhere in workflow branch e.g. in the following example "ApproveExpense" is a child workflow:

As explained here not only can you customise the signal handling, but you can also use signals for different purposes.

Other interesting examples of manual approvals using lambda functions can be found here

Tuesday, 7 August 2018

Guflow now fully supports scheduling of AWS Lambda functions

I have released the next version of Guflow, an open source C#.NET library built on Amazon SWF, and it now supports the scheduling of AWS lambda functions. You will find Guflow, built up on Amazon SWF, to be an alternative to Amazon Step Functions and the FlowFramework. It is hosted on github.

Here is a simple Iterator example to compare:
  1. Amazon Step Functions took approax 41 lines to implement.
  2. Guflow took 5 lines to implement.

I'm looking forward to adding more real life examples. Please feel free to provide links to any real life examples you would like to see implemented.
Guflow brings both simplicity and flexibility in one place. Some of the highlights are:
  • Guflow lets you make use of all the Amazon SWF features*.
  • Guflow lets you seamlessly schedule Lambda functions, Activities and Timers.
  • Supports parallel branches in the workflow.

*Support for child workflows coming next.

Guflow is supported by documentation, tutorials and examples. Any feedback from the community will help greatly in improving this library.

Friday, 23 March 2018

My common mistakes with TDD

In this post I will try to list some of the mistakes I made while practising Test Driven Development(TDD). I will partly blame my mistakes on how the information about TDD was disseminated and how I (mis)understood it. I started to follow some of the TDD principles back in 2009 and one of the point I strongly agreed to was the need of writing automated unit tests. After reading through tons of articles and mixing my intuition with this newly gained knowledge I started to write code which I believed was a TDD style but in reality it was not. I ended up writing the code which was not following any of good object oriented programming practices.

So here goes my list of mistakes I made while boarding TDD train:
  1. Writing tests after code:   This is the the very first mistake I made and I have seen many people making this mistake and believing they are following TDD. It was difficult for me to think of test beforehand and write the code later and I reverted back to writing code first. Majority of time, writing tests later
    • Makes them complicated and difficult to read
    • Makes them brittle and encourage you break encapsulation or other OOPs principle to increase test coverage
    • Encourage you to count the asserts
    • Tends to increase the size of setup

  2. Abusing the power of interfaces and DI to facilitate unit test:   This one is very interesting. I got the impression that with the power of interface and dependency injection I can unit (class) test any code at any time then why bother writing test before code. It is precisely because of this misunderstanding I ended up writing code first. While following this approach vigorously I ended up creating interface with just on method. This approach is no way near the good OOPs let alone the TDD. I have blogged about it in details here.

  3. Assuming a unit test is always equal to class test in every situation:   This is another wrong impression I got while introducing myself to TDD. Many of the online articles were explaining unit testing using an OO language like C# or Java and almost all of them used to emphasise that -
    • Unit test for a class should focus only testing of behaviour of one class
    • As soon as class under test interacts with other class, use mock and stub
    First suggestion is very good and it should be observed while writing unit tests. However the second suggestion is what created problem for me. I'm not saying it is bad suggestion for all situations but it should not be followed in every situation instead golden rule of computer science- 'It Depends'. If you start strictly following second suggestion then your target classes becomes like sliced bread, which are not designed to cooperate with each other and you create your own mesh of communication for these classes to interact. But in reality objects tends to collaborate and you should let them collaborate but under the constraints.

  4. Too much mocking:  I completely submitted to the idea that unit test should focus only on one class and the moment it start using collaborating with other objects I should use stub and mock straightway. As a result I was writing the test where a mock was returning another mock. My unit tests were brittle and were breaking on slight refactoring. I can write a separate post on perils of too much mocking. These days I'm using stub and relying on object state and identity/equality for state verification and occasionally using mock when my system is trying to communicate with other system and I am quite happy with readability and reliability of unit test cases.

  5. Blanket ban on usage of static methods/properties:  To promote unit testing, programming to interface and dependency injection some posts has almost advise not to use static method/properties. On of the primary reason for not using static method/properties is that they are not good at being stubbed or mocked. But it depends on what kind of code you're writing in static method/properties. If you're writing behavioural unit test and your target code is using accessing static method/property then it will tested along with it.

  6. Counting the number of assertions in test:  If you're counting the assert than probably you're writing code first. Because if you are writing a behavioural unit test before the code than you tends to write all the necessary asserts to validate the behaviour and generally do not count them.

  7. Try to get 100% unit test coverage: I had given too much importance to code coverage and tried all the tricks to increase it. But in reality coverage does not tell you anything about the quality of unit tests or code itself. I have seen that people even break encapsulation to increase test coverage.

  8. Open up internals of target code to ease unit testing:  Encapsulation is the holy grail of OOP and needless to say that code becomes unmaintainable if it is broken.

  9. TDD is the only way to write quality code:  In think that is where TDD was oversold (mis-communicated/misunderstood). Alone writing of test first does not guarantee the quality of code, you need good knowledge of OOPs (if you're programming in object oriented language), design patterns, SOLID principles and willingness to represent domain language in code. Even if you're writing the test first but does not have good understanding of good programming practices then quality of your tests and code are going be very poor. I have written a blog post to highlight this issue further. In this post I have tried to show that even though you are writing test first and programming to interfaces and using dependency injection all over the places but the quality of your code and unit test is still very poor. Real problem is here not TDD but how the programmers have (mis)understood it.

  10. No upfront design:  When someone mentioned that programmers should not waste too much time on upfront design and let your tests discover the it, I (mis)understood as- I should not spend any time of design instead should straight go to writing the tests and let my tests discover it. But in reality you need some design (not the design of whole system) then only you can write the unit test to validate/refactor it. By design I mean you need think of a class and what it represent in your system and what should be its role and responsibilities. You need to think about its behaviour then you will write the test first to validate your design and understanding about this class.
This post will be incomplete if I do not mention how I learned about these mistakes:
  1. Inhouse training in OOPs by Fred George at Cloudhouse.
  2. Feedback and criticism from my colleague at Cloudhouse
  3. Practice, practice, practice.. apart from try out the ideas on company projects I worked on my personal open source project at my own pace.
TDD is not about throwing away the OOP techniques or good practices that you have learned over the years, instead it is another skill/tool which you should learn along with recommended practices, patterns and principles. TDD brings immense benefits to your project but you need to do it right otherwise you might be doing Test Driven Damage (TDD) and I'm just another person to realise this truth.

Sunday, 27 November 2016

What is your programming style - Procedural OOP or just OOP?

In this post I'm going to share two programming styles - one I switched to when I boarded the TDD train and the other one is I'm following currently.
I will write a small application using both styles. The job of this sample application is to parse the meetings from CSV format file and schedule them in a calendar.

Monday, 3 August 2015

Service locator is (not) an anti-pattern

I have used service locator pattern in my projects without any problems and I was quite happy with it until someone told me that is an anti-pattern. I was bit surprised and did some search on google and found many articles suggesting that it is an anti-pattern. After going through them I concluded -"that is not how I have used it".

Friday, 24 July 2015

Entities to database mapping in EntityFramework

In this post I'm going to share different ideas to map domain entities to database schema in Code First development. In all of the approaches, I'm going to derive from DbContext class and overrides its OnModelCreating method. You can still use the ideas from this post even if you're directly using DbModelBuilder to create DbContext. For the purpose of this post I'm using two classes- Product and Brand; you can find them here.

Guflow added support for timeout in signal APIs

Just released version - 2.0.5 of Guflow has added the support for timeout in signal APIs. Now with minimum efforts you can support the human...