Introduction

CAP stands for Consistency, Availability and Partition tolerance. The CAP theorem first appeared in autumn 1998 and published as the CAP principle in 1999 also named Brewer’s theorem after computer scientist Eric Brewer states that it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:

  • Consistency: Every read receives the most recent write or an error
  • Availability: Every request receives a (non-error) response, without the guarantee that it contains the most recent write
  • Partition tolerance: The system continues to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes

Fallacies of Distributed Systems

The distributed systems are heavily dependent on various moving parts connected over a network and heavily rely on partitioning to achieve the scalability, and be informed that network failure is inevitable http://www.mypassionfor.net/2020/03/11/8-fallacies-of-distributed-computing/

 Image Credit – Denise Yu Twitter: https://lnkd.in/eJYnpC

Can a system have all CAP?

The only exception which can practically demonstrate all CAP would be a single node system, which can’t be regarded as a distributed system. Moreover, it can’t scale to the level of what a distributed system is capable of and designed with a goal in mind. 

Note: Single node can utilize only Scale-Up or Vertical-Scaling strategy. Any system which is using Scale-Out or Horizontal-Scaling has to abide by the CAP theorem.

Explanation

No distributed system is safe from network failures, thus network partitioning has to be tolerated. In the presence of a partition, one is then left with two options: consistency or availability. When choosing consistency over availability, the system will return an error or a time out if particular information cannot be guaranteed to be up to date due to network partitioning.

When choosing availability over consistency, the system will always process the query and try to return the most recent available version of the information, even if it cannot guarantee it is up to date due to network partitioning (which is better in many cases for user experience). When a network connection is established, consistency will be achieved again across nodes/partitions i.e. eventually consistent.

Database systems designed with traditional ACID guarantees in mind such as RDBMS choose consistency over availability, whereas systems designed around the BASE philosophy, common in the NoSQL databases, for example, choose availability over consistency.

CAP in Practice

Let’s say you are designing a distributed system that has a cluster of 4 data nodes. Replication factor is 2 i.e. any data written in the cluster must be written on 2 nodes; so when one goes down – second can serve the data.

https://www.linuxtopia.org/

Now try to apply CAP theorem on this requirement. Remember, in a distributed system, two things may happen anytime i.e. node failure (hard disk crash, EC2/VM failure) or network failure (the connection between two nodes go down) [Fallacy of distributed computing].

CP [Consistency/Partition Tolerance] Systems

Distributed systems ensure data consistency at the time of reading the data, by a voting mechanism, where all nodes who have a copy of data mutually agree that they have “same copy” of requested data. Now let’s assume that requested data is present in two nodes A-1 and A-2. The client tries to read the data; and our CP system is partition tolerant as well, so an expected network failure occurred and A-1 is detected as down. Now the system cannot determine that A-2’s data copy is the latest or not; it may be stale as well. So the system decides to send an error to the client.

Here system chose to prefer data consistency over data availability. Similarly, at the time of writing the data if the replication factor is 2, then the system may reject write requests until it finds two healthy nodes to write data fully in consistent manner. Hence, now the system is considered not “Available” i.e CAP’s “A” is sacrificed.

CP system is harder and expensive to implement.

AP [Availability/Partition Tolerance] Systems

In today’s customer-obsessed mindset, a system is expected to up-and-running 24×7 hence, you have to put proper thinking in place and make informed decisions while choosing trade-offs. As with CP, the system is known not to be “Available” in the event of a failure.

A resilient system design would rather consider instead of sending ERROR (in case A-1 is down); it sends the data received from A-2. Chances are that the data client will get may not be the latest data (hard to decide). Hence, now the system is considered “Available” i.e CAP’s “C” is sacrificed.

CA [Consistency/Availability] Systems, Really?

In a distributed environment, we cannot avoid “P” of CAP. So we have to choose between CP or AP systems. If we desire to have a consistent and available system, then we must forget about partition tolerance and it’s possible only in non-distributed systems such as an RDBMS system.

No alt text provided for this image

Closing Note

CAP is frequently misunderstood as if one has to choose to abandon one of the three guarantees at all times. In fact, the choice is really between consistency and availability only when a network partition or failure happens; at all other times, no trade-off has to be made.

CAP is to choose your tradeoff in the event of a failure (network/node). In the absence of network failure – that is, when the distributed system is running normally – both availability and consistency can be satisfied.

In today’s world, we can achieve all 3 in a distributed system (if not fully, then partially at least). E.g. Tunable consistency in Cassandra

Seattle Code Camp 2017

I spoke at Seattle Code Camp 2017 on 09/09/2017 and covered two topics.

• AntiPatterns Every Software Development Team Must Know https://lnkd.in/ebEMDBb
• DevOps: What, why and how?
https://lnkd.in/eQf3dFm

Seattle Code Camp started with a Keynote from Microsoft’s Jeremy Foster and he shared a slide with all Microsoft MVP (Most Valuable Professionals) and FTE (Full Time Employee) who were speaking at 09/09/2017 Seattle Code Camp.

Microsoft got separate printed agenda for MVP and FTE Sessions

Session Details

My 1st Session on AntiPattern was in Room#103 at 11 am -12 pm. I had a brief introduction and begin with the presentation. As already set the expectation with the audience, I kept it very interactive and many participated well to share knowledge and experiences with others.

Some of the attendees even spoke to their friends in the lunch break and recommended them to attend my next session. Some of the attendees returned for the 2nd session for DevOps at 1-2pm and some mentioned that it was the best talk they attended. Well, I thank them for their kind words and patience to provide me an opportunity to share my thoughts with them.

What people said after my sessions

Presentation Slides

Slides are available at https://github.com/vidyavrat/SeattleCodeCamp2017

Contact Me

Please connect with my via
LinkedIn : https://www.linkedin.com/in/vidyavrat/
Twiter : https://twitter.com/dotnetauthor

Send me a message using Contact Me tab on the blog.

How to use Agile correctly?

September 27th, 2016 | Posted by Vidya Vrat in Agile-Scrum | Best Practices - (0 Comments)

Abstract

This article uncovers the various aspects of Agile software development technique and Scrum framework to enable an Agile team/ team member to understand various issues any software development team sails through and how to come over those challenges.

Where Did Agile Come from?

In 1970, Dr. Winston Royce presented a paper entitled “Managing the Development of Large Software Systems” which criticized sequential development.

He asserted that software should not be developed like an automobile on an assembly line, in which each piece is added in sequential phases. In such sequential phases, every phase of the project must be completed before the next phase can begin. Dr. Royce recommended against the phase based approach in which developers first gather all of a project’s requirements, then complete all of its architecture and design, then write all of the code, and so on. Royce specifically objected to this approach due to the lack of communication between the specialized groups that complete each phase of work.

Developing a Solution for Customer

Any software project starts from Gathering Requirements phase and many times what is developed is not exactly what end user wanted, and many software projects fail during implementation.

Value Delivery Impediments

In today’s world teams have huge dependencies on various stakeholders of the project including Users <-> Developers <-> QA <->Operations etc. and it’s proven that we need regular communication and collaboration to deliver the value.

Any communication gap or lack of collaboration between these team(s) or individuals will have impact in following areas

Plan Driven Vs Value Driven Approach 

Old school of software development has taught “waterfall” approach of software development.  In waterfall approach, one phase’s output becomes input to next phase and those phases are distributed across the project timeline as shown in the image below.

Today’s software development technique is “Iterative“ and “Incremental” I.e. Agile. In Agile, team run through all the phases within a Sprint as briefly shown in the image below.

In waterfall, development teams only have one chance to get each aspect of a project right. Whereas in Agile team has better understanding and learning from previous Sprint on what to emphasize upon and what to avoid to reap better results.

Why Agile

  • Agile development methodology provides opportunities to assess the direction of a project throughout the development lifecycle.
  • This is achieved through regular cadences of work, known as sprints or iterations.
  • At the end of which teams must present a potentially shippable product increment. The results of this “inspect-and-adapt” approach to development greatly reduce both development costs and time to market.

Agile Manifesto

Perfect Agile Team, does it really exist?

Success of any project depends on Team. I.e. it’s critical to have an awesome team to have rocking results. But in reality this doesn’t happen as team consists of individuals with their own attitude, aptitude, work style, ethics, behavior and issues etc.

Bruce Tuckman’s team development model is a perfect example how team can come together and start functioning.

Agile team’s Success heavily depends upon “self-Organized” team.

Scrum Process

Sprint Length and Team Size

Sprint is to Run at full speed over a short distance. Ideal Sprint length is 2 weeks. My recommendation is as following and I have experienced that it really works well.

  • Ideal Agile teams must be 7 to 9 +/-2 members.
  • If you have more candidates in a team, then divide teams and have separate agile teams.
  • A representative of each team might want to attend other team’s standup for critical issues, follow-up and announcements etc.

Most wanted thing in Agile – Velocity

Velocity is the account of work team completes and delivers in each sprint. Ideal sprint duration is 2 weeks and highly recommend this to any team.

I have seen better results when team works towards a pre-defined code complete date for instance, today is Tuesday and sprint is for two weeks, team can agree upon a code complete date of Wednesday of 2nd week. I.e. team will try to complete all the work by that day and have it ready for QA.

This just gives a deadline to accomplish the work, however there will be situations where work couldn’t get complete or even rolled over to next sprint and that is fine in some cases.

Here are some of my recommendations:

Give as much time as possible to Developers, SDETs and QA to fulfill their commitment. I.e. less meetings and hindrance.

Have at-least 2-3 sprints worth work well-groomed and available for the team as “ready for development”.  Two reasons:

1 – At times for unforeseen reasons or instances a user story may be pulled out of current sprint. In such situations you lose story points you committed to. In such scenarios other US can be delivered.

2- Sometimes team or an individual is able to complete the work early and available to pick more work, in such situation well-groomed loaded backlog can come very handy.

Groom Often (Backlog Grooming)

  • Usually Sprint 0 is dedicated for backlog grooming and then team start to deliver in Sprint 1 and onward.
  • Considering any Enterprise Line of Business (LOB) application, sprint 0 can’t suffice the entire backlog groomed at once.
  • Hence, team must regularly have backlog grooming in small chunks of time instead of lengthy full day meetings.

Ideally, grooming is a lengthy process and hence groom in short chunks and team lead can be present in the regular or small grooming sessions with PO or business and team can continue to focus on their work. However, team must be present at Sprint Planning time.

Brainstorm Together (Sprint Planning)

  • Everyone is invited. Many teams ask only Dev’s to attend and excuse the QA team members.
  • Understand the problem 1st.
  • Ask Questions and clarifications.
  • “Well defined” Acceptance criteria is a must.
  • Confirm that User Story is ready for development.
  • Nothing should fall from the cracks, document all within the User Story.

Daily Status Check

Just three things, no more; no less

  1.  What have you done since yesterday?
  2.  What are you planning to do today?
  3.  Do you have any blockers preventing you from accomplishing your goal?

I recommend, that if you have to discuss something related to a User Story or bug or some reported a status on something etc. then “Post Scrum” that. I.e. discuss that when team has given the status and now you can drill into the detailed discussion.

Many times Dev’s start going into technical details of the issue, design of solution, architecture, code review comment details etc. during their status. This is not right way of doing it. Just Post Scrum all that; if you have to discuss anything other than those three absolute must.

I am Blocked

It’s is obvious that someone at some time is blocked on something. You can help, by asking just:

  • Really
  • On what
  • What is the issue
  • Who is POC (Point of Contact)
  • What is ETA (Estimated Time of Arrival) I.e. delivering solution to you.

I will give you a scenario, let’s say I join a team which works on some third part control library and my license of that product is pending or not yet processed. Am I blocked. Well in a way; yes, but I can use trial version up to 30 days and when my license information come I can punch those.

Also, many times we just tell other team that we are blocked on something and we are expecting the endpoint or JSON format etc. but we don’t always ask what is ETA and convey the timelines we have to adhere. If this has any impact on your team’s deliverable than you need to re-prioritize, escalate etc. so either that work is delivered to you on time or that user story is pushed to next sprint and you pick next item on Stack rank (priority) from the Product backlog.

Scrum Master must help you to get unblocked.

Is there time to Think?

Many people and teams think that Agile has no time for following:

  • Researching a solution
  • Brain storming on the solution architecture.
  • Share your thought process, design, approach with the architects, PO etc. to get the insight.

Well, there is and it’s called “Spike”. In agile software development, a “Spike” is a user story that cannot be estimated until a development team runs a time boxed investigation. The output of a spike story is an estimate for the original story.

Some examples of spikes:

1- Discussing authentication mechanism and partner team’s flexibility to apply / accept those changes.

2- Discovering or researching for an off the shelf solution work flow solution.

Technical Debt

Every team has it, generated it, accumulate it; not a problem. Just make sure you pay it off.

Technical debt is a terms which is used for the work which team or an individual didn’t prioritize upon while pushing the deliverable, and require improvements.

  • First and foremost, poor coding style and standards.
  • No unit test cases.
  • Not following OO design principles and developing long monolithic classes and code libraries.
  • Not envisioning on proper candidate technology, architecture or approach and then hitting a wall. I.e. when application is little bit mature you start to feel the hit on User experience, performance, scalability, code maintenance etc.
  • Code files has a lot of comments. I.e. code is completely documented. Many developers write few lines of comment for each line of code.
  • Code is not self-documented.
  • Magic strings (hard coded path and endpoints etc. in the code)
  • Dead code in project. You must have seen or left some commented code in various code files. This is dead code and needs to be cleaned up.

Read my detailed article on Technical Debt

Branching and Merging

Branching enables parallel development and delivery by providing each development activity a self-contained snapshot of needed sources, tools, external dependencies and process automation.

Continuous check-ins pollute the branch.  Have a separate Release branch per Release.

Basic Dual Branch is an Ideal branch plan, have a Main, spin a Dev branch for development and have RI (Reverse Integration) and FI (Forward Integration) to merge changes between Child and Parent branch respectively.

When you are ready to deliver the shippable product at sprint completion then spin a Release Branch and deliver the product out of that.

Feature Branch Plan is slightly complex and requires more merge efforts but at the same time it give entire isolation of work being done in a feature branch for entire time; until it’s ready for merge to Dev branch. One major issue with this plan is that your feature branch will have old and stale code and when you will Get Latest / Pull from the changes then you will get some conflicts etc.

Just saying

“Save your creativity for your product… not the branch plan.”

“Your branch distance from main is equal to your level of insanity”

Unit Testing

Many teams don’t invest in Unit Testing. For any Agile Team Unit Test is the most critical thing and team must continue to increase the code coverage of the tests. Even based on Test Triangle as shown in the image below, Unit Test has the larger scope in Software Testing.

Read my detailed article on NUnit with Visual Studio

Read my article on Visual Studio and .NET’s Unit Test Framework

Read my article on Inside Out: TDD using C#

Benefits of Unit Testing

  1. Unit Testing gives an opportunity to think as User of your code, instead of an implementer of the production code.
  2. Reduce bugs by identifying all the use case scenarios to reflect intent (end user’s mindset, business needs, expected functionality and business validations etc.)
  1. Less-n-less time on debugging.
  2. Avoid collateral damage. I.e. a fix in one area may break functionality in another possibly
    related/unrelated area.
  3. Helps you achieve YAGNI– You Aren’t Gonna Need It. I.e. saves you from writing code which you
    don’t need

Tips for System Test

  • Must know how much to test, drive your Test cases from Acceptance criteria.
  • Avoid duplicate test steps.
  • Make sure that all your Test Cases are Mapped to Acceptance Criteria.
  • Try to combine similar behaviors in a single test case.
  • Do not go above and beyond to identify every corner case or hack the system. I.e. above a beyond the acceptance criteria. I know this is tricky and someone may want to debate on it. I didn’t mean to say that don’t test any areas of application which might have direct impact of a User Story or what not. But there is always a fine line on what to test and what not.
  • Time box for ad-hoc testing. I.e. in each sprint time-box some time

Continuous Integration (CI)

  • An important part of any software development process is getting reliable builds of the software. – Martin Fowler
  • Continuous Integration (CI) is the strategy and practice of making sure that changes to a software project’s code base are successfully built, tested, reported on, and rapidly made available to all parties after they are introduced.

Advantages of CI

  • Increase ROI (Return on Investment).
  • Guarantees successfully compiled software.
  • Visible progress reporting and problem tracking.
  • Low TCO (Total Cost of Ownership).
  • Improve development standards, consistencies and accountability.
  • Rapidly identify bugs, who created them, and where it is.
  • Quickly push high quality change updates to testing.
  • Reduce development integration effort.
  • Increase amount of quality code.

Successful Build

An aggressive goal for a successful build would include:

  • All the latest sources are checked out of the configuration management system.
  • Every file is compiled from scratch.
  • The resulting object files are linked and deployed for execution.
  • The system is started and a suite of tests is run against the system.
  • If all of the above execute without error or human intervention and every test passes, that is a successful build.

Let the Team see what is happening

  • Must have Gated builds and nightly builds to ensure value delivery of the functionality.

You can use this build monitoring tool from https://teambuildscreen.codeplex.com/

Continuous Delivery (CD)

CI mainly focuses on development teams. The output of the CI system normally forms the input to the manual testing process and to the rest of the release process.

You’re doing continuous delivery when:

  • Your software is deployable throughout its lifecycle
  • Your team prioritizes keeping the software deployable over working on new features
  • You can perform push-button deployments of any version of the software to any environment on demand

 

 

Introduction

Technical Debt is a term that is commonly used in agile-scrum team process. Technical debt is used for the work which team or an individual didn’t prioritize upon while pushing the deliverable, and  either left some unwanted code in various project artifacts, such as – .cs, .config, .cshtml, .js, .sql etc. or didn’t use the right technique to accomplish the goal. But in real world software development process this is expected and totally fine as long as team takes the responsibility to pay off the Technical Debt.

How is Technical Debt created?

Technical Debt is like financial $$ debt; if you don’t pay off previously owned $ amount but keep borrowing more than you are getting into messier situation. I assume you are not the one who like debt that much; whether it is technical or financial. Anyways, just to be aware; if you don’t take good care of the following items then you are potentially seeding “Technical Debt” situation in general, later on which needs to be paid off.

  • First and foremost poor coding style and standards.
  • No unit test cases.
  • Not following OO design principles.
  • Developing long monolithic classes and code libraries.
  • Not envisioning on proper candidate technology, architecture or approach and then hitting a wall. I.e. when application is little bit mature you start to feel the hit on User experience, performance, scalability, code maintenance etc.
  • Over engineered application. I.e. things which can be done in simpler way are done using very complicated mechanism. For instance, to do encryption data, custom code is written or taken from internet which causes a lot of security holes and performance hits.
  • Code files has a lot of comments. I.e. code is completely documented. Many developers write few lines of comment for each line of code.
  • Code is not self-documented. I.e. Classes, functions, variables etc. are given improper names. For example, a function is named Salary instead of EmployeeSalary or a variable is called double sal instead of double employeeSalary.
  • Shortcut approach is taken to push the functionality to meet the code complete deadlines. Such events trigger further refactoring to be performed later. For instance, created one thick bulky Model class with a lot of classes within. Or hard coded various paths and endpoints into the .cs code rather than putting those into a web.config and reading web.config Key in the code for the related value (key-value pair).
  • Dead code in project. You must have seen or left some commented code in various code files. This is dead code and needs to be cleaned up.

Based on above mentioned points, now you will be able to understand that why Technical Debt is also known as Code Debt or Design Debt. In addition, anything in your software development work; which slows you down or looks odd, or can be improved is a “Technical Debt”.

How to handle Technical Debt

First step is, not to cause any technical debt from your end; if at all possible. However, in agile development it’s common to have some technical debt accumulated over the period of time, if so then move to second step. Second step is to report any technical debt which you have either caused or came across.

Please don’t get into blame game or point finger to any individual. Let’s say you come across some code blocks in a file you are working on and then you see some dead code. Rather than start cleaning it up, I recommend create a Technical Debt item and let the team decide.

How to Report Technical Debt

Technical debt items are usually reported as Issues or as a “New Product Backlog Item”. Also, Technical debt items are supposed to be logged in a separate backlog. I.e. don’t report those to Production or sprint backlog. In many teams and as per my experience with agile-scrum I have always worked on a separate dedicated “TechnicalDebt backlog”

Having a separate TechnicalDebt Backlog allows the team to stay focused on Sprint backlog and don’t interfere with business requirements which are logged in the Product Backlog.

Creating Technical Debt backlog

Creation of backlog and modifying process templates etc. are usually done by an admin on your team project. In an agile team setting this duty is usually performed by the scrum master.

If your team doesn’t already have a Technical Debt backlog, then it’s time create one.

  1. Go to VSTS (Visual Studio Team Services) Team Project’s Web Portal and in control panel under work, click on Areas.
  2. Under the “Areas” click on “New child”
  3. Name it as “TechnicalDebt_<YourTeamProjectName>”. TechnicalDebt prefix helps you differentiate it with other areas and makes it self-explanatory.

     4.It will now appear under your Team Project as an area.

Let’s see it from Developer’s angle

Developers usually interact via Team Explorer from within Visual Studio IDE.

Select Work Items and then click on “New Work Item” and based on your team process template; usually either Agile or Scrum, you can select Product Backlog Item or Impediment or Issue as item type to report the Technical debt.

Filling in the details

Usually, any item in any backlog needs to have ample information to describe what the issue is. In the below example, it is briefly pointed out that some classes need code cleanup. Some questions might still be unanswered and those will be discussed during backlog grooming and sprint planning.

When to work on Technical Debt

Just like Product and Sprint backlogs, Technical Debt backlog also needs to be groomed I.e. each “Technical Debt” item needs to be reviewed and groomed by the team to identify its validity, impact on overall team’s development experience and software quality team is producing. Once, team is in agreement to pay off a technical debt item or items then those items are transferred to Sprint Backlog and many times a new User Story is created for each technical debt.

Many Agile experts say that a team must not carry Technical Debt beyond a sprint, just like you should not carry Credit Card balances over to next pay period. I.e. pay off full Credit Card debt in the same billing cycle. But, it’s not always possible, so it doesn’t happen in software world for Technical Debt as well.

Summary

I personally recommend that as a developer you should not cause any technical debt due to the code you have written or currently writing. Be honest, about any improvements your code might need and explicitly call out what changes can be made to make it better. Avoid any over engineering or unwanted design patterns and technology implementations to be called out as Technical Debt. If you are not sure whether a particular code / technique is Technical Debt or not, call out a short brain storming session. In today’s software development industry it’s not easy to avoid technical debt, we all live with it, but be aware that you have to get rid of technical debt to achieve complete Technical Freedom.

Abstract

This article provides a broad overview of review process for the code written in C# using Visual Studio 2015 and also uncovers best practices for code review. Code Review is a very important part of any developer’s life. Code review is a technique which allows another developer (not necessarily working in same team or same feature within a team) to go over-n-through your code line-by-line and identify areas for improvement or point out holes.  Hence, code review is a process and not a technology. However, there are some tools available (covered later in this article) which can enable a developer to write good quality code.

Disclaimer

There are numerous guidelines and best practices software development teams follow and depend on. This article will uncover most of those but it may not cover all the best practices around code review. However, I want to assure you that all the guidelines mentioned below will help any individual to practice and apply good coding principles and perform a quality code review.

Is it must to have my code, reviewed by other dev?

Well, you must. But it depends on your team’s development methodology and ALM (Application Lifecycle Management) tool settings. There are ways to by-pass the code review by simply just not doing it and straight checking-in the code. It’s not recommended though.

What if my code is not reviewed?

It’s hard to say, but at times and in some cases it might cause serious issues and raise concern for the whole team. For instance, a condition check is missed, or null is not handled properly or not all error situations are being handled by your exception handling block. Well, these examples might sound very simple and most of the developers do write defensive code and cover such aspects. But what code review can also provide value towards is your “design”, “techniques”, “patterns”, “approach” etc.

How to find a code reviewer

I have worked in various team settings and work environments. Many times I have been invited to perform a code review for a developer who is not part of my team or rather I am not part of their team. But what I admire and appreciate here is the fact; that someone reached out to another dev in case of their team’s developer is either not available or busy with critical production issue etc. Such mindset empowers the team to deliver the best written code.

Let’s Begin with Best Practices of code Review

Here, I am going to list out some areas which are critical from code review perspective. I tried to highlight the core best practices which are must in any code review. I have seen many times that in a code review developers are more focused to look for code design patterns or some areas in code review and then try to convince

1- Project and File names

Many times developer’s only focus on code, but in my view your Project name, file name etc. also matters a lot. It’s not sufficient to deliver well written functional code; a well-defined project and file name is equally important and brings a lot of clarity by offering a sense of purpose being served by solution, project or a file. For instance see the solution and project name in as shown in the image below.


Figure-1: Properly named Solution and Project

2- Always begin from the top

Before you really start scanning through the code blocks/statements in a class (.cs) file; I would recommend that you must 1st look at the “using” statements in any .cs file. I have personally observed that many times developers add numerous “using” statements while trying various code blocks to achieve the functionality. But once that functionality is accomplished; many developers tend to forget about cleaning up references of those “using” statements which are no longer needed now and must be removed. Visual Studio 2015 show unused using statements in grey color which can be safely removed as shown in the image below.

Figure-2: Un-used using statements are grayed out by default in Visual Studio 2015

3-  Sort all the using statements

Usual development practice is that we keep adding new using statements at the end of previous ones, for instance as shown in the image below.

Figure-3: Newly added using statements

Let’s assume that code is consuming all of the added using statements, but the issue is that these are not sorted. One of the coding best practices is to Sort all using statements. To sort using statements right-click in code editor windows and click on “Organize Usings” then click on “Sort Usings”.

Figure-4  Sort Usings option in Visual Studio 2015

After performing the “Sort Usings” all the using statements will be alphabetically sorted (this is the only order A – Z) and will be arranged as shown in the image below.

Figure-5 Alphabetically Sorted Using statement

4- Don’t just ignore warnings

As a developer we are more focused on compilation errors and want to see that project/solution build successfully. For instance, consider the code as shown in the image below.

Figure-6 sample code

This is a very simple code and project will build successfully without any compilation errors. However, as you can see that “j” is used nowhere in the code and so this will cause a warning; which many developers doesn’t seem to care about. In my view and as many software companies including many Microsoft teams I have worked with enforce 0 warnings policy before check-in. Hence, it is very important to look in detail at the “Error List” View menu à Error List, and then observe Warning Tab and must try to have that also show “0 Warning” just like we always work to only see “0 Errors”.

Figure-7 Error List, highlighting warning in the code

5-  Code Consistency

One very important quality of well written code is “Consistency”. I.e. stick to one style. Let’s say that you want to declare an integer variable and it’s obvious that different teams and developers will have different coding guidelines. Many times developers ignore this and code has scattered instances of types/keywords Int32 or int and String or string, this demonstrates that code consistency is violated. However, using mixed statements will successfully compile the code but makes your code base completely in-consistent. 


Figure-8 Code consistency violation

6-  Do care for Null all the times

Null has catastrophic impact on your code functionality. Simply a null check ignored and you will face the consequences. This is why many developer productivity tools like Re-Sharper prompt for any potential “NullReferenceException” which can be triggered from your code. Make sure that all your if/else do take enough care of null and have guard(s) in place, most of the times IsNullOrEmpty or IsNullOrWhiteSpace will come really handy.

7-  Dead code

Many times I have seen that as a developer we are mostly interested in our own code; to be specific, code we are writing. At times we do observe a block of code which is commented for long, but we don’t seem to care, but why not?  Well, in my view there are two reasons for this. First, I don’t care as long as my code works. Second, I am working in an agile team and I am committed to finish my task in committed timelines. First one is an attitude problem, second is timeline and hours remaining to complete the work. But both can do one thing for sure. Open an item in Technical Debt backlog with details to have that file cleaned up.

8-  Naming Convention

All developers today are well aware of Camel and Pascal casing and when to use one over the other. For instance variable and parameter names must follow Camel casing and for class, function, and method names Pascal casing must be used. Make sure this basic principle is applied consistently.

9-  Code Readability

Many times code is written in a way that anyone can hardly make sense out of it. I.e. all code is so jumbled up and one line after the other that it’s barely readable. Make sure that code has proper Single line spacing wherever applicable between the code blocks.

 10-Handling Unmanaged Resources 

Even though .NET Framework takes good care of Memory management via GC (garbage collection) but there are limitations on what all garbage items and from where those can be collected and what not. Many times, it’s wise to handle cleaning of expensive resources like File I/O handles, connections, Network resources, etc. by yourself. Such items can be disposed of once their usage is over and this can be done using the “using” block for unmanaged code, if you want to automatically handle the disposing of objects once they are out of scope.  Another good place to handle such code is finally block for example, File I/O operation to read a file as shown in the image below.

Watch my YouTube channel video on FIle I/O here:

Figure-9 Handling unmanaged resources by .NET’s StreamReader

11-    Write Defensive Code

.NET Exception Handling is the key to write defensive code and protect your application against any runtime anomalies. Three magic words to solve most of your problems are try/catch and finally. Proper implementation and usage of Exception Handling and logging any exception messages and details can add a lot of value to application in terms of application monitoring and troubleshooting.

12-    Declare access specifiers explicitly

C# .NET has default scope defined for various types for instance a variable is private by default and so in a class we like to write just “int i” but it’s more appropriate to be declarative and instead write it as “private int i”.

Do you know what default scope of a class is in C #? Watch my YouTube channel video here 
13- Self Documenting code

Many times developers do follow naming convention (camel or pascal etc.) but the given names to variables, methods, functions and class etc. are not meaningful at all. Hence, at times developers write long code comments to describe what is the  purpose of each function or variable for instance. In my view, giving “self-describing” names will add a lot of value and also save developer’s time in documenting the code; as many software teams have a practice of writing comment above each line of code to explain the objective of code below. For instance, instead of “int age;” you may want to declare “int studentAge;”. Similarly, instead of just writing a function with name “GetData()” it will be preferred and more helpful to say “GetStudentsReportData()”. Similar techniques can also be applied to class names, functions and Unit Tests etc. But in case of unit tests, name(s) might get really lengthy, but this is totally fine and acceptable. Hence, a unit test method name “TestSuccessWithOneStudentRecordAddedToDb” will be much preferred than just saying “TestOneRecordData”.

Summary

Above mentioned code review guidelines are light weight, easy to look for and easy to apply techniques with larger impact on any code base.  Mostly it has been evident that simple things are either ignored or not cared about. These best practices can be added up with more guidelines or in combination with other techniques as applicable. Happy Coding…

Related Articles:

Inside Out: TDD using C#

Visual Studio and .NET Unit Test Framework

Unit Test Automation with Visual Studio

Introduction

Unit Tests play an important role in delivering high quality software solutions. An ideal unit test is a piece of code (automated test) written by a developer which exercises a small but specific area of code functionality to ensure that it works as expected.

Why Unit Test

According to the Test Triangle, in a software project the largest number of tests must be Unit Tests. Because multiple individual Unit Tests exercises small units of functionality which spans over entire various areas of functionality offered by the software solution.

 

Unit Test Check-List

While writing Unit Test(s) following points must be considered and followed by the Developers and SDETs.

Check

Description

  √

Self-Describing Names

Unit Test method names must be Self-Describing and Pascal case.  For example choose Add_New_Customer_With_Valid_AcccountNumber over AddCustomer_with_validAcc or addCustomer etc.Also focus on naming style, keep the naming style consistent across all the tests methods and test.

   [ ]

A3 (Arrange, Asset, Act)

Make sure that all the Test Methods are designed around Arrange, Act and Assert.If required Refactor your code to fall into these three sections.

   [ ]

Test Happy and Sad Path

The unit test should cover all possible scenarios and strive for high code coverage and ensuring good quality metrics. Unit Test methods must exercise all possible use case scenarios to test the input validations, interactions, errors messages, edge cases and exceptions etc.

   [ ]

Make use of Attributes

Use Test Framework provided Attributes like :

[TestCategory(“<describe if its Unit or Integration Test>”)]

[TestCategory(“<Which section of the application is being tested>”)]

[Priority(n), TestCategory(“<define if it’s Gated or not-Gated build Tests>”)]

[WorkItem(xxxx)]

[Owner(“<who wrote this test>”)]

   [ ]

Have least number of asserts per test (if applicable)

A good Unit test should only have limited # of assert statements. It should unit test the very functionality, as indicated in its descriptive name.A well-defined Unit Test should contain only one assert statement per test and must not try to exercise all the validation/boundary checks etc. by multiple Assert() in one Unit Test method. .

   [ ]

Keep assert messages descriptive

Use descriptive messages to improve readability of code and the build log.Assert.IsTrue(customer.IsExist,”The Customer is not found in the Database”);

   [ ]

Unit != Integration

There is a very fine line between Unit and Integration, if you happen to go beyond what your function is supposed to be doing then you are not writing a Unit Test. I.e. Unit Test doesn’t focus on interaction with external systems and software layers/dependencies.Test Doubles (for example Microsoft Fakes framework) comes into the picture to write unit tests which has dependencies on external libraries and systems etc.

   [ ]

Follow OOP Design and Adopt DI

Following Dependency Injection will allow to convert potential Integration Tests into small and quickly testable Unit Tests by taking advantages of Test Doubles (e.g. Microsoft Fakes, Moq, FakeItEasy frameworks etc.)

   [ ]

Should be thorough

Unit Tests are supposed to test all the possible areas of functionality that are subject to failure due to incorrect input/validation checks/boundary checks etc. for given function/method.

   [ ]

Must be Repeatable

Unit Tests must be repeatable for every build and must produce the same results. The development best practice suggests that if you are working on code that is impacting a Unit Test then you must fix the affected Unit Test as well and ensure that it passes.

   [ ]

Have to be Independent

Unit Tests must be independent of another test. In other words, no collateral damage. Hence, a Unit Test must focus only on a small aspect of big functionality. When this Unit Test fails, it should be easy to discover where the issue is in the code. I.e. can be tested in isolation

   [ ]

Keep it Professional

Even though at times Unit Tests may appear to be very simple and small, you must write Unit Tests with coding practices as good as you use for your main development coding. You may want to follow Refactoring, Code Analysis and Code Review practices and so on as for your Test Projects as well.

  [ ]

No Collateral Damage

Make Sure to Run all related Unit Tests after any dev code change big or small; to verify and ensure that no collateral damage occurs or has been introduced.

  [ ]

If you break it, You bought it

If you are working on a feature and to verify no collateral damage, as a best practice run all the Unit Tests. If you observe that some Unit Tests started failing because of your code changes then you own to Fix those broken Unit Tests to make sure that continue to pass.

  [ ]

Track and  maintain the tests

The test code changes should be tracked and maintained as on-going effort. Continue to follow thedesign principles and coding guidelines.

  [ ]

Code Review the Tests

Just like any other Dev code, Unit Tests also needs to be code reviewed by peer. Regardless of size of the test; follow the process.Code review might include reviewing the name of test method, scenarios covered, conditions checked, scope of assertions and code / design smells etc.