OwnerOfBugs - 2026-01-20 08:38:04

Summary:


The following text is copied from [https://web.archive.org/web/20110712084057/http://testobsessed.com/2009/03/13/handling-bugs-in-an-agile-context/ archive.org] as the original article no longer exists. [[I]] found the original write up inspiring hence [[I]] referenced it from [[API Patch]] note. [[I]] still (in 2025) believe it is very inspiring text...

== Handling Bugs in an Agile Context ==

I was honored to be included on the lunch and learn panel at the Software Quality Association of Denver (SQuAD) conference this week. One of the questions that came up had to do with triaging bugs in an Agile context. Here’s my answer, in a bit more detail than I could give at the panel.

The short answer is that there should be so few bugs that triaging them doesn’t make sense. After all, if you only have 2 bugs, how much time do you need to spend discussing whether or not to fix them?

When I say that, people usually shake their head. “Yeah right,” they say. “You obviously don’t live in the real world.” I do live in the real world. Truly, I do. The problem, I suspect, is one of definition. When is a bug counted as a bug?

In an Agile context, I define a bug as behavior in a “Done” story that violates valid expectations of the Product Owner.

There’s plenty of ambiguity in that statement, of course. So let me elaborate a little further.

Let’s start with the '''Product Owner'''. Not all Agile teams use this term. So where my definition says “Product Owner,” substitute in the title or name of the person who, in your organization, '''is responsible for defining what the software should do'''. This person might be a Business Analyst, a Product Manager, or some other Business Stakeholder.

This person is not anyone on the implementation team. Yes, the testers or ''programmers may have opinions'' about what’s a bug and what’s not. The implementation team can advise the Product Owner. But the ''Product Owner decides''.

This person is also not the end user or customer. When end users or customers encounter problems in the field, we listen to them. The Product Owner takes their opinions and preferences and needs into account. But the ''Product Owner is the person who ultimately decides if the customer has found something that violates valid expectations'' of the behavior of the system.

Yes, that does put a lot of responsibility on the shoulders of the Product Owner, but that’s where the responsibility belongs. Defining ''what the software should and should not do is a business decision, not a technical decision''.

Speaking of expectations, let’s talk about that a little more.

When the Product Owner defines stories, they have expectations about what the story will look like when it’s done. The implementation team collaborates with the Product Owner on articulating those expectations in the form of Acceptance Criteria or Acceptance Tests.

It’s easy to tell if the software violates those explicit expectations. However, implicit expectations are a little more difficult. And the Product Owner will have implicit expectations that are perfectly valid. There is no way to capture every nuance of every expectation in an Acceptance Test.

Further, there are some expectations that cannot be captured completely. “It should never corrupt data or lose the user’s work,” the Product Owner may say, or “It should never jeopardize the safety of the user.” We cannot possibly create a comprehensive enough set of Acceptance Tests to cover every possibility. So we attend to both the letter of the Acceptance Tests and the spirit, and we use Exploratory Testing to look for unforeseen conditions in which the system misbehaves.

Finally, let’s talk about “Done.” Done means implemented, tested, integrated, explored, and ready to ship or deploy. Done doesn’t just mean coded, Done means finished, complete, ready, polished.

Before we declare a story “Done,” if we find something that would violate the Product Owner’s expectations, we fix it. We don’t argue about it, we don’t debate or triage, we just fix it. This is what it means to have a zero tolerance for bugs. This is how we keep the code base clean and malleable and maintainable. That’s how we avoid accumulating technical debt. We do not tolerate broken windows in our code. And we make sure that there are one or more automated tests that would cover that same case so the problem won’t creep back in. Ever.

And since we just fix them as we find them, we don’t need a name for these things. We don’t need to prioritize them. We don’t need to track them in a bug tracking system. We just take care of them right away.

At this point someone inevitably asks, “But don’t we need to track the history of the things we fix? Don’t we want to collect metrics about them?” To that I answer “Whatever for? We’ve caught it, fixed it, and added a test for it. What possible business value would it have to keep a record of it? Our process obviously worked, so analyzing the data would yield no actionable improvements.”

If we are ever unsure whether something violates the Product Owner’s expectations we ask. We don’t guess. We show the Product Owner. The Product Owner will say one of three things: “Wow, that’s a problem,” or “That’s outside the scope of this story, I’ll add it to the backlog,” Or “Cool! It’s working exactly as I want it to!” If the Product Owner says it’s a problem, we fix it.

If the Product Owner says “Technically, that’s a bug, but I would rather have more features than have you fix that bug, so make a note of it but leave it alone for now” then we tell the Product Owner that it belongs on the backlog. And we explain to the Product Owner that it is not a bug because it does not violate their current expectations of the behavior of the software.

Someone else usually says at this point, “But even if the Product Owner says it’s not a problem, shouldn’t we keep a record of it?” Usually the motivation for wanting to keep a record of things we won’t fix is to cover our backsides so that when the Product Owner comes back and says “Hey! Why didn’t you catch this?” we can point to the bug database and say “We did too catch it and you said not to fix it. Neener neener neener.” If an Agile team needs to keep CYA records, they have problems that bug tracking won’t fix.

Further, there is a high cost to such record keeping.

Many of the traditional teams I worked with (back before I started working with Agile teams) had bug databases that were overflowing with bugs that would never be fixed. Usually these were things that had been reported by people on the team, generally testers, and prioritized as “cosmetic” or “low priority.”

Such collections of low priority issues never added value: we never did anything with all that information. And yet we lugged that data forward from release to release in the mistaken belief that there was value in tracking every single time someone reported some nit picky thing that the business just didn’t care about.

The database became more like a security blanket than a project asset. We spent hours and hours in meetings discussing the issues, making lists of issues to fix, and tweaking the severity and priority settings, only to have all that decision making undone when the next critical feature request or bug came in. If that sounds familiar, it’s time to admit it: that information is not helping move the project forward. So stop carrying it around. It’s costing you more than it’s gaining you.

So when do we report bugs in an Agile context?

After the story is Done and Accepted, we may learn about circumstances in which the completed stories don’t live up to the Product Owner’s expectations. That’s when we have a bug.

If we’re doing things right, there should not be very many of those things. Triaging and tracking bugs in a fancy bug database does not make sense if there are something like 5 open issues at any given time. The Product Owner will prioritize fixing those bugs against other items in the product backlog and the team will move on.

And if we’re not doing things right, we may find out that there are an overwhelming number of the little critters escaping. That’s when we know that we have a real problem with our process. Rather than wasting all that time trying to manage the escaping bugs, we need to step back and figure out what’s causing the infestation. Stop the bugs at the source instead of trying to corral and manage the little critters.

Patch - 2026-01-20 07:56:40

Summary: /* Trying It */


How can a [[patch]] be distributed? When accepting [[API Patch]]es and having proper [[Git]] repository infrastructure one can probably think of a [[patch]] as a pull request. However, there are older and [[I]]'d like to claim still useful ways to deliver patches that work well with [[Git]] and other versioning systems. In fact this ''old [[good]] way'' is still in the heart of these versioning systems. [[I]] am talking about:

<source lang="diff">
diff --git channel/Channel.java channel/Channel.java
index da14c1bce6..0db8858d0a 100644
--- a/channel/Channel.java
+++ b/channel/Channel.java
@@ -493,13 +494,10 @@ public final class Channel<Data extends Channel.Config> implements AutoCloseable
* @return {@code true} if the exception was printed and further details should be printed
*/
private boolean printStackTrace(Throwable ex, boolean userCode) {
- if (!userCode) {
if (ex != null) {
ex.printStackTrace();
}
- return true;
- }
- return false;
+ return true;
}

/**
</source>

== Quiz ==

What do you think about the above text?
* I have a feeling I understand the patch
* I known what those lines starting with '''+''' and '''-''' mean
* I can apply the same changes to existing ''Channel.java'' file manually
* I known tool to apply the changes for me
** It is a UI application
** I can do it from command line
** I ask AI to apply the change for me
* I know the '''-p''' argument of the CLI command
* I know the '''-R''' argument of the CLI command
* I know something more than [[I|you]]!


== Answers ==

=== Reading ===

My colleague Ilya wrote: ''" In most cases, I will just observe the patch without applying it if it is small enough. (it usually is!)"''. In such case the situation is simple. Lines starting with a single '''-''' are the ones being removed and those starting with a single '''+''' are those being added. The header identifies the file that's being modified, but one doesn't really have to parse it - it is clear the above [[patch]] is related to ''Channel.java'' file.

=== Trying It ===

However sometimes just reading isn't enough. Sometimes we need to apply the [[patch]] locally to try how it behaves. Let's quote Ilya one more time: ''"If it is small enough (a few lines), I will repeat it manually, if ... typing everything by hand is not an option, I will apply it with [[git]]."'' [[I]] am not fully sure how to apply a [[patch]] with [[git]], but let's do it with another program (years older than [[git]]) which is (unsuprisingly) named [[patch]].

<source lang="bash">
$ patch -p0 <my.diff
</source>

The '''-p''' argument is very important. Without it [[patch]] command doesn't know how to interpret the header and locate the ''Channel.java'' file. In such case the [[patch]] command switches to interactive mode - which is quite annoying (but it shows how old the [[patch]] command is - it comes from ages when interactions with user were happening in terminal and not a [[GUI]]). Using '''-p''' argument avoids the interactivity.

With '''-p0''' the above patch seeks for ''channels/Channel.java'' file. One can use '''-p1''' to instruct [[patch]] utility to strip one level from the specified directories. Then the utility would be looking for ''Channel.java'' file only. By default use '''-p1''' for diffs generated by [[git]] '''diff''' command.

=== Pipe It! ===

The [[patch]] command expects the changes on stdio - hence the '''<''' to send ''my.diff'' file in. That can be useful to ''cherry pick'' any [[git]] commit. Just try:
<source lang="bash">
$ git show 88e601f | patch -p1
</source>
and the changes from ''88e601f'' commit will be applied just like you'd typed them manually. Simple way to extract changes from [[git]] history without [[git]] knowing anything about it - e.g. without changing the internals of the local [[git]] repository at all.

=== Embeddable Format ===

The above [[diff]] format can be easily embedded into an email and sent as a ''part of a message''. E.g. surrounding the [[patch]] with prose sections as completely OK. The [[patch]] command line tool will just ignore everything not having the appropriate '''diff''' header

=== Applying a PR from Another GitHub Repository ===

A neat trick is to feed [[patch]] directly from GitHub. Did you know each pull request URL can be appended with ''.diff'' or ''.patch'' and then one gets a plain text page in [[patch]] format? As such one can:

<source lang="bash">
$ curl -L https://github.com/enso-org/enso/pull/14666.diff | patch -p1
</source>

Get all changes in 14666 PR and pipe the output directly to [[patch]] utility. Don't forget to remove one directory from paths (as by default [[Git]]'s prepends '''a''' and '''b''' to differentiate between original and target file) by applying '''-p1'''.

== Conclusion ==

I have been adding (sometimes complicated) diffs as PR comments for many years and just recently I realized that I am not sure people know how to apply them! That's why I decided to write this down. I find the [[patch]] command line utility very useful. I wish its knowledge would spread. Let this little quiz help with that!

Aeron - 2025-10-03 06:46:37

Summary:


If there is one thing to do to improve performance of your application, it is [[APIDesign]] - [https://www.youtube.com/watch?v=GqU4PnWClTI&t=2572s hear 42:50 at GeeCON 2017 closing keynote].


{{#ev:youtube|GqU4PnWClTI}}


[[Category:Video]]

ExtensionMethods - 2025-09-10 06:04:26

Summary:


A way to extend [[RootClass]] (or any other class) with functionality without ''disturbing others''. Way better than [[DefaultMethods]]. Used in [[Kotlin]]. And also in [[Enso]].

The basic idea is to avoid extending [[RootClass]] ''physically'', but rather extend it ''virtually'' via a lexical compilation scope.

See [[wikipedia:Extension_method]] explanation which may agree or contradict my view.

RootClass - 2025-09-10 04:56:20

Summary:


[[OOP]] languages tend to have a [[RootClass]] - a super type of every object in the system. [[Java]] has {{JDK|java/lang|Object}}. [[Scala]] has '''Any'''. Etc.

[[Smalltalk]] systems come with a bunch of predefined classes which everyone can use and modify (in the form of serialized heap, btw.). Of course, the nature of [[OOP]] system is to be extensible. Thus one can create new subclasses (OK, that is the same as in [[Java]]), but one can also add new methods to existing classes. Lovers of meta-programming may be excited by that, but on and on, this is not a system that could work in a [[distributed development]] environment easily. Imagine:

The classical [[Smalltalk]] style to implement '''instanceof''' (e.g. to find out if an object is instance of a certain type) is based on a bunch of '''isSomething''' methods:

<source lang="smalltalk">
> 1 isNumber
true
> 'text' isNumber
false
> 'text' isString
true
</source>

What can developers do when they define new types like '''Person''' and want to recognize their instances? They add '''isPerson''' method to '''Object''' to return '''false''' and override it in '''Person''' class to return '''true''':

<source lang="smalltalk">
> Object subclass: #Person
> !Object methodsFor: 'Checking Person'! isPerson ^false !!
> !Person methodsFor: 'Checking Person'! isPerson ^true !!
</source>

One can then easily check on any object if it is a person or not:

<source lang="smalltalk">
> 1 isPerson
false
> Person new isPerson
true
</source>

As a result, if you want to understand a [[Smalltalk]] program/system, you should look at the added '''isSomething''' methods in the '''Object'''. Some might argue, that this is the way [[OOP]] should be done. On the other hand, such kind of programming creates not pure [[OOP|object oriented systems]], but different flavors (in the above case a ''person oriented system''), where capabilities of each object are driven by the variety of '''isSomething''' methods on its [[RootClass]].

I don't like that each [[Smalltalk]] system ends up being completely unique. Merging two such systems together may create a lot of accidental conflicts preventing merge of systems developed independently, as far as I can tell.

== Is [[Java]] an [[OOP]] system? ==

But enough about [[Smalltalk]] and let's look at [[Java]]'s root class {{JDK|java/lang|Object}}. Can you guess what kind of ''oriented system'' [[Java]] is?

[[Image:JavaLangObject.png]]

I think the answer is clear. [[Java]] is a '''hash oriented language''' and also '''lock oriented language'''!