{"authors":[{"name":"Martin Stühmer","url":"https://daily-devops.net/authors/martin/"},{"name":"Jendrik Brack","url":"https://daily-devops.net/authors/jendrik/"}],"description":"Recent content in Tool and Code Extensions for Developers on Daily DevOps \u0026 .NET","favicon":"https://daily-devops.net/images/logo_hu_6465d873dfa490cf.png","feed_url":"https://daily-devops.net/tags/extensions/feed.json","home_page_url":"https://daily-devops.net/tags/extensions/","icon":"https://daily-devops.net/images/logo_hu_5926de77762241ba.png","items":[{"authors":[{"name":"Martin Stühmer","url":"https://daily-devops.net/authors/martin/"}],"content_html":"\u003cp\u003eMore than thirteen years ago, I was \u003cem\u003eforced\u003c/em\u003e by a project to switch from VB.NET to C# as my primary language. It wasn’t a change I had planned or wanted at the time. VB.NET had its quirks, but it also had a pragmatic and forgiving nature that made certain things feel\u0026hellip; effortless. Over the years, I grew to love C#: its precision, its tooling, its expressiveness. I never looked back.\u003c/p\u003e\n\u003cp\u003eWell – almost never.\u003c/p\u003e\n\u003cp\u003eThere was always one thing I missed. A tiny, elegant helper that VB.NET allowed me to write. A method that I’ve silently wished C# could express as cleanly:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-vb\" data-lang=\"vb\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"na\"\u003e\u0026lt;HideModuleName\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003ePublic\u003c/span\u003e \u003cspan class=\"k\"\u003eModule\u003c/span\u003e \u003cspan class=\"nn\"\u003eDisposableExtensions\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"c\"\u003e\u0026#39;\u0026#39;\u0026#39; \u0026lt;summary\u0026gt;Tries to release allocated resources.\u0026lt;/summary\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"na\"\u003e    \u0026lt;Extension, DebuggerStepThrough\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003ePublic\u003c/span\u003e \u003cspan class=\"k\"\u003eFunction\u003c/span\u003e \u003cspan class=\"nf\"\u003eTryDispose\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eOf\u003c/span\u003e \u003cspan class=\"n\"\u003eT\u003c/span\u003e \u003cspan class=\"ow\"\u003eAs\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"n\"\u003eClass\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eIDisposable\u003c/span\u003e\u003cspan class=\"p\"\u003e})(\u003c/span\u003e\u003cspan class=\"k\"\u003eByRef\u003c/span\u003e \u003cspan class=\"n\"\u003esource\u003c/span\u003e \u003cspan class=\"ow\"\u003eAs\u003c/span\u003e \u003cspan class=\"n\"\u003eT\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"ow\"\u003eAs\u003c/span\u003e \u003cspan class=\"kt\"\u003eBoolean\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eIf\u003c/span\u003e \u003cspan class=\"n\"\u003esource\u003c/span\u003e \u003cspan class=\"ow\"\u003eIs\u003c/span\u003e \u003cspan class=\"k\"\u003eNothing\u003c/span\u003e \u003cspan class=\"k\"\u003eThen\u003c/span\u003e \u003cspan class=\"k\"\u003eReturn\u003c/span\u003e \u003cspan class=\"k\"\u003eTrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eTry\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003esource\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eDispose\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003esource\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003eNothing\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003eReturn\u003c/span\u003e \u003cspan class=\"k\"\u003eTrue\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eCatch\u003c/span\u003e \u003cspan class=\"n\"\u003eex\u003c/span\u003e \u003cspan class=\"ow\"\u003eAs\u003c/span\u003e \u003cspan class=\"n\"\u003eException\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003eReturn\u003c/span\u003e \u003cspan class=\"k\"\u003eFalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eEnd\u003c/span\u003e \u003cspan class=\"k\"\u003eTry\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003eEnd\u003c/span\u003e \u003cspan class=\"k\"\u003eFunction\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eEnd\u003c/span\u003e \u003cspan class=\"k\"\u003eModule\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThis was a genuine life- and time-saver. It not only disposed of an object safely but also \u003cem\u003enulled out\u003c/em\u003e the reference afterwards. In VB.NET, this was possible because extension methods could take parameters \u003cem\u003e\u003ccode\u003eByRef\u003c/code\u003e\u003c/em\u003e – meaning the method could modify the original reference.\u003c/p\u003e\n\u003cp\u003eIn C#, for over a decade, this wasn’t possible. You could write an extension method to call \u003ccode\u003eDispose()\u003c/code\u003e, sure – but you couldn’t also set the caller’s variable to \u003ccode\u003enull\u003c/code\u003e. The language just didn’t allow it.\u003c/p\u003e\n\u003cp\u003eThat missing capability kept this one helper locked in the past, forever trapped in a VB.NET module.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"looking-ahead\"\u003e\u003ca href=\"/posts/still-waiting-for-the-final-piece/#looking-ahead\" title=\"Looking Ahead\"\u003eLooking Ahead\u003c/a\u003e\u003c/h2\u003e\n\n\n\n\n\u003ch3 id=\"net-10-and-c-14-extension-everything\"\u003e\u003ca href=\"/posts/still-waiting-for-the-final-piece/#net-10-and-c-14-extension-everything\" title=\".NET 10 and C# 14: Extension Everything\"\u003e.NET 10 and C# 14: Extension Everything\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eNow with \u003cstrong\u003e.NET 10\u003c/strong\u003e and \u003cstrong\u003eC# 14\u003c/strong\u003e, Microsoft introduces one of the most impactful additions to the language in years: \u003cstrong\u003eExtension Everything\u003c/strong\u003e.\u003c/p\u003e\n\u003cp\u003eThis feature expands what extensions can do. Instead of being limited to methods, extensions can now define \u003cem\u003eproperties\u003c/em\u003e, \u003cem\u003eoperators\u003c/em\u003e, and even participate in pattern matching. The new syntax is expressive, elegant, and feels like the logical next step for C#.\u003c/p\u003e\n\u003cp\u003eHere’s what a modern \u003ccode\u003eTryDispose\u003c/code\u003e might look like using the new \u003ccode\u003eextension\u0026lt;T\u0026gt;\u003c/code\u003e construct:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-csharp\" data-lang=\"csharp\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003enamespace\u003c/span\u003e \u003cspan class=\"nn\"\u003eSystem\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kd\"\u003estatic\u003c/span\u003e \u003cspan class=\"k\"\u003eclass\u003c/span\u003e \u003cspan class=\"nc\"\u003eIDisposableExtensions\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003eextension\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"n\"\u003eT\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;(\u003c/span\u003e\u003cspan class=\"n\"\u003eT\u003c/span\u003e \u003cspan class=\"n\"\u003edisposable\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"k\"\u003ewhere\u003c/span\u003e \u003cspan class=\"n\"\u003eT\u003c/span\u003e \u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eIDisposable\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"kd\"\u003epublic\u003c/span\u003e \u003cspan class=\"kt\"\u003ebool\u003c/span\u003e \u003cspan class=\"n\"\u003eTryDispose\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003edisposable\u003c/span\u003e \u003cspan class=\"k\"\u003eis\u003c/span\u003e \u003cspan class=\"kc\"\u003enull\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003etry\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                \u003cspan class=\"n\"\u003edisposable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eDispose\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                \u003cspan class=\"n\"\u003edisposable\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"k\"\u003edefault\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003ecatch\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                \u003cspan class=\"k\"\u003ereturn\u003c/span\u003e \u003cspan class=\"kc\"\u003efalse\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eClean. Expressive. \u003cstrong\u003eImagine this:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-csharp\" data-lang=\"csharp\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kt\"\u003evar\u003c/span\u003e \u003cspan class=\"n\"\u003estream\u003c/span\u003e \u003cspan class=\"p\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eFile\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eOpenRead\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003epath\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e// Lots of code...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e(!\u003c/span\u003e\u003cspan class=\"n\"\u003estream\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eTryDispose\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003elogger\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eWarn\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Could not release stream properly.\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIt reads perfectly. It’s elegant. And yet today, it’s still only half real. For now, the value won’t become \u003ccode\u003enull\u003c/code\u003e. The compiler still passes a copy. The concept is ready, but the implementation is not.\u003c/p\u003e\n\u003cp\u003eExactly what we’ve been waiting for.\u003c/p\u003e\n\u003cp\u003eExcept\u0026hellip; not quite.\u003c/p\u003e\n\u003cp\u003eWhile the syntax is here, the semantics aren’t – at least not yet. The extended instance (\u003ccode\u003edisposable\u003c/code\u003e) behaves as a copy of the reference, not a true alias to the caller’s variable. So even though the method compiles and runs, the original variable won’t be set to \u003ccode\u003enull\u003c/code\u003e afterwards. The dream of safely disposing and nulling in a single step remains just out of reach.\u003c/p\u003e\n\n\n\n\n\u003ch3 id=\"why-it-still-matters\"\u003e\u003ca href=\"/posts/still-waiting-for-the-final-piece/#why-it-still-matters\" title=\"Why It Still Matters\"\u003eWhy It Still Matters\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eThis syntax is more than just an aesthetic change—it represents an intentional step toward making the language more expressive and aligned with real-world usage. It points in the right direction, even if the final step hasn’t landed yet.\u003c/p\u003e\n\u003cp\u003eThe idea is simple: bring intent and safety together. Give developers the ability to describe what should happen to a resource without extra ceremony. Whether it’s cleanup, resetting, or transformation—such syntax makes intent explicit and code safer.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"closing-thoughts\"\u003e\u003ca href=\"/posts/still-waiting-for-the-final-piece/#closing-thoughts\" title=\"Closing Thoughts\"\u003eClosing Thoughts\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eThis evolution in syntax feels like the final stretch in a journey that began more than a decade ago. It’s tantalizingly close—a feature that captures the spirit of what VB.NET once made easy, expressed in the elegance of modern C#.\u003c/p\u003e\n\u003cp\u003eVB.NET was always about readability and pragmatism. C# built on that foundation with structure and precision. With \u003cem\u003eExtension Everything\u003c/em\u003e, the two worlds almost meet—but not entirely. Not yet.\u003c/p\u003e\n\u003cp\u003eFor me, that’s both exciting and frustrating. The language can now express the shape of what I’ve wanted for years, but the behavior still isn’t there. So, I’ll keep that old VB.NET module around a little longer — partly out of nostalgia, partly because C# is still a step behind its little brother in this very specific trick. Even though VB.NET no longer holds any real relevance in my work, it’s amusing to see that it still has this one ace up its sleeve.\u003c/p\u003e\n\u003cp\u003eBut we’re getting close. Very close. \u003cstrong\u003eStill waiting for the final piece.\u003c/strong\u003e\u003c/p\u003e\n","date_modified":"2026-05-26T10:22:03+02:00","date_published":"2025-10-06T09:00:00+02:00","id":"https://daily-devops.net/posts/still-waiting-for-the-final-piece/","language":"en","summary":"C# 14’s new 'Extension Everything' syntax comes close to VB.NET’s ByRef magic—but not quite. A witty look at what’s still missing in modern .NET.\n","tags":["csharp","dotnet","extensions","hidden-gems","vbnet","visualstudio"],"title":"Still Waiting for the Final Piece: C# 14 Comes Close","url":"https://daily-devops.net/posts/still-waiting-for-the-final-piece/"},{"authors":[{"name":"Martin Stühmer","url":"https://daily-devops.net/authors/martin/"}],"content_html":"\u003cp\u003eWhatever our role, be it developer, IT professional or architect, we try to avoid technical debt. If this is not possible from the outset, or if we decide to accept this technical debt for a limited period of time, we usually lack the tools to do so. This is where this article may help.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"what-is-technical-debt\"\u003e\u003ca href=\"/posts/illuminate-technical-debt/#what-is-technical-debt\" title=\"What is technical debt?\"\u003eWhat is technical debt?\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eTechnical debt is a metaphor used to describe the costs and risks incurred as a result of decisions or omissions. It is important to note that this metaphor can be applied to all types of technical debt.\u003c/p\u003e\n\u003cp\u003eFirst, there is \u003cstrong\u003earchitectural debt\u003c/strong\u003e, which is usually based on a decision made by an individual architect or group of architects. Then there is \u003cstrong\u003eimplementation debt\u003c/strong\u003e, which is probably the most common in most projects, as it is also identified through source code analysis. And then there is the \u003cstrong\u003etest\u003c/strong\u003e and \u003cstrong\u003edocumentation\u003c/strong\u003e debt, which is far too often neglected.\u003c/p\u003e\n\u003cp\u003e\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"responsive\"\u003e\n  \u003cpicture\u003e\n    \n      \n      \n    \n    \u003cimg\n      src=\"/images/what-colors-is-your-backlog-kruchten.svg?v=cbed4f593fdd5d7d97b708ff8f33da51\"\n      alt=\"What colors is your backlog?\"\n      loading=\"lazy\"\n      \n      decoding=\"async\"\n      width=\"1444\" height=\"1444\"\n      title=\"Phillipe Kruchten - https://pkruchten.files.wordpress.com/2012/07/kruchten-110707-what-colours-is-your-backlog-2up.pdf\"\n      copyright=\"Phillipe Kruchten - https://pkruchten.files.wordpress.com/2012/07/kruchten-110707-what-colours-is-your-backlog-2up.pdf\" /\u003e\n  \u003c/picture\u003e\n  \n  \u003cfooter\u003e\u003csmall\u003ePhillipe Kruchten - https://pkruchten.files.wordpress.com/2012/07/kruchten-110707-what-colours-is-your-backlog-2up.pdf\u003c/small\u003e\u003c/footer\u003e\n  \n  \n\u003c/figure\u003e\n\nWhatever the type of technical debt, the common denominator is that it tends to cause problems in projects and later in operations. In July 2011, Phillipe Kruchten described them as \u0026ldquo;invisible negative elements in the backlog\u0026rdquo;.\u003c/p\u003e\n\u003cp\u003eHowever, they are rarely recorded and visualized.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"how-can-i-still-make-them-visible\"\u003e\u003ca href=\"/posts/illuminate-technical-debt/#how-can-i-still-make-them-visible\" title=\"How can I still make them visible?\"\u003eHow can I still make them visible?\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eIn most projects, it is individuals or a small group of individuals who are aware of individual Technical Debts. However, these projects usually have another thing in common: when these technical debts are addressed, they are postponed or even dismissed.\u003c/p\u003e\n\u003cp\u003eTo avoid this, Technical Debts need to be tracked in the same way as requirements or defects. All you need is a person with administrative rights in Azure DevOps or comparable platforms.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"extension-of-the-azure-devops-process-templates\"\u003e\u003ca href=\"/posts/illuminate-technical-debt/#extension-of-the-azure-devops-process-templates\" title=\"Extension of the Azure DevOps process templates\"\u003eExtension of the Azure DevOps process templates\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eAzure DevOps provides the ability to visualize technical debt by extending process templates. The Microsoft article [Customize a process template] (\u003ca href=\"https://learn.microsoft.com/en-us/azure/devops/reference/process-templates/customize-process?view=azure-devops\" target=\"_blank\" rel=\"noopener external noreferrer\"\u003ehttps://learn.microsoft.com/en-us/azure/devops/reference/process-templates/customize-process?view=azure-devops\u003c/a\u003e) details how to inherit and extend a process template to achieve the following result.\u003c/p\u003e\n\u003cp\u003e\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"responsive\"\u003e\n  \u003cpicture\u003e\n    \n      \n        \n        \n\n        \n          \n        \n\n        \n\n        \n        \n\n        \n        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-544x111.webp?v=8d9af73128053bf12e79a9a910bdec83\"\n  type=\"image/webp\"\n  media=\" (max-width: 575.98px)\" /\u003e\n  \n  \n\n\n\n\n\n\n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-544x111.png?v=f138a1d35f81eb1c94e190694d99c3be\"\n  type=\"image/png\"\n  media=\" (max-width: 575.98px)\" /\u003e\n  \n  \n\n\n\n\n        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-672x137.webp?v=f77240208a267ede01ad7ba67d8111fa\"\n  type=\"image/webp\"\n  media=\" (max-width: 767.98px)\" /\u003e\n  \n  \n\n\n\n\n\n\n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-672x137.png?v=c62698be0bfc91fdaaa7dce809015f72\"\n  type=\"image/png\"\n  media=\" (max-width: 767.98px)\" /\u003e\n  \n  \n\n\n\n\n        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-896x182.webp?v=301a2d3e0dc3d923117bae4e1d24d94e\"\n  type=\"image/webp\"\n  media=\" (max-width: 991.98px)\" /\u003e\n  \n  \n\n\n\n\n\n\n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-896x182.png?v=c61cf536954ee7ebb57a90f5933cbc27\"\n  type=\"image/png\"\n  media=\" (max-width: 991.98px)\" /\u003e\n  \n  \n\n\n\n\n        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-1104x224.webp?v=ba7177e89e0191052e1f13719f93da32\"\n  type=\"image/webp\" /\u003e\n  \n  \n\n\n\n\n\n\n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-process-templates-1104x224.png?v=b6ef52b236efe2029b6041fe258dc5ee\"\n  type=\"image/png\" /\u003e\n  \n  \n\n\n\n\n        \n\n\n\n\n\n\n      \n      \n    \n    \u003cimg\n      src=\"/posts/illuminate-technical-debt/azure-devops-process-templates.png?v=07ef92b07b784fd85b4eb91ec33eddf1\"\n      alt=\"Azure DevOps Prozess Templates Erweiterung\"\n      loading=\"lazy\"\n      \n      decoding=\"async\"\n      width=\"1444\" height=\"1444\"\n      \n       /\u003e\n  \u003c/picture\u003e\n  \n  \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003eIn this case, the extended process templates AgileRCDA and ScrumRCDA were simply extended by an additional WorkItem type, which will be used in the future to record and visualize technical debt. In 2011, Kruchten already used the color black for the color scheme of technical debt.\n\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"responsive\"\u003e\n  \u003cpicture\u003e\n    \n      \n        \n        \n\n        \n          \n        \n\n        \n\n        \n        \n\n        \n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n      \n      \n    \n    \u003cimg\n      src=\"/posts/illuminate-technical-debt/azure-devops-workitem-technical-debt.png?v=cf328b57fb1eb531943745c3671c492f\"\n      alt=\"WorkItem Type: Technical Debt\"\n      loading=\"lazy\"\n      \n      decoding=\"async\"\n      width=\"1444\" height=\"1444\"\n      \n       /\u003e\n  \u003c/picture\u003e\n  \n  \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003eFor later prioritization and sorting, it is advisable to pass additional parameters to the WorkItem type, such as\n\n\n\n\n\n\n\n\n\n\n  \n  \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cfigure class=\"responsive\"\u003e\n  \u003cpicture\u003e\n    \n      \n        \n        \n\n        \n          \n        \n\n        \n\n        \n        \n\n        \n        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n  \n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-workitem-technical-debt-settings-544x145.webp?v=fab732c602641b73883dce8c1b304a4c\"\n  type=\"image/webp\" /\u003e\n  \n  \n\n\n\n\n\n\n  \n  \n\u003csource\n  srcset=\"/posts/illuminate-technical-debt/azure-devops-workitem-technical-debt-settings-544x145.png?v=ed5e00c199145fa56e8ffeeb123a1865\"\n  type=\"image/png\" /\u003e\n  \n  \n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n        \n\n\n\n\n\n\n      \n      \n    \n    \u003cimg\n      src=\"/posts/illuminate-technical-debt/azure-devops-workitem-technical-debt-settings.png?v=7e567c600ecc2d9fe97aa179a4779f95\"\n      alt=\"WorkItem-Typ: Technical Debt - Settings\"\n      loading=\"lazy\"\n      \n      decoding=\"async\"\n      width=\"1444\" height=\"1444\"\n      \n       /\u003e\n  \u003c/picture\u003e\n  \n  \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003eThis creates the technical foundation based on the process templates, and within the project only the technical debt type work items need to be recorded.\u003c/p\u003e\n\n\n\n\n\u003ch2 id=\"summary\"\u003e\u003ca href=\"/posts/illuminate-technical-debt/#summary\" title=\"Summary\"\u003eSummary\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eThe Azure DevOps extension (or alternative platforms) presented here takes only a few minutes to extend and deploy. But it will have the desired effect by the next sprint meeting. That\u0026rsquo;s because the black work items of the \u0026ldquo;technical debt\u0026rdquo; type quickly give the impression of a tombstone and provide the necessary visibility.\u003c/p\u003e\n\u003cp\u003eDon\u0026rsquo;t be surprised if the tombstones start to pile up after a few weeks. Your colleagues and team members know about other Technical Debts that you probably haven\u0026rsquo;t noticed yet.\u003c/p\u003e","date_modified":"2026-05-25T22:16:53+02:00","date_published":"2023-04-12T17:00:00+02:00","id":"https://daily-devops.net/posts/illuminate-technical-debt/","language":"en","summary":"Learn how to make technical debt visible, measurable, and manageable using platforms like Azure DevOps with practical tools, metrics, and strategies.","tags":["azuredevops","extensions","rcda","technicaldebt"],"title":"Illuminate Technical Debt with .NET Analyzers \u0026 Metrics","url":"https://daily-devops.net/posts/illuminate-technical-debt/"}],"language":"en","title":"Tool and Code Extensions for Developers on Daily DevOps \u0026 .NET","version":"https://jsonfeed.org/version/1.1"}