Vergosity Business Actions

What are business actions? They are simple units of business logic implemented using the Action base class from the Vergosity Framework. They are just simple classes that follow a specific pattern. All of the business logic is performed in the PerformAction() method. Notice that the constructor takes in the target entity CodeSample. The entity value is contained in a field called _codeSample – which is decorated with a rule attribute EntityIsValid. This rule is evaluated when the action is executed. If any of the business rules and data validation rules fail, the PerformAction() method is not called or processed. You can supply the action with as many input items as you wish. This action takes the input parameters in the constructor – however, there isn’t anything preventing you from adding public properties to do the same.

This action has an output object, the IsUpdated boolean property. Since we are using classes for the business logic implementation, we are not limited to a single return or output item. We can have as many as we need. Using classes to implement business logic has a lot of benefits.

image

Most of the magic of the business action is implemented in the ActionBase or more so in the framework Action class. The following shows the base action class which is a generic. It contains the common or shared elements of the business action and inherits from the Vergosity Framework Action class which is abstract. This base class contains a ProviderBase class which coordinates calls to other business actions within the specified service.

image

Vergosity Framework :: Action Class

The Action class provides the structure or processing pipeline for the business logic implementation.

image

The action process is started by calling the Execute() method. This is the implementation of the Template Method pattern. There is a series of things that happen before and after the execution of the actual business logic. And as you can see from the diagram above, if you want to include any additional behavior – there are several events that you can hook into to add your own custom features.

If everything goes well, meaning that the user is authorized via permissions and no business rules or data validations have been evaluated false – the call to the ProcessAction() is made. This is where the actual business logic is implemented or what you define as the action to perform.

image

There is a lot more going on in the StartAction() and the FinishAction() method calls – but for now just understand that there is a pipeline of processing for the execution of a business action. If you use business actions to implement all of your business logic, you have a very consistently mechanism for managing the process. Adding new behavior or features globally (to all business actions/logic items) is very easy using the base classes.

How Business Actions Are Called

You might be wondering how business actions are called. They are simply initialized as any class would be and started by using the Execute() method. The following example is more advanced because it is using Dependency Injection – but the approach is the same:

1. Initialize the action and pass in the parameters to the constructor.

2. Execute the action.

3. Retrieve the return object of the action.

image

You do not have to use Dependency Injection, however, the sample application I’m using demonstrates an architecture that takes advantage of DI techniques. The DI container is resolving the ActionManager<T> – a generic class. This generic type is injected with a BusinessProvider instance that is injected with a one or more Repository items used for data operations. There is a lot of opportunity to remove dependencies from your application objects by using DI. What we see in the ActionManager<T>.Execute() method is the actual call to the business action’s Execute() method. Using DI allows for more extensibility of my implementation of business logic. I can control how my business logic is wrapped and called – without effecting the actual implementation of the business logic. .

image

Conclusion

Using a class-based approach to implement units of business logic has many benefits. The implementation is very consistent and maintainable. Extending or adding new behavior is much easier using the base classes and/or using depending injection. Since each action class is a specific unit of business logic – there is a lot of opportunity to perform unit testing and perhaps using a test-driven approach to the implementation of the business logic.

The Action part of the Vergosity Framework is even more powerful when you combine it with the power of the business and data validation rule engine. Decorating your target objects with rule attributes is simple and easy.

Test-Driven Development – A Life-Style or a Process?

Recently, I had the pleasure of working with a talented team of software engineers to increase their awareness of how they could do more with test-driven development. The team was highly skilled and knew how to write unit tests. One of the discoveries during the process, was that they needed to make their software more testable to enable the test-driven approach. We covered a lot of ground during the 2.5 days of work. One of the best outcomes of the session, was that testing is really more of a developer lifestyle than just a process. We realized that the process of testing really helped with the design of the software and that there was a lot more analysis and design when taking the test-driven approach.

It is important to take time to think before you write code – and sometimes this thinking should be as non-technical as possible. It shouldn’t involve writing code or the IDE – maybe some simple pencil sketches are all that is required. TDD doesn’t rule out thinking, analysis, or design before you write code. It is part of the natural process and needs to be included in the flow of TDD. Here is my slide deck used to facilitate some of the discussion.

Slide Deck: Test-Driven Development

Fries on the Floor

A story about technical debt…

I work on an application that tracks millions of requests each day. There was a time when we recycled the application pools of the web servers in the web farm. During this process we lost a few seconds of processing – in which there may be a few thousands requests not tracked. I referred to this in a meeting awhile back as, “fries on the floor.” The analogy made me think about things that matter when they are added up over time.

It reminded me of the typical fast food restaurant. You look behind the counter and what do you see? A few fries on the floor right? Not a big deal. Moving at the speed of fast food and dropping a few fries on the floor is all part of business. But I got to thinking about how many fries (pounds) that adds up to be for a single restaurant, or all restaurants in a single day over a week, month, or year. A few fries on the floor probably add up to tons of wasted french fries. Why am I concerned? I’m not too concerned about the fries, really. But I am concerned with the mentality of waste and letting things build up over time – things that create technical debt.

Technical Debt

Using the same analogy to the software development life cycle, we are leaving some fries on the floor or in essence creating some technical debt. We do this on each sprint, cycle, project, new feature added, etc. Business moves pretty fast and most companies that develop their own software or solutions hire the minimum number of developers for the job less one, right? We’re all pretty busy. The problem is that we move on to the next round of features or stories to implement. And of course many of us are eager to do so – doing something new and different is pretty cool; and we are eager to please. But we are creating technical debt. It may not feel like it in the beginning, but over time the debt accumulates and starts to compound. Then we are in trouble. You have to address the debt.

Why not leave a few less fries on the floor each day by doing some or any of the following:

  • design first
  • thorough business analysis
  • peer code reviews (daily)
  • refactoring loose code
  • test-driven development
  • unit testing for a specified amount of code coverage
  • alternate flow unit testing (negative tests)
  • performance analysis of the new release
  • making specific elements configurable vs. hard-coded
  • refactoring to a design pattern
  • documentation of the feature
  • code review by team
  • ________________ (add more items here)
I’m not saying we have to do all of the above all of the time. But it would be fair to say that there are fries on the floor at 5pm each day. They may not seem like a lot at the end of the day. But if we tracked what we didn’t do over time and how it effected our future development – it might surprise us! Maybe we can leave a few less fries on the floor by taking the time each day to do what we know needs to be done. This may increase the development effort. But we should be including many of these elements in our estimation. Then we can communicate the estimates and progress accurately and honestly with our project managers, CTOs, or IT Directors/Managers. In this everything has to be done yesterday mentality, it is going to be difficult. However, if we stick to the art of pragmatic programming, we can reduce a significant amount of technical debt. The benefits will be seen and recognized over time.