Technical Debt – What it is and what to do about it

The following paragraphs in italic are taken from an article in IASA (International Association of Software Architects) written by Gene Hughson

In spite of all that’s been written on the subject of technical debt, it’s still a common occurrence to see it defined as simply “bad code”. Likewise, it’s still common to see the solution offered being “stop writing bad code”.  It’s not that simple.

What is Technical Debt?

A design or construction approach that’s expedient in the short term but that creates a technical context in which the same work will cost more to do later than it would cost to do now (including increased cost over time) .

Technical debt may not only incur costs due to rework of the original item, but also by making more difficult changes that are dependent on the original item.

Deferring bug fixes is a form of technical debt as is deferring automation of recurring support tasks.

Dependencies can be a source of technical debt, both in regard to debt they carry and in terms of their fitness to your purpose.

The platform that hosts your application is yet another potential source of technical debt if not maintained.

As noted above, the “interest” on technical debt can manifest as the need for rework and/or more effort in implementing changes over time. This increase in effort can come through the proliferation of code to compensate for the effects of unresolved debt or even just through increased time to comprehend the existing code base prior to attempting a change.

In short, technical debt is any technical deficit that involves a risk of greater cost to expand the application and/or end user dissatisfaction.

What to do about it?

Becoming aware of existing debt is a critical first step, but is insufficient in itself. Taking steps to actively manage the system’s debt portfolio is essential. The first step should be to stop unconsciously taking on new debt. Latent debt tends to fit into the immediate, unexpected payback model mentioned above. Likewise, steps taken to improve the quality up front (unit testing, code review, static analysis, process changes, etc.) should reduce the effort needed for detection and remediation. Architectural and design practices should also be examined. Too little design can be as counter-productive as too much.

Just as the taking on of new debt should be done in a rational manner, so should be the retirement of old debt.

Think of technical debt as credit card debt and you’ll realize why it is important to account for it, be aware of it and pay it off before funding any new features.

Domain Modeling, why it is replacing Data Modeling and bottom up designs

Complexity is the driving force for the adoption of the Domain Model pattern. Complexity should be measured in terms of the current requirements and what processes are modeled or automated by the application.

A domain model is a collection of plain old classes, each of which faithfully represents a significant entity in the business domain. These classes are data containers and can expose public properties, but they also are expected to expose methods. The term POCO (Plain Old CLR Object) is often used to refer to classes in a domain model. At some point, the classes in the domain model needs to be persisted. Persistence is not a responsibility of the domain model, and it will happen outside of the domain model through repimageositories connected to the infrastructure layer.

The conversion between the model and relational store is typically performed by ad hoc tools— specifically, Object/ Relational Mapper (O/ RM) tools, such as Microsoft’s Entity Framework or NHibernate. The unavoidable mismatch between the domain model and the relational model is the critical point of implementing a Domain Model pattern.

For decades (1980 to 1990s), relational data modeling was the most effective way to model the business layer of software applications. In the .NET space, the turning point came in the early 2000s, when more and more companies that still had their core business logic carved in the rough stone of mainframes took advantage of the Microsoft .NET Framework and Internet breakthroughs to renovate and modernize their systems. In only a few years, this poured an incredible amount of complexity on the shoulders of developers. RAD (Rapid Application Development) and relational modeling then— we’d say almost naturally— appeared worn out and their limits were exposed.

 

All the text above was taken from “Esposito, Dino; Saltarello, Andrea (2014-08-28). Microsoft .NET – Architecting Applications for the Enterprise (2nd Edition) (Developer Reference)” with permission from the authors.

Complexity is tackled best using classes that model the business with ubiquitous language. Language that is understood by the technical modelers (software architects/developers) and by the business counterparts or system matter experts. Domain Services encapsulate services that can be consumed by other applications or different GUIs. The focus now is in modeling the domain and modeling the behavior, rather than modeling the data (RDBM) model without events or behavior. The data model, as a starting point in the design, falls short without modeling the sequence of events (behavior) and the flow of information.

Should I use sessionID to uniquely identify users?

Should I use sessionID to uniquely identify users?
NO, that’s why UserId/UserName or LoginID and password combinations are for.
SessionID is a “random” string and can be repeated (e.g. when IIS is restarted or the server is rebooted, the sequencing scheme that generates SessionID values is reset). So if you store information for a user based on the SessionID value, be very aware that a new person next week might happen to get the same SessionID value–this will either violate a primary key constraint, or mix two or more people’s data.

However in ASP.NET, the SessionID is 120 bits in length, so like a GUID, is virtually guaranteed to never repeat.

But in classic ASP, this built-in mechanism is not a good strategy for identifying users over the long term. A better methodology would be to generate a key value in a database that is guaranteed to be unique (e.g. IDENTITY or AUTOINCREMENT) and store that in a cookie on the client. Then you can identify them not only for the life of their current session, but during future visits as well (of course, only until the next time they delete their cookies).

As usual, it depends, on the technology you inherit, how the old modules were built and so on.

Storing ASP.NET SessionId and at the same time storing a SessionGUID generated from the SessionId in ASP.NET doesn’t make much sense.

L.

Selling my book collection at Amazon…

I recently moved to a smaller place and can’t keep all my technical book collection.

I’m selling the books that I already read, no longer need or have duplicates. Some of them are for old .NET frameworks, but if you are maintaining legacy applications with these framework versions, the books from Microsoft Press can be helpful.

There are also books about SOA and SOAP, SQL Server specific books etc. The books are selling pretty fast.

You can access my seller’s collection at Amazon here.

All the prices are set for shipping within the USA only.

Happy coding!

The Eight Fallacies of Distributed Computing

Almost everyone, when they first start building a distributed application, make the following eight assumptions. All are proven to be false in the long run and cause trouble and painful learning experiences:

  1. The network is reliable
  2. Latency is zero
  3. Bandwidth is infinite
  4. The network is secure
  5. Topology doesn’t change
  6. There is one administrator
  7. Transport cost is zero
  8. The network is homogeneous

Keep the points above in mind when you design a distributed application. They are fallacies that increase the maintenance costs of your distributed application.

Closures in the Task Parallel Library, what are they? …beware of race conditions.

Up to .NET 3.5 multi-threading programming had it challenges. Multi-threading is a way to improve application performance and responsiveness by running long operations in a different thread from the main application thread.
Up to .NET 3.5 the parallel threads created by an application domain only targeted a single CPU core by CPU affinity. We also know that CPUs (Central Processing Units) couldn’t increase the processor clock without melting the integrated circuits away and requiring bigger cooling fans. So, the hardware evolved into placing several CPU cores in parallel to increase computing power.
The task parallel library introduced in .NET 4.0 responded to the need of catching up with the hardware capabilities and as a way to execute parallel operations in different cores.
Each task created by the TPL has its own stack and a thread or set of CPU threads.

When creating a task, a common code snipped to launch a task using a Lambda expression as an Action is:

1
2
3
4
5
6
Task.Factory.StartNew( () =>
   {
       statement1;
       statement2;
   }
);

However, very rarely a newly created task will receive no data from the method invoking it.
It is more likely to have the following code inside a C# method calling a parallel task:

1
2
3
4
5
6
7
8
9
...
int y=45;
 
Task.Factory.StartNew( () =>
    {
        y++;
    }
);
...

y is a variable that is passed to the parallel task for further processing.
Now, what would be the value of the variable y when the task finishes running?
Is y passed by value or by reference?

After the task completes the value of the primitive y is 46. y is indeed passed by reference. These variables passed to a task receive the name of closures.

Now, from multi-threading programming you might remember that objects that were shared between several threads could end up with a value that was not predictable, this was the dreaded race condition. There were ways to mitigate this condition such as using the lock statement to avoid concurrent threads affect the state of the object in an unpredictable way. Threads compete for CPU time and there is no guarantee that they will execute sequentially or in a predictable order.

You can also cause race conditions with closures in the task parallel library. Let’s see how:

1
2
3
4
5
6
7
8
9
10
...
int y=45;</code>
 
Task.Factory.StartNew( () =>
    {
       y++;
    }
);
...
Console.WriteLine(y);

In the example above, y won’t always be 46.

Once the task is kicked off, it is set in queue for processor time, and so is the main thread where the method that starts the task is.

They both compete in parallel for CPU cycles and run as parallel as possible. The executing code gets forked. If the main thread runs first while the parallel task is waiting in queue, the value of y will be displayed on the console as 45. If the task runs before the main thread makes it to the Console.WriteLine statement, the displayed value will be 46.
This is a typical race condition.

You have several ways to mitigate this condition in the TPL. One of them is shown below:

1
2
3
4
5
6
7
8
9
int y=45;
Task t = null;
    t = Task.Factory.StartNew( () =>
       {
                y++;
       }
);
Task.WaitAll(t);
Console.WriteLine(y);

The example above will always show 46 in the console.

Book Collection for a Junior Architect

Design pattern books:

1.       C# 3.0 Design Patterns

2.       Design Patterns: Elements of Reusable Object-Oriented Software:

3.       Patterns of Enterprise Application Architecture

This book is a must

4.       Microsoft .NET: Architecting Applications for the Enterprise (Pro-Developer)

5.       Microsoft Application Architecture Guide (Patterns & Practices) (This one can be downloaded for free as PDF from msdn)

6.       Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (This book is really good for specializing in middle tier aka services, queues etc)

7.       Core J2EE Patterns: Best Practices and Design Strategies (2nd Edition)

 

 

 

Domain Model Pattern (These books are dealing only with the DM pattern)

1. Applying Domain-Driven Design and Patterns: With Examples in C# and .NET

It has examples in C# 2.0 but the concept (DM) is still valid nowadays.

2.       Domain-Driven Design: Tackling Complexity in the Heart of Software

This is a classic although the book is a bit dense, see the examples. The book is narrated as a story when the author was developing an application for embedded electronic circuits.

 

Inversion of Control Pattern/IoC:

3.       Dependency Injection

Internet Architectures (Load balancing, redundancy, ways to scale out)

4. Scalable Internet Architectures

5. The Art of Scalability: Scalable Web Architecture, Processes, and Organizations for the Modern Enterprise

These two are “must have”references, specifically the UML one:

6.       UML Distilled: A Brief Guide to the Standard Object Modeling Language (3rd Edition)

7.       Refactoring: Improving the Design of Existing Code

And to translate from the Object Oriented World, Class Diagrams and UML notation to the Entity Relational World with Entity Relationship Diagrams:

8. Agile Database Techniques: Effective Strategies for the Agile Software Developer (Wiley Application Development)

9.       Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series (Fowler))

Thanks to Srinivasa Tammana for asking me to put this list together. I own other titles but they are more detailed to a particular database technology or programming language and the books here are long time favorites.

Cheers
Lizet

Determining the .NET target version of a dll or .exe assembly

It’s been a while since I blogged. It’s good to be back.

I switched job descriptions and became an application architect, which means, I get to decide how solutions are designed…and if the solutions won’t work, the blame goes on me :-p

Now seriously, I was reviewing old posts and realized WordPress didn’t make a good job at keeping my old code snippets from Blogger :(, the formatting is way off and you can hardly see the code properly. Oh well.

Today we had a deployment issue, one of our projects was compiled to the wrong target framework. When we compared properties and sizes we realized this was not the ordinary dll size, but how could we determine the actual target framework?

The windows explorer properties or the IIS properties are of no use in this case, giving you only the build number.

There are actually two main options with two utilities distributed on the SDK to determine the target framework of a dll or exe:

  1. ILDASM.exe
  2. CorFlags.exe
ILDASM.exe to determine framework version
ILDASM.exe to determine framework version

and if you want to use CorFlags.exe:

CorFlags.exe determining target framework version of a dll

Happy coding :)

L.