Monday, December 12, 2022

Test Driven Development (TDD) more then software tests

In the practice of software projects and software developers there are great misunderstandings about test-driven development (TDD). Most developers do not see or know the difference between JUnit testing and TDD. They believe that TDD is a theoretical, time-consuming testing approach.

 TDD is more then testing:

  1. Proof that your code does the expected thing
  2. Safety net for (your ongoing) refactorings
  3. Helps you to separate concerns in your code
  4. Last but IMHO most important, TDD is the spec of your code


PS: If you think you have to spend more time for the TDD, try it without.

Sunday, October 9, 2022

Agile Anti-Pattern: Architectural Decision Records (ADRs)

Architectural Decision Records (Link) are ... a decision log. How can ADRs improve the agile software development? What is the ADR benefit? I can't see it. For me ADRs looking like an 'cover your ass' thingy. After reading most of the linked articles, I'm very confident that ADRs are a new kind of the obsolete old Waterfall  Software Development with a cool name. It breathes the old idea that it is possible to catch all software requirements before we start to developing. This wrong assumption lead us to the first software crisis, it's proven false in the 90s and in 2022 too.

Suggestions:

  1. Don't use ADRs
  2. Talk with your real customers and write extensive user stories


Thursday, October 6, 2022

Software Architect as Agile Anti-Pattern

You can find Software Architects in I guess the half of all German software projects. A Software architect is often a formerly senior developer. Sometime he is part of a software development team sometimes multiple Software architects are aggregated a Architecture Teams. Why companies think that a Software architect is good idea:

  1. Increasing the software quality
  2. Have the big architecture picture in mind and keep every thing right
  3. Avoid divergent development branches 
  4. Avoiding the development of concurrent solutions for the same problem over different teams

If you know more arguments for Software architects, please comment below.

 The main misconception is that companies and many developer too don't understand that software development is different to 'normal' engineering or building a house. The major difference is the complexity! Software development is much more complex.  This is also the reason why all model driven software development approaches fail.

Lets talk about point 1, Software architects ensure software quality. How could he do that? Bad Idea, give him the power to merge feature branches. This gives him the power do suppress alternative ideas. This means the software architect impede the software development progress. If he accept only code that is like his code he additionally blocks all development because every other developer have to ask for every thing. The creates a frustrating situation in the whole team. At the end, we impede progress, limiting work throughput and frustrate the software developers. 

Point 2, that's for me a pseudo argument. No team need a dedicated developer for this purpose. This is done by normal inter team communication. There is no befit but higher costs.

Point 3. Many project people like many developers believes that alternative solutions are bad because it"s a wast of time. But this not right. What you have to understand is that alternative solutions are great. You can choose between different solution and take the better one. If you have only one solution there is a risk that your current solution is the worst solution but in case of multiple solutions your are sure that the chosen solution is not worst solution. This is a totally underestimated benefit.

Point 4. This is a general misunderstanding of requirements. On the first view same problems looks equal. But in reality the problems are different. If someone comes with this idea around the corner please understand that this phrase is an indicator of a lack of user stories aka requirements. Pressing the second problem into an existing software solution ends up with a huge bunch of  technical debt and missing of at least one requirements.

At the end the software architect is not needed an brings more risk to every agile project. May software development can learn from golf. Golf is not a game of perfect. Golf is a game the best miss. The one that makes the smallest mistake wins. 



PS 1: Software architects are almost formerly senior software developers. Now in the new position they spend most of the time in meetings. Some of them have no time for coding. The advises they give are 5 to 10 years old. It's greeting from the past but not an improvement.


PS  2: I also worked together with great software architects (greetings to the real Mirko). But these guys working differently.



Tuesday, July 26, 2022

Test Coverage as Software Metric

The measurement of test coverage is often used as indicator of software quality. This is OK but be a aware of following interpretation of this number, if the test coverage is low that means:

  1. You have to write tests
  2. You are in trouble because your code is not developed in the TDD way and the code is not easy to extend or to maintain.

On the other hand if the code coverage is high, this means nothing. Or with other words: 

High code coverage != High quality code




Friday, June 17, 2022

How to build stable and reliable System Test for Micro Services

Work in Progress, I'm currently overwork this article. Please come back later!

 

 

System tests are testing the orchestration of a bunch of micro services. Most of the test covers external features used by other micro services or by the front end.

If the current micro service is optimized for resilience (Yeah, Great) then system tests on feature endpoints can't discover errors related to (incoming) dependend micro services. The root cause of this lower power system test is the decoupling of micro services eg via the Fail Fast Pattern  or other Circuit Breakers (Thanks to Netflix). Or with other words resilience pattern could reduce the value of system tests.

System Tests improved by Diagnostic Endpoints

One way to avoid this negative side of resilience is to introduce what I called Diagnostic Endpoints. A diagnostic endpoint is only used by system test an not by features. The goal of diagnostic endpoints are to verify that functions that are covered eg by resilience pattern work.


In the real world, we save a huge amount of time after establishing of diagnostic endpoints. The software developers and the Project Owner love them.

Saturday, February 26, 2022

How to avoid Fat Git PRs with massive changes

Fat PRs with massive changes are a huge  and anyoing workitems for reviewers. The question is how to avoid these massive Git pull requests (PR)? But there is a more easy way.

Massiv PRs contains many changed files. If you look more into the detail you can recognize differtent pattern of code changes:

  1. Code changes not related to the new function. These changes are clean-ups olf existing code without any relation to the new functionaliity. These changes are caused by the boy scout rule "Every time you work on some code it may get a little bit better." This is called Tidy First.
  2. Changes that relates to the function but are only preparations for the following implementation. These changes are functional neutral.
  3. The new feature itself.
  4. Cleanup the new feature code. These changes are also functional neutral.

The idea is to split large PRs into smaller PRs by seperation of these concerns. This keeps PR small an easy to review.

The down-side of these PR seperation of concerns that all code changes are spread over multiple PRs. You review 3 times code that will properly change again. Rool-backs are maybe a little more nasty. 

At the end reviewing 4 PRs looks like extra effort but it isn't because every PR is bound to his own concern. That makes it much easier to review.

Monday, February 7, 2022

Fail Fast vs Fail Early

If you look into Stackoverflow or so, you see tha Fail Fast and Fail Early used as synonyms. But that is not true. Let me just explain it.

Fail Early

Fail Early is working on method level.  The idea of Fail Early is to verify at method entry the parameters. The result is an early return or an early exception. The downside of fail early is that you have multiple exit points. That's why you have to keep your method short. But you have always to keep the method short or you handle different concerns in it.
At the end fail early is a technique to verify method parameters at the start of the method to avoid issues caused by data. The Lombock annotation @NonNull is a simple kind of fail early.

Fail Fast

Fail Fast is working on System Level. It's a technique to improve the resilience of micro services. It's a server side implementation of a circuit breaker. I developed this idea 2014 for a German company but I think many other software engineer also has the same idea. The fail fast pattern could be implemented in diefferent ways and for differen aspects of the software system. Now two examples of the fail fast pattern show the different aspect of it:

Fail Fast Example 1: Health Check

The micro service monitors his own health and if the service in unhealthy maybe because of an unhealthy or not responding subsystem the service can decide of fail fast some related (HTTP) request without going the whole service to the unhealthy state.

Fail Fast Example 2: Performance Check

The micro service monitors his own  request runtime. If the runtime exceeded a timeout the the service can cap the reuqest execution to free resources and response with an (HTTP) error code. This improves the performance resilience of the software system.

If you understand this pattern, you can imagine that are many more cases for Fail Fast.

Over all, the Fail Fast pattern avoid that slow or weak subsystems can shuts down all your services. It's a kind of an circuit breaker apttern.

Summary

  • The difference between Fail Fast and Fail early is the Abstraction Level. Fail Fast protects your micro service. Fail early makes your methods more stable. At the end you should use booth.