How to avoid triggers revisited.

Posted: 2013-11-05 by Rikard Mathisson in Best Practices, Databases
Tags: , ,

When I wrote the paper “why to avoid triggers and how” a couple of years ago my current target DB was MSSQL so I forgot to mention what applies to Oracle regarding part 4.1.

4.1. Enforcing complex integrity/business rules.

Add CHECK constraints to your fields in your create
table statements [5a]. They allow using UDF:s (user
defined functions) for constraint validation. Such UDF:s
may be very complex and since they are faster than stored
procedures, and only runs when data is updated in
affected columns, they are highly efficient. Note that
check on computed columns requires persisted option (4.4
below).

Oracle allows neither user-defined functions nor sub-queries on check constraints, so that leaves out any obvious workaround for triggers. That is for implicit constraints. It is still possible to enforce explicit business rules (procedure call, for example) before committing data inside a transaction to allow late data rejection, if not prevented early in a code flow.

Early rejection of illegal values are of course preferred in any case.

Double Dabble

Posted: 2011-12-19 by Roger C S Wernersson in Best Practices, Design, Programming, Refactoring, Unit Tests

I’ve been trying out a bit of TDD.

Basically, I think TDD is the only way forward.

I’ll start at the beginning.

Code evolve, and as it does, it also decays if not pruned, a bit like a garden in that respect. Pruning mean refactoring to make it fulfill its evolving purpose.

Refactoring is only ever safe if we have a good unit test coverage. Unit tests we write after the production code is written are OK at best, because we tend to test things we know works. We also tend to test in a way that makes it harder to change the implementation, because as we are aware of the implementation, we take shortcuts. I’ve seen this a lot of times.

TDD forces us to write the test code first, before the production code. Hence, we can’t test the implementation, because there isn’t any. This makes it much easier to refactor the production code.

However.

The TDD cycle is something like this: write a test, test fails, write production code until the test succeeds, refactor the code.

Now, most people skip that last step.

But from what I’ve seen, even people who actually do the last step doesn’t do it fully; they refactor the production code, but not the test code. This will be their downfall. As test code decays, the production code will go stale and then everything goes downhill.

Here’s the problem: How do you ensure that you don’t break the test code when you refactor it?

I’ve mostly used TestNG. It might be a TestNG only problem, but I doubt it.

Let’s say I’ve got some production code I want to test, in this case equals(), a method actually generated by Eclipse.

    public boolean equals( Object obj )
    {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        if (myId != other.myId) return false;
        return true;
    }

Here’s my test method, using FEST asserts for the nice flow:

    @Test
    public void equalsIfAllFieldsAreEqual()
    {
        Person actual = createPerson();
        Person expected = createPerson();
        
        boolean isEqual = actual.equals(expected);
        
        assertThat(isEqual).isTrue();
    }

Not much to refactor, but it’s only an example. If I make a mistake when I refactor the production code, the test will fail and I’ll know.

But if I make a mistake when I refactor the test code so that I now test something else, or even worse, I don’t actually test anything, how would I know?

I gave this some thought and came up with a solution, but it’s somewhat convoluted. Here it is:

I’ve added a new class of which I need an instance for each testable feature:

public class Testable
{
    private boolean myState = true;
    private boolean myWasDoubleChecked = false;
    private String myName;

    public Testable(String name)
    {
        myName = name;
    }
    
    public boolean asBoolean()
    {
        return myState;
    }

    public void activate()
    {
        myState = true;
    }

    public void deactivate()
    {
        myState = false;
        myWasDoubleChecked = true;
    }

    public boolean wasDoubleChecked()
    {
        return myWasDoubleChecked;
    }

    public String getName()
    {
        return myName;
    }
}

Then I need to add an instance for each testable feature.

public class Person
{
    private int myId;
    public static Testable FEATURE_EQUAL_IF_ALL_FIELDS_ARE_EQUAL = new Testable("equal if all fields are equal");
    public static Testable FEATURE_EQUAL_IF_SAME_OBJECT = new Testable("equal if same object");

    public boolean equals( Object obj )
    {
        if (this == obj) return FEATURE_EQUAL_IF_SAME_OBJECT.asBoolean();
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        if (myId != other.myId) return false;
        return FEATURE_EQUAL_IF_ALL_FIELDS_ARE_EQUAL.asBoolean();
    }
}

I added a new class which must be the base class for all tests:

public abstract class DoubleTester
{
    private boolean myDoubleCheck = false;
    private List myFeatures = new ArrayList();

    @BeforeClass
    public void createFeatureList()
    {
        addFeatures();
    }
    
    protected abstract void addFeatures();
    
    protected void add(Testable feature)
    {
        myFeatures.add(feature);
    }

    @AfterMethod
    public void activateAllFeatures()
    {
        for(Testable feature : myFeatures)
        {
            feature.activate();
        }
        
        myDoubleCheck = false;
    }

    protected void check(Testable feature)
    {
        if (myDoubleCheck)
        {
            feature.deactivate();
        }
    }

    protected void doubleCheck()
    {
        myDoubleCheck = true;
    }
    
    @Test
    public void makesSureWeRunAfterClass()
    {
    }
    
    @AfterClass
    public void makeSureWeDoubleCheckedAllFeatures()
    {
        for(Testable feature : myFeatures)
        {
            Assert.assertTrue(feature.wasDoubleChecked(),
                    "Add double check for \""+ feature.getName() +'"');
        }
    }
}

This means a test class must do the following:

public class PersonTest extends DoubleTester
{
    
    @Override
    protected void addFeatures()
    {
        add(Person.FEATURE_EQUAL_IF_SAME_OBJECT);
        add(Person.FEATURE_EQUAL_IF_ALL_FIELDS_ARE_EQUAL);
    }
    
    @Test(expectedExceptions=AssertionError.class)
    public void doubleCheckEqualsIfSameObject()
    {
        doubleCheck();
        equalsIfSameObject();
    }
    
    @Test
    public void equalsIfSameObject()
    {
        Person expected = createPerson();
        Person actual = expected;
        
        check(Person.FEATURE_EQUAL_IF_SAME_OBJECT);
        boolean isEqual = actual.equals(expected);
        
        assertThat(isEqual).isTrue();
    }
    
    @Test(expectedExceptions=AssertionError.class)
    public void doubleCheckEqualsIfAllFieldsAreEqual()
    {
        doubleCheck();
        equalsIfAllFieldsAreEqual();
    }
    
    @Test
    public void equalsIfAllFieldsAreEqual()
    {
        Person actual = createPerson();
        Person expected = createPerson();
        
        check(Person.FEATURE_EQUAL_IF_ALL_FIELDS_ARE_EQUAL);
        boolean isEqual = actual.equals(expected);
        
        assertThat(isEqual).isTrue();
    }
}

That’s it, basically.

Now, I’ve got several issues with this.

1. I need to add code to the production code, which makes it a source of errors. I could just add it for tests I want to refactor, but now that I know of the problem, I want to double check all my tests.

2. There is probably a performance impact. How do I get rid of that in production?

3. Will I ever get anyone else to write tests like this?

I think there might be a way of doing this using annotations. It would nice to be able to do the following instead:

@Testable
public class Person
{
    private int myId;

    public boolean equals( Object obj )
    {
        if (this == obj) return true; @Doublecheck EQUAL_IF_SAME_OBJECT
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        if (myId != other.myId) return false;
        return true; @Doublecheck EQUAL_IF_ALL_FIELDS_ARE_EQUAL
    }
}

And then have the test code go like this:

public class PersonTest extends DoubleTester
{
    @Doublecheck
    public void equalsIfSameObject()
    {
        Person expected = createPerson();
        Person actual = expected;
        
        @Check=Person.FEATURE_EQUAL_IF_SAME_OBJECT
        boolean isEqual = actual.equals(expected);
        
        assertThat(isEqual).isTrue();
    }
    
    @Doublecheck
    public void equalsIfAllFieldsAreEqual()
    {
        Person actual = createPerson();
        Person expected = createPerson();
        
        @Check=Person.FEATURE_EQUAL_IF_ALL_FIELDS_ARE_EQUAL
        boolean isEqual = actual.equals(expected);
        
        assertThat(isEqual).isTrue();
    }
}

Either way. I’d like to know what everyone else is doing to address this.

How do you make sure you don’t break the test you refactor?

/Roger

Flattr Roger

An Agile point of view

Posted: 2011-07-06 by Rikard Mathisson in Methodology

I’ve had a long WordPress break due to a recent career change. Becoming a consultant have given me a slight change of perspective since I’ve been moving from product development to, more or less, producing hours

Thinking about perspectives; often different roles in a project have very different perspective upon measuring lead time, resources and workload. Even though most of the industry have accepted agile processes as cost effecient and an resource effective tool for reducing waste and getting prioritiez right – not everybody gets it! Agile methods have become the daily bread of all kinds of companies; ranging from telecom to car manufacturing.

It seems to me that understanding agile methods is a essentially different from implementing them! Take SCRUM, for example; just adding tasks as post-it on a whiteboard does not make you Agile. And in turn, that does not make you produce less waste or being able to deliver prioritized values on target or on time. It does neither make your team members happier or reduces the need for quality requirements. It also does not make your teams able to work disconnected from the customer (a.k.a black-box), which by the way is probably as far from SCRUM as you can come.

This should be obvious, it may seem. However, that is probably due to my software engineer perspective. Apparently not everyone involved in software development processes understands that reducing waste and increasing quality is hard labour that requires planning and serious thought. Good quality does not come from yellow post-its. Neither does more output.

It seems that due to your personal perspective, you may or may not understand that number-crunching is not actually a part of the production; it is just a tool for measurement. And as such, measurement cannot be achieved without affecting the outcome! Hence, the less you measure, the more effecient you can produce.

when measuring the  physical state of a quantum system there’s a fundamental limit to the amount of precision that can be achieved
/Werner Heisenberg

However, I have come to mind that whether this is true or not, in the arbitrary team, depends on that team’s perspective on labour. It  heavily depends upon the level of engagement and self-propelling in the team itself!

Conclusions

  • Output may be negative affected by the method of measurement, which also have impact on the quality of the output
  • Poor output  is a management problem and not a measuring issue, and there are proper Agile ways to deal with it
“Working more hours” does not necessarily mean “producing more output”
/Agile SCRUM

Testing my Heritage

Posted: 2011-03-13 by Roger C S Wernersson in Best Practices, Programming, Unit Tests
Tags: ,

I love being right. So much so, that if I discover that I’m wrong, I change my mind immediately. I think I was wrong about this last week. Unfortunately, this might turn out to be more of a discussion than anything else. However, the journey, as we all know, is the goal. I don’t think I’ll be changing my mind on this again though. (But I’m willing to do it if I’m proven wrong. 🙂

I think the best approach is to test all inherited methods by having your DerivedClassTest classes inherit from BaseClassTest class. This way you will test all important methods of the base class from the point of view of all the derived classes, ensuring that you didn’t introduce any bugs when over-riding base class implementation.

I hate to remove the previous content of this post, because I thought I was so clever. But as the saying goes; sometimes you have to Kill Your Darlings.

Flattr Roger

Eclipse Quickies

Posted: 2011-02-09 by Rikard Mathisson in Programming
Tags: ,

Working with Eclipse everyday combined with being pro-keyboard usage I get pretty annoyed sometimes that Eclipse forces me to use the mouse more that most other IDE:s.

However, here is a quick list of shortcuts that applies by default in Eclipse and that are most useful, although sometimes annoyingly limited.

Happy coding!

Read the rest of this entry »

The Knights who say NIH

Posted: 2011-02-02 by Roger C S Wernersson in Documentation

As I’ve written about before, I’m interested in humans reading and remembering what I write. Therefore I try to tease the brains of the reader with BDD User Stories about characters to whom the reader can relate.

I wrote a quite amusing user story involving Hansel and Gretel. To illustrate this I added a picture of a gingerbread house. Now it looks like it will be removed because a colleague higher up the food chain thinks it is unprofessional.

It is frustrating. I’m trying to improve, reach higher, make the organization and products better. Almost everyone who read these documents are very positive to my ideas.

I think I’ve just met one of The Knights who say NIH ( Not Invented Here).

 

Flattr Roger

Shifting DOS Parameters

Posted: 2011-01-17 by Rikard Mathisson in DOS, Programming
Tags: ,

Every now and then you’ll find myself in need to automate tedious and repetitious work task like this;

  1. update local source from repository
  2. clean and deploy the source
  3. run unit tests- run static analysis
  4. more of this stuff …

… repeating it over and over again. In this situation I often find myself writing batch scripts in DOS (trying to keep scripts compatible with most Windows versions).  One of the (many) annoying limitations in DOS scripting is that you can only refer to maximum 10 parameters. And already with a few parameters you might end up with all parameters being mandatory rather than optional.

Here follows a rather complete code example for DOS which shifts out parameters and run blocks of the script based on what parameters have been set.

Ps. If you read the code carefully, I’ve included several general hints about writing .bat scripts. Sorry btw for the syntax coloring scheme, i found no MS-DOS syntax schema so I used perl instead, it’s almost the same anyway 😉

@echo off
@rem Author: rikard.mathisson@gmail.com
@rem Date: 2011-01-15

@rem Copyright: Just please give me credit, otherwise public domain.

@rem This is an example of how to switch command line parameters in a
@rem simple (and best practice) way. Note that this script uses basic
@rem GOTO:s and :LABELS as we all did in the early 80's - but it's for
@rem good reasons - DOS does not handle flow control at all, unless you
@rem have the benefin of using Power Pack - which is not always possible.

echo This is a parameter demo. All CLI parameters will be looped and printed below.
set /a i=0 >> NUL
set silent=no
set filename=__unset

:LOOP

@rem Here is the part where your program should handle parameter input
@rem Jump to MAIN label, when no more parameters found, and do the main processing.
if "%1"=="" goto MAIN

@rem This counter is not only for nice printout but also to make it possible to know if no parameters was given. The redirect to NUL is just to avoid the result being printed to the console and the /a flag is to let the SET command know it's an arithmetic expression.
set /a i+=1 >> NUL

@rem Here you can process input parameters accordingly, lite switches etc.
@rem I include a small and simple example of handling switches where the /s switch will make this script silent and the /f switch will allow output to a specified file. /? will jump to HELP section without processing other parameters.
if "%1"=="/?" goto HELP
if "%1"=="/s" goto SUB_S
if "%1"=="/f" goto SUB_F

if "%silent%"=="no" echo [DEBUG] parameter #%i%=%1

:RETURN

@rem Get the next parameter into %1 and repeat
shift
goto LOOP

@rem This is a good place to put help text when the user forgot using parameters.
if %i%==0 echo goto HELP

:SUB_S
@rem This is the subroutine for handling the /s switch.
set silent=yes
goto RETURN

:SUB_F
@rem This is the subroutine for handling the /f FILENAME switch.
@rem Note that it shifts out another (the FILENAME) parameter.
shift
set filename=%1
if "%silent%"=="no" echo [DEBUG] FILNENAME set to "%filename%"
goto RETURN

:MAIN

@rem This is the main program section. Add your subprogram here.
@rem Example code writes the "dir" output to a file, if specified, otherwise to console (STDOUT).
if "%silent%"=="no" echo [DEBUG] MAIN Begin

set mycommand=dir
@rem Note that the caret (^) is used for escaping the redirect (>) character below.
if not "%filename%"=="__unset" set mycommand=%mycommand% ^> %filename%
if "%silent%"=="no" echo [DEBUG] MYCOMMAND set to "%mycommand%"

@rem Note that the line below executes the value stored in mycommand
%mycommand%

if "%silent%"=="no" echo [DEBUG] MAIN End
goto END

:HELP
echo Syntax: params [/s] [/f FILENAME] [...]
echo - /s mutes the debug output
echo - /f send main output to FILENAME istead of console

:END
if "%silent%"=="no" echo [DEBUG] DONE!
Silence: Silence is golden, Doct tape is silver!

Duct tape is another way of making things silent...

In a well formed development environment, where unit tests have been added during feature implementation for quite some time, almost always will be sensitive for code changes. Any change may break several to many unit tests, especially during refactoring… And change is inevitable, as we’ve known for a while now 🙂 How would you cope with all those unit tests without a major meltdown during the refactoring of core features’ source code?

I am trying to break as few unit tests as possible during changes, which not always may be an easy task. But here is a formula I’m working at, from a method-refactoring perspective in Java:

1a. To make it clear where the code may have to change, add an @deprecated annotation to the old method interface. Now there will be an indicator about how many unit tests will break and you can easily hunt them down.

1b. Alternatively, throw a checked exception from the old interface. This will break the code and point out more clearly where the old interface is used. Mark the affected methods with TODO tags or similar, then remove the checked exception to make the code build once again.

2. Implement the new method and write new unit tests testing it thoroughly. Make sure it works.

3. Optionally, review and commit your work already at this point. The code should still be 100% stable since no regression have been applied.

4. Now go back and locate the methods using the deprecated method (1a or 1b), first change unit tests – one at a time – before changing any collaborating core source code. Pick one unit test and continue with next step.

5. Be prudent and make sure the unit tests you rewrite still is at least as good as before. If the unit tests are incomplete, now is a good time to add missing parts – I.E missing negative testing, new code flow etc. Also look out for diminishing code coverage; the new method may need different testing perspective. Note if the current unit test is useful when applied on the new method.

6. Repeat 4-5 until all unit tests use the new method, then make sure all works as supposed to!

7. Review, commit, etc.

8. Clean up, remove obsolete unit tests and remove the deprecated method. Review and commit again.

The above process takes a little more time than having a more aggressive approach, but there are far less risks involved and the code is stable 100% of the time. Also, if you for some reason have to deliver an incomplete feature, a.k.a increasing the technical debt, you still can do that – with intact stability. And keep on cleaning it up in the upcoming sprint.

Be prudent! Be patient! Be consistent!
Then the magic will work in your favour!

Somehow server and client time is always messed up at some point in a software system’s evolution… I’ve been trying to figure out how to make this a brief post for quite some time – but although my recipe below is simple, the problem quickly becomes complex and nontrivial unless done correctly from the start. It is a usual, tricky and expensive problem, that is a little earns some explanation, so here we go…

Because the daylight saving rules for local time zones are so convoluted and can change based on local law at unpredictable times, true interoperability is best achieved by using Coordinated Universal Time (UTC).  ~RFC3339

The trinity of timing; server, software and UI!

The Y2K frustration all over again:

How often does not one run into the situation where a deployed software or Internet service at some point have or have had issues with incorrect time stamps or unsynchronized clocks. When the situation evolves in different systems the impact depends on the kind of software. A payment provider will have a much critical situation at hand than a simple blog. But the basic problem is almost certainly the same!

Issues known to happen, any day now on a system near You:

  • The application server clock wanders off – eventually seconds becomes hours
  • The database is on a separate server, clocks out of sync with the app server
  • End user meets an off-shore server time instead of locale translation which should include daylight saving adjustments – affecting schedules, etc
  • Synchronizing SYSLOGs collected from several servers  becomes an impossibility and are impossible to correlate
  • The database uses getdate instead of getdateUTC and it becomes a stealth bug when searching for internationalization bugs
  • Time stamps was collected with regard to daylight saving time, but no one knows which locate was used
  • Users in different locates cannot cooperate due to locale issues, using common calendars does not work well
  • Chat logs contains time-zone dependent time stamps and cannot be correlated
  • Data aggregation becomes error prone due to arbitrary time stamps (datetime) from unclear sources
  • … or any other data-, schedule- or log timing issues

The why is embedded in the constant-change nature of software:

Here is a typical real-life scenario, walking through a number of system versions…

  1. All the software is run on one piece of hardware, the application, the database (if such exist)  and all client software (I.E. webserver, jboss, etc). All users are in the same locale or physically in the same building.
  2. The software breaks up into client and server, locale from user’s desktops turns up, but all users are still in the same locale.
  3. Parts of the system is migrated to new hardware with it’s own clock, like directory services or the database. They are still in the same locale though.
  4. International users is incorporated, meeting a global market. This means users with different locales.
  5. New clients are developed, I.E. webclient, desktop- and handheld clients, etc.  This means the same user accesses the software from different locales, possibly simultaneously.
  6. The system becomes distributed and the cloud gets several servers with different locales.
  7. Security requirements emerge and SYSLOG becomes a requirement as well as correct timing on events etc.

When does the problems first emerge, and when does it become a critical red bug:

The first timing problems surfaces already in version 2 , where the user may or may not see correct times depending of the lag between the server and client clocks – the quick fix often selected is to only show server time – which is fine, for now.

In version 3 it get’s serious – many security issues relates to different clock in the database. Unless fixed, the system becomes more vulnerable to some attacks from this point.

In version 4, 5 and 6 the “now” concept becomes increasingly complex. Unless sorted out quickly and required refactoring is applied, it will eventually become a mess – and nobody will ever know when problems emerged, just putting a bug report will make anybody nausea – you simply can’t tell what time stamp is being used.

In worst-case, in version 7 the problem becomes obvious, unless detected previously. From that point you simply cannot proceed without rewriting vast parts of the system.

How do I keep it on track then, if it is that obvious?

The thing is; there is ever only one time! – There are however a few perspectives: server, desktop user, web user, etc – just to mention some. Only in the user perspectives any locals should be applied, and only when the date/-time is visualized. Never apply locales  otherwise!

The recipe is simple, in detail below:

  1. Synchronize all hardware clocks using ntpd or equivalent
  2. Use only UTC format (see SYSLOG note)
  3. Specific locales may be applied ONLY when visualizing to end user

Step 1: Make sure all server clocks are synchronized with an atomic clock using ntpd or equivalent. Make sure any firewalls and routers will let this clock synchronization through. An isolated test environment, cut off from the Internet, should be synchronized with a local NTP server, that will have the same effect. Watch out for firewalls blocking NTP traffic though…

Step 2: Then make sure all software use only the UTC date and time format. This will store enough information to get it all right, unless you hack – then you will most certainly fail 😉 There are few general datetime libs that gives any clue to the wrongdoing in localized datetime, but if you use non-UTC libs you will probably end up not being able to put together locale-independent UTC-equivalent methods without messing it up… Instead, just keep it simple and use UTC-compatible libraries whenever possible.

Step 3: Only when an end user meets the software via user interfaces you should worry about locales like date format, time zone and daylight saving times. Never in other classes. Never on the server. When the user may input date and time for scheduling you still only have to worry about this in the UI classes! Make sure to always translate from locale to UTC before sending to server.

Time-Zone note: Synchronized server clusters distributed over several time-zones is not either a problem; a server in New York  has the UTC timezone specified a -04:00 and  a server in Stockholm has +01:00 in the winter and +02:00 in the summer. Make sure the server is correctly

SYSLOG note: In the early days, the year was 2001, SYSLOG RFC3164 emerged. This RFC which have an annoying flaw – it is locale dependent and you cannot decide the correct time stamp once it is written! Even today many servers and solutions depend on the RFC3164. There is a new, much more general and UTC-compatible SYSLOG RFC5424 that is preferred if you have the choice. If not, it is crucial to set up all syslog servers using the same locale – otherwise you will have to translate incoming SYSLOG events to the local time zone before adding them to a central server. This is not very hard to do, but unless you do it you will not be able to apply correct time stamps in an environment where log time stamps is a critical piece of information regarding the integrity of audit events and such (when did who do what where and what is affected). Besides from the time-zone information, the RFC3164 omits year and milliseconds. Also note that RFC5424 obsoletes RFC3164 altogether. Comparison between the two SYSLOG timestamps below.

What date and time is it? RFC3164 RFC5424 January 3rd 2010 USA,EST 3:33:59 AM Jan 3 03:33:59  2010-01-03T08:33:59-04:00
December 25th 2010 Sweden,CET,Winter Noon Dec 25 12:00:00 2010-12-25T12:00:00+01:00
December 25th 2010 Sweden,CET,Summer Noon Dec 25 12:00:00 2010-12-25T12:00:00+02:00


Conclusion:

Obviously, it is not trivial to decide the exact time stamp if you use any other format than UTC. See RFC3339 for more details about the internet time stamps especially.

Regarding Martin Fowler’s Technical Debt Quadrant, I agree with the critical voices that states there should be no bad code or unintentional results in what is considered technical debt, at least when applied on Cunningham’s definition of technical debt (1992).

However, point taken, Fowler states that after the job is done – however clean and tidy it may be – you figure “what the design ought to have been”. I agree that this is often the case with new features, but I state that it’s more recurrent when working with new stuff than revisiting and refactoring old features – since then you actually know what should have been the first time.

If implementing a feature according to given specs and user stories, and everybody is happy in the end – how can that be a wrong? Since Agile states that continuous improvement is required, otherwise the product will wither and die, following the Folwer statement that would mean you would almost certainly always produce an increased technical debt on new stories. Then becoming Agile would become a paradox unless Tech Debt is constant.

I however disagree with that. Those ones not being able  to deal with the constant-change-factor, are in trouble. And it’s not Agile. Merely redefining technical debt to include all possible design-, story-, spec.-  and other organizational- problems is insufficient, and wrong in so many ways. 🙂

However, defining a more general non-exclusive perspective on decay would be be beneficial; including a more self-awareness on the, from a developer team’s perspective, external organization-units dependencies – like the sales and marketing department, project lead, customer services, etc.

I agree with Fowler in many ways and also state that there are problems that surfaces only after deployment, however the terminology does not suffice upon this, so here I go…

Including all possible problems in a new definition rather than redefining Cunningham’s old one, I’d like to introduce the concept of “Technical Dearth”, or more crude; “Tech. Death” – when dealing with decay and evolution beyond the technical debt definition.

Fowler's quadrant in the Tech Dearth perspective.

Fowler's quadrant in the Tech Dearth perspective.

“The only thing constant in life is change.”
~François de la Rochefoucauld, ~1650

“He who rejects change is the architect of decay.  The only human institution which rejects progress is the cemetery.”
~Harold Wilson, 1967