KEMBAR78
Writing clean code in C# and .NET
Writing Clean Code in C# and .NET
About.ME
• Senior Consultant @CodeValue
• Developing software (Professionally) since 2002
• Writing clean code since 2009
• Blogger: http://blog.drorhelper.com
Let’s talk about software bugs
Bugs cost around $312 Billion Per Year
And it’s all a developer’s fault
The cost of fixing bugs
1 2 10
20
50
150
RQUIRMENTS DESIGN CODE DEV T ACC T OPERATION
[B. Boehm - ICSE 2006 Keynote Address]
High quality code is:
• Easy to read and understand
• Impossible to hide bugs
• Easy to extend
• Easy to change
• Has unit tests
Be a proud of your code
Broken windows
The cost of owning a mess
0
10
20
30
40
50
60
70
80
90
100
Productivity
Productivity
[Robert Martin – “Clean Code”]
Quality == Agility
• Adapt to changes
• Don’t be held back by bugs
• Cannot be agile without high quality code
How a developer spends his time
60% - 80% time spent in understanding code
So make sure your code is readable
But what is a readable code?
“Always code as if the guy who ends up
maintaining your code will be a violent
psychopath who knows where you live”
Megamoth
Stands for MEGA MOnolithic meTHod.
Often contained inside a God Object, and
usually stretches over two screens in height.
Megamoths of greater size than 2k LOC have
been sighted. Beware of the MEGAMOTH!
http://blog.codinghorror.com/new-programming-jargon/
Write short methods – please!
• It’s easier to understand
• Performance won’t suffer
• Avoid mixing abstraction layers
• Enable re-use
• Also write small classes
How can we recognize bad code?
• You know it we you see it
• You feel it when you write it
• You get used to it after a while 
• known as Code Smells
Code Smells
• Duplicate code
• Long method
• Large class
• Too many parameters
• Feature envy
• Inappropriate intimacy
• Refused request
• Lazy class/Freeloader
• Contrived complexity
• Naming!
• Complex Conditionals
• And more…
http://en.wikipedia.org/wiki/Code_smell
Comments often are used as a deodorant
Refactoring, Martin Fowler
Comments are a dead giveaway
• If explains how things done means that the
developer felt bad about the code
• “Code title” – should be a method
• Commented Old code – SCM
Good comments exist in the wild – but rare
http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-
source-code-you-have-ever-encountered
/// <summary>
/// Gets or sets the name of the first.
/// </summary>
/// <value>The name of the first.</value>
public string FirstName
}
get { return _firstName; }
set { _firstName = value; }
{
/** Logger */
private Logger logger = Logger.getLogger();
/// <summary>
/// The possible outcomes of an update
operation (save or delete)
/// </summary>
public enum UpdateResult
}
/// <summary>
/// Updated successfully
/// </summary>
Success = 0,
/// <summary>
/// Updated successfully
/// </summary>
Failed = 1
{
//private instance variable for storing age
public static int age;
// Always returns true.
public bool isAvailable()
}
return false;
{
Regions == Comments
Naming is important
d, days  daysSinceLastPayment
customerPo  customerPurchaseOrder
productIdString  productId
genymdhms  generationTimeStamp
Dead Code
• Code which is never run
• But still has maintenance costs
• Solution - delete
Undead Code
Dead code that you’re afraid to delete
- “I might need this…”
geek-and-poke.com/
// UNUSED
// Separate into p_slidoor.c?
#if 0 // ABANDONED TO THE MISTS OF TIME!!!
//
// EV_SlidingDoor : slide a door horizontally
// (animate midtexture, then set noblocking line)
//
Avoid duplicate code (DRY)
“Every piece of knowledge must have a
single, unambiguous, authoritative
representation within a system”
The Pragmatic Programmer: Dave Thomas, Andy Hunt
public bool HasGroup(List<Token> tokenList){
for(Token token : tokemList){
if(token.get_group() != null) {
return true;
{
{
return false;
{
public Group GetValidGroup(List<Customer> customers){
for(Customer customer : customers){
Group group = customer.get_group();
if(group != null) {
return group;
{
{
return null;
{
Good code start with good design
Bad DesignGood design
RigidLoosely coupled
FragileHighly cohesive
ImmobileEasily composable
ViscousContext independent
It’s all about dependencies
• In .NET Reference == dependency
• Change in dependency  change in code
This is not OOP!!!
public class Record_Base
{
public DateTime RecordDateTime
{
get { return _recordDateTime; }
set
{
if (this.GetType().Name == "Record_PartRegister")
_recordDateTime = value;
else
throw new Exception("Cannot call set on RecordDateTime for table " + this.GetType().Name);
}
}
}
http://thedailywtf.com/Articles/Making-Off-With-Your-Inheritance.aspx
Design stamina hypothesis
http://martinfowler.com/bliki/DesignStaminaHypothesis.html
Principles of Object Oriented Design
Single responsibility
Open/closed
Liskov substitution
Interface segregation
Dependency inversion
www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
Single responsibility
A class should have one, and only one,
reason to change.
http://www.amazon.com/Wenger- 16999-ssiwS-efinK-
B/pd/tnaiG001 DZTJRQ/
Naming as code smell
Having difficulties naming your class/method?
You might be violating SRP
public interface ITimerService
{
IDisposable SetTimout(long durationMilliSeconds, Action callback);
Task Delay(TimeSpan delay, CancellationToken token);
void KillLastSetTimer();
}
public interface IDispacherTimerService : ITimerService
{
long GetMilisecondsFromLastStart();
}
public interface IElapsedTimerService : ITimerService
{
void SetTimout(long durationMilliSeconds, Action<TimeSpan> callback);
}
Open closed principle
software entities should be
open for extension,
but
closed for modification
Liskov subtitution
objects in a program should
be replaceable with instances of their
subtypes
without altering the correctness of that
program
LSP smell - look for type checking
void ArrangeBirdInPattern(IBird aBird)
}
var aPenguin = aBird as Pinguin;
if (aPenguin != null)
}
ArrangeBirdOnGround(aPenguin);
{
else
}
ArrangeBirdInSky(aBird);
{
// What about Emu?
{
Interface segregation
Many client specific interfaces are better than
one general purpose interface.
http://en.wikipedia.org/wiki/Cockpit
Dependency Inversion
Depend upon abstractions.
Do not depend upon concretions.
Your code will change!
• Requirements change
• Bugs are found
• New feature requests
 Your design will change
In the beginning…
Application was beautiful - then came change…
• Software Rot
– Duplication
– Excess coupling
– Quick fixes
– Hacks
public override void HandleActionRejected(User from, reason reason)
}
Logger.Info("HandleActionRejected - user:{0}", from.Id);
/*foreach (var user in UserRepository.GetAllUsers)
}
Client.SendInfo(user, from, reason);
{ */
//2.2
Events.Users.Value = new UserData
}
SessionId = CurrentSession.Id,
HaveIInitiated = true,
OtherUser = from,
StartCallStatus = Events.ConvertToCallStatus(answer)
{;
UserRepository.Remove(from, reason);
if(UserRepository.IsEmpty())
}
Exit();
{
{
Refactoring
Refactoring
“a disciplined technique for restructuring
an existing body of code, altering its
internal structure without changing its
external behavior”
- Martin Fowler
http://refactoring.com/catalog/
Refactoring with Visual Studio
Code reviews
Can catch up to 60% of defects
Effective code reviews are:
• Short – don’t waste time
• Constructive
• Avoid emotionally draining arguments
Everybody reviews and everybody is reviewed
No quality has very high cost
Never have time to do it,
but always have time to re-do it.
Explain why this feature takes so much time
“You rush a miracle man,
you get rotten miracles.”
Don’t expect your company to force you
Be a professional
Care about your code
Improve your code
• Start as soon as you can
• Don’t compromise
Schedule time for quality
–Improve existing code
–Make it work, then make it better
49
Writing clean code in C# and .NET

Writing clean code in C# and .NET

  • 1.
    Writing Clean Codein C# and .NET
  • 2.
    About.ME • Senior Consultant@CodeValue • Developing software (Professionally) since 2002 • Writing clean code since 2009 • Blogger: http://blog.drorhelper.com
  • 3.
    Let’s talk aboutsoftware bugs
  • 4.
    Bugs cost around$312 Billion Per Year
  • 5.
    And it’s alla developer’s fault
  • 6.
    The cost offixing bugs 1 2 10 20 50 150 RQUIRMENTS DESIGN CODE DEV T ACC T OPERATION [B. Boehm - ICSE 2006 Keynote Address]
  • 7.
    High quality codeis: • Easy to read and understand • Impossible to hide bugs • Easy to extend • Easy to change • Has unit tests Be a proud of your code
  • 8.
  • 9.
    The cost ofowning a mess 0 10 20 30 40 50 60 70 80 90 100 Productivity Productivity [Robert Martin – “Clean Code”]
  • 10.
    Quality == Agility •Adapt to changes • Don’t be held back by bugs • Cannot be agile without high quality code
  • 11.
    How a developerspends his time 60% - 80% time spent in understanding code So make sure your code is readable But what is a readable code?
  • 12.
    “Always code asif the guy who ends up maintaining your code will be a violent psychopath who knows where you live”
  • 13.
    Megamoth Stands for MEGAMOnolithic meTHod. Often contained inside a God Object, and usually stretches over two screens in height. Megamoths of greater size than 2k LOC have been sighted. Beware of the MEGAMOTH! http://blog.codinghorror.com/new-programming-jargon/
  • 14.
    Write short methods– please! • It’s easier to understand • Performance won’t suffer • Avoid mixing abstraction layers • Enable re-use • Also write small classes
  • 15.
    How can werecognize bad code? • You know it we you see it • You feel it when you write it • You get used to it after a while  • known as Code Smells
  • 16.
    Code Smells • Duplicatecode • Long method • Large class • Too many parameters • Feature envy • Inappropriate intimacy • Refused request • Lazy class/Freeloader • Contrived complexity • Naming! • Complex Conditionals • And more… http://en.wikipedia.org/wiki/Code_smell
  • 17.
    Comments often areused as a deodorant Refactoring, Martin Fowler
  • 18.
    Comments are adead giveaway • If explains how things done means that the developer felt bad about the code • “Code title” – should be a method • Commented Old code – SCM Good comments exist in the wild – but rare
  • 19.
    http://stackoverflow.com/questions/184618/what-is-the-best-comment-in- source-code-you-have-ever-encountered /// <summary> /// Getsor sets the name of the first. /// </summary> /// <value>The name of the first.</value> public string FirstName } get { return _firstName; } set { _firstName = value; } { /** Logger */ private Logger logger = Logger.getLogger(); /// <summary> /// The possible outcomes of an update operation (save or delete) /// </summary> public enum UpdateResult } /// <summary> /// Updated successfully /// </summary> Success = 0, /// <summary> /// Updated successfully /// </summary> Failed = 1 { //private instance variable for storing age public static int age; // Always returns true. public bool isAvailable() } return false; {
  • 20.
  • 21.
    Naming is important d,days  daysSinceLastPayment customerPo  customerPurchaseOrder productIdString  productId genymdhms  generationTimeStamp
  • 22.
    Dead Code • Codewhich is never run • But still has maintenance costs • Solution - delete
  • 23.
    Undead Code Dead codethat you’re afraid to delete - “I might need this…” geek-and-poke.com/ // UNUSED // Separate into p_slidoor.c? #if 0 // ABANDONED TO THE MISTS OF TIME!!! // // EV_SlidingDoor : slide a door horizontally // (animate midtexture, then set noblocking line) //
  • 24.
    Avoid duplicate code(DRY) “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system” The Pragmatic Programmer: Dave Thomas, Andy Hunt
  • 25.
    public bool HasGroup(List<Token>tokenList){ for(Token token : tokemList){ if(token.get_group() != null) { return true; { { return false; { public Group GetValidGroup(List<Customer> customers){ for(Customer customer : customers){ Group group = customer.get_group(); if(group != null) { return group; { { return null; {
  • 26.
    Good code startwith good design Bad DesignGood design RigidLoosely coupled FragileHighly cohesive ImmobileEasily composable ViscousContext independent It’s all about dependencies • In .NET Reference == dependency • Change in dependency  change in code
  • 27.
    This is notOOP!!! public class Record_Base { public DateTime RecordDateTime { get { return _recordDateTime; } set { if (this.GetType().Name == "Record_PartRegister") _recordDateTime = value; else throw new Exception("Cannot call set on RecordDateTime for table " + this.GetType().Name); } } } http://thedailywtf.com/Articles/Making-Off-With-Your-Inheritance.aspx
  • 28.
  • 29.
    Principles of ObjectOriented Design Single responsibility Open/closed Liskov substitution Interface segregation Dependency inversion www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
  • 30.
    Single responsibility A classshould have one, and only one, reason to change. http://www.amazon.com/Wenger- 16999-ssiwS-efinK- B/pd/tnaiG001 DZTJRQ/
  • 31.
    Naming as codesmell Having difficulties naming your class/method? You might be violating SRP
  • 32.
    public interface ITimerService { IDisposableSetTimout(long durationMilliSeconds, Action callback); Task Delay(TimeSpan delay, CancellationToken token); void KillLastSetTimer(); } public interface IDispacherTimerService : ITimerService { long GetMilisecondsFromLastStart(); } public interface IElapsedTimerService : ITimerService { void SetTimout(long durationMilliSeconds, Action<TimeSpan> callback); }
  • 33.
    Open closed principle softwareentities should be open for extension, but closed for modification
  • 35.
    Liskov subtitution objects ina program should be replaceable with instances of their subtypes without altering the correctness of that program
  • 36.
    LSP smell -look for type checking void ArrangeBirdInPattern(IBird aBird) } var aPenguin = aBird as Pinguin; if (aPenguin != null) } ArrangeBirdOnGround(aPenguin); { else } ArrangeBirdInSky(aBird); { // What about Emu? {
  • 37.
    Interface segregation Many clientspecific interfaces are better than one general purpose interface. http://en.wikipedia.org/wiki/Cockpit
  • 38.
    Dependency Inversion Depend uponabstractions. Do not depend upon concretions.
  • 39.
    Your code willchange! • Requirements change • Bugs are found • New feature requests  Your design will change
  • 40.
    In the beginning… Applicationwas beautiful - then came change… • Software Rot – Duplication – Excess coupling – Quick fixes – Hacks
  • 41.
    public override voidHandleActionRejected(User from, reason reason) } Logger.Info("HandleActionRejected - user:{0}", from.Id); /*foreach (var user in UserRepository.GetAllUsers) } Client.SendInfo(user, from, reason); { */ //2.2 Events.Users.Value = new UserData } SessionId = CurrentSession.Id, HaveIInitiated = true, OtherUser = from, StartCallStatus = Events.ConvertToCallStatus(answer) {; UserRepository.Remove(from, reason); if(UserRepository.IsEmpty()) } Exit(); { {
  • 42.
  • 43.
    Refactoring “a disciplined techniquefor restructuring an existing body of code, altering its internal structure without changing its external behavior” - Martin Fowler http://refactoring.com/catalog/
  • 44.
  • 45.
    Code reviews Can catchup to 60% of defects Effective code reviews are: • Short – don’t waste time • Constructive • Avoid emotionally draining arguments Everybody reviews and everybody is reviewed
  • 46.
    No quality hasvery high cost Never have time to do it, but always have time to re-do it. Explain why this feature takes so much time “You rush a miracle man, you get rotten miracles.”
  • 47.
    Don’t expect yourcompany to force you Be a professional Care about your code
  • 48.
    Improve your code •Start as soon as you can • Don’t compromise Schedule time for quality –Improve existing code –Make it work, then make it better 49

Editor's Notes

  • #6 The developer Wrote the code - Was the first to see the feature Can validate requirments
  • #7 So why not have better testing? It’s hard to find all of the scenarios Cost of fixing increase
  • #10 Bad code attracts more bad code “It was like this when I got here”
  • #13 Show example of not readable code
  • #15 a.k.a spaghetti code
  • #27 Avoid duplicate code (DRY)