SlideShare a Scribd company logo
1 of 169
High-Quality Programming Code Construction Revealing the Secrets of Self-Documenting Code http://schoolacademy.telerik.com For C# Developers Svetlin Nakov Telerik Corporation www.telerik.com
Table of Contents What is High-Quality Programming Code? Naming Identifiers Naming classes, methods, variables, etc. Code Formatting Designing High-Quality Classes High-Quality Methods Cohesion and Coupling Using Variables Correctly Using Expressions Correctly 2
Table of Contents (2) Using Constants Using Control-Flow Constructs Correctly Conditional Statements Loops Defensive Programming Assertions and Exceptions Comments and Documentation Code Refactoring 3
What is High-Quality Programming Code?
Why the Code Quality Is Important? static void Main() {   int value=010, i=5, w;   switch(value){case 10:w=5;Console.WriteLine(w);break;case 9:i=0;break;           case 8:Console.WriteLine("8 ");break;      default:Console.WriteLine("def ");{ 	        Console.WriteLine("hoho ");	}      for (int k = 0; k < i; k++, Console.WriteLine(k - 'f'));break;} { Console.WriteLine("loop!"); } } What does this code do? Is it correct? 5
Why the Code Quality Is Important? (2) static void Main() {   int value = 010, i = 5, w;   switch (value)   {     case 10: w = 5; Console.WriteLine(w); break;     case 9: i = 0; break;     case 8: Console.WriteLine("8 "); break;     default:       Console.WriteLine("def ");       Console.WriteLine("hoho ");       for (int k = 0; k < i; k++, Console.WriteLine(k -'f'));        break;     }     Console.WriteLine("loop!"); } Now the code is formatted, but is still unclear. 6
Software Quality External quality Does the software behave correctly? Are the produced results correct? Does the software runfast? Is the software UI easy-to-use? Internal quality It the code easy to read and understand? It the code well structured? Is the code easy to modify? 7
What is High-Quality Programming Code? High-quality programming code: Easy to read and understand Easy to modify and maintain Correct behavior in all cases Well tested Well architectured and designed Well documented Self-documenting code  Well formatted 8
Code Conventions Code conventions are formal guidelines about the style of the source code: Code formatting conventions Indentation, whitespace, etc. Naming conventions PascalCase or camelCase, prefixes, suffixes, … Best practices Classes, interfaces, enumerations, structures, inheritance, exceptions, properties, events, constructors, fields, operators, etc. 9
Code Conventions (2) Microsoft has official code conventions called Design Guidelines for Developing Class Libraries: http://msdn.microsoft.com/en-us/library/ms229042.aspx Large organizations follow strict conventions Code conventions can vary in different teams Most conventions developers follow the official Microsoft's recommendations but extend them High-quality code goes beyond code conventions Software quality is not just a set of conventions – its is a way of thinking 10
Naming Identifiers Naming Classes, Interfaces, Enumerations, Methods, Variables and Constants
General Naming Guidelines Always use English How you will feel if you read Vietnamese code with variables named in Vietnamese? English is the only language that all software developers speak Avoid abbreviations Example: scrpCnt vs. scriptsCount Avoid hard-to-pronounce names Example:  dtbgRegExPtrn vs. dateTimeBulgarianRegExPattern 12
Use Meaningful Names Always prefer using meaningful names Names should answer these questions: What does this class do? What is the intent of this variable? What is this variable / class used for? Examples: FactorialCalculator, studentsCount, Math.PI, configFileName, CreateReport Incorrect examples:  k, k2,k3,junk,f33,KJJ,button1, variable, temp, tmp, temp_var, something, someValue 13
Fake Meaningful Names Junior developers often use meaningful names that are in fact meaningless Bad naming examples: Topic6Exercise12, LoopsExercise12,Problem7, OOPLecture_LastExercise Yes, Topic6Exercise12 indicates that this is solution to exercise 12, but what is it about? Better naming: MaximalNumbersSubsequence 14
Naming Types Naming types (classes, structures, etc.) Use PascalCase character casing Examples: RecursiveFactorialCalculator, TreeSet, XmlDocument, IEnumerable, Color, TreeNode, InvalidTransactionException, MainForm Incorrect examples:  recursiveFactorialCalculator, recursive_factorial_calculator,  RECURSIVE_FACTORIAL_CALCULATOR 15
Naming Classes and Structures Use the following formats: [Noun] [Adjective] + [Noun] Examples: Student, FileSystem, BinaryTreeNode, Constants, MathUtils, TextBox, Calendar Incorrect examples: Move, FindUsers, Fast, Optimize, Extremly, FastFindInDatabase, Check 16
Naming Interfaces Following formats are acceptable: 'I' + [Verb] + 'able' 'I' + [Noun], 'I' + [Adjective] + [Noun] Examples: IEnumerable, IFormattable, IDataReader, IList, IHttpModule, ICommandExecutor Incorrect examples: List, FindUsers, IFast, IMemoryOptimize, Optimizer, FastFindInDatabase, CheckBox 17
Naming Enumerations Several formats are acceptable: [Noun] or [Verb] or [Adjective] Use the same style for all members Examples: enum Days {Monday, Tuesday, Wednesday, …}, enum AppState {Running, Finished, …} Incorrect examples: enum Color {red, green, blue, white}, enum PAGE_FORMAT {A4, A5, A3, LEGAL, …} 18
Naming Special Classes Exceptions Add 'Exception' as suffix Use informative name Example: FileNotFoundException Incorrect example: FileNotFoundError Delegate Classes Add 'Delegate' or 'EventHandler' as suffix Example: DownloadFinishedDelegate Incorrect example: WakeUpNotification 19
The Length of Class Names How long could be the name of a class / struct / interface / enum? The name should be as long as required Don't abbreviate the names if this could make them unclear Your IDE has autocomplete, right? Examples: FileNotFoundException, CustomerSupportNotificationService Incorrect examples: FNFException, CustSuppNotifSrvc 20
Naming Projects / Folders Project naming guidelines Use PascalCase Following formats are preferable: ProductName Company [., -, _] ProductName Name project folders to match the project name / its component names Examples: Sitefinity, Telerik JustCode Incorrect example: ConsoleApplication17 21
Naming Namespaces Namespaces naming guidelines Use PascalCase Following formats are acceptable: Company . Product . Component . … Product . Component . … Example: Telerik.WinControls.GridView Incorrect example: Telerik_WinControlsGridView, Classes 22
Naming Assemblies Assembly names should follow the root namespace in its class hierarchy Examples: Telerik.WinControls.GridView.dll Oracle.DataAccess.dll Interop.CAPICOM.dll Incorrect examples: Telerik_WinControlsGridView.dll OracleDataAccess.dll 23
Naming Methods Methods naming guidelines Method names should be meaningful Should answer the question: What does this method do? If you cannot find a good name for a method, think about does it have clear intent Examples: FindStudent, LoadReport, Sin Incorrect examples: Method1, DoSomething, HandleStuff, SampleMethod, DirtyHack 24
Naming Methods (2) Use PascalCase character casing Example: LoadSettings, not loadSettings Prefer the following formats: [Verb] [Verb] + [Noun], [Verb] + [Adjective] + [Noun] Examples: Show, LoadSettingsFile, FindNodeByPattern,  ToString, PrintList Incorrect examples: Student, Counter, White, Generator, Approximation, MathUtils 25
Methods Returning a Value Methods returning values should describe the returned value Examples: ConvertMetersToInches, not MetersInches or Convert or ConvertUnit Meters2Inches is still acceptable CalculateSinis good Sin is still acceptable (like in the Math class) Ensure that the unit of measure of obvious Prefer MeasureFontInPixelsto MeasureFont 26
Single Purpose of All Methods Methods should have a single purpose! Otherwise they cannot be named well How to name a method that creates annual incomes report, downloads updates from internet and scans the system for viruses? CreateAnnualIncomesReportDownloadUpdatesAndScanForViruses is a nice name, right? Methods that have multiple purposes (weak cohesion) are hard to be named Need to be refactored instead of named 27
Consistency in Methods Naming Use consistent naming in the entire project LoadFile, LoadImageFromFile, LoadSettings, LoadFont, LoadLibrary, but not ReadTextFile Use consistently the opposites at the same level of abstraction: LoadLibrary vs. UnloadLibrary, but not  FreeHandle OpenFile vs. CloseFile, but not  DeallocateResource GetName vs. SetName, but not  AssignName 28
The Length of Method Names How long could be the name of a method? The name should be as long as required Don't abbreviate Your IDE has autocomplete Examples: LoadCustomerSupportNotificationService, CreateMonthlyAndAnnualIncomesReport Incorrect examples: LoadCustSuppSrvc, CreateMonthIncReport 29
Naming Method Parameters Method parameters names Preferred form: [Noun] or [Adjective] + [Noun] Should be in camelCase Should be meaningful Unit of measure should be obvious Examples: firstName, report, usersList, fontSizeInPixels, speedKmH, font Incorrect examples: p, p1, p2, populate, LastName, last_name, convertImage 30
Naming Variables Variable names Should be in camelCase Preferred form: [Noun] or [Adjective] + [Noun] Should explain the purpose of the variable If you can't find good name for a variable check if it has a single purpose Exception: variables with very small scope, e.g. the index variable in a 3-lines long for-loop Names should be consistent in the project 31
Naming Variables – Examples Examples: firstName, report, usersList , fontSize, maxSpeed, font, startIndex, endIndex, charsCount, configSettingsXml, config, dbConnection, createUserSqlCommand Incorrect examples: foo, bar, p, p1, p2, populate, LastName, last_name, LAST_NAME, convertImage, moveMargin, MAXSpeed, _firstName, __temp, firstNameMiddleNameAndLastName 32
More about Naming Variables The name should be addressed to the problem we solve, not to the means we use to solve it Prefer nouns from the business domain to computer terms Examples: accounts, customers, customerAddress, accountHolder, paymentPlan, vipPlayer Incorrect examples: accountsLinkedList, customersHashtable, paymentsPriorityQueue, playersArray 33
Naming Boolean Variables Boolean variables should imply true or false Prefixes like is, has and can are useful Use positive boolean variable names Incorrect example: Examples: hasPendingPayment, customerFound, validAddress, positiveBalance, isPrime Incorrect examples: notFound, run, programStop, player, list, findCustomerById, isUnsuccessfull 34 if (! notFound) { … }
Naming Special Variables Naming Counters Establish a convention, e.g. [Noun] + 'Count' Examples: ticketsCount, customersCount State Establish a convention, e.g. [Noun] + 'State' Examples: blogParseState, threadState Variables with small scope and span Short names can be used, e.g. index, i, u 35
Temporary Variables Do really temporary variables exist? All variables in a program are temporary because they are used temporarily only during the program execution, right? Temporary variables can always be named better than temp or tmp: 36 // Swap a[i] and a[j] int temp = a[i]; a[i] = a[j]; a[j] = temp; // Swap a[i] and a[j] int swapValue = a[i]; a[i] = a[j]; a[j] = swapValue;
The Length of Variable Names How long could be the name of a variable? Depends on the variable scope and lifetime More "famous" variables should have longer and more self-explaining name Acceptable naming examples: Unacceptable naming examples: 37 class Student {   public string lastName; } for (int i=0; i<users.Length; i++)   if (i % 2 == 0)     sum += users[i].Weight; class Student {   private int i; } class PairOfLists {   public int Count { get; set; } }
Prefixes / Suffixes and Hungarian Notation In C# prefix / suffix notations are not popular Hungarian notation Using prefixes to denote the variable types, e.g. lpcstrText, lpdwFlags, cbMultiByte, hWnd The Hungarian notation works well in unmanaged languages like C++ Do not use Hungarian notation in C# and .NET Don't use prefixes / suffixes to denote the variable data type 38
Naming Properties Name properties in C# using a noun, noun phrase, or an adjective Use Pascal Case Examples: Incorrect examples: 39 public int Length { … } public Color BackgroundColor { … } public CacheMode CacheMode { … } public bool Loaded { … } public int Load { … } public Color BackgroundColor { … } public bool Font { … }
Naming Constants Use CAPITAL_LETTERS for const fields and PascalCase for readonly fields Use meaningful names that describe their value Examples: Incorrect examples: 40 private const int READ_BUFFER_SIZE = 8192; public static readonly PageSize DefaultPageSize = PageSize.A4; private const int FONT_SIZE_IN_POINTS = 16; public const int MAX = 512; // Max what? Apples or Oranges? public const int BUF256 = 256; // What about BUF256 = 1024? public const string GREATER = "&gt;"; // GREATER_HTML_ENTITY public const int FONT_SIZE = 16; // 16pt or 16px? public const PageSize PAGE = PageSize.A4; // Maybe PAGE_SIZE?
Names to Avoid Don't use numbers in the identifiers names Example:  PrintReport and PrintReport2 What is the difference? Exceptions: When the number is part of the name itself, e.g. RS232Port, COM3, Win32APIFunctions Don't use Cyrillic or letters from other alphabets E.g. FindСтудентByName, CalcΩ2Protein 41
Never Give a Misleading Name! Giving a misleading name is worse than giving a totally unclear name Example: Consider a method that calculates the sum of all elements in an array It should be named Sum or CalculateSum What about naming it CalculateAverageor Max or CheckForNegativeNumber? It's crazy, but be careful with "copy-paste" 42
Don't Believe Microsoft! Microsoft sometimes use really bad naming in their API libraries (especially in Win32 API) Examples: Navigateand Navigate2methods in Internet Explorer ActiveX control (MSHTML.DLL) WNetAddConnection3method in Multiple Provider Router Networking API (MPR.DLL) LPWKSTA_USER_INFO_1structure in Win32 Don't follow them blindly, just think a bit! 43
What's Wrong with This Code? 44 FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew); // Create the writer for data. BinaryWriter w = new BinaryWriter(fs); // Write data to Test.data. for (int i = 0; i < 11; i++)  {   w.Write( (int) i); } w.Close(); fs.Close(); // Create the reader for data. fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); // Read data from Test.data. for (int i = 0; i < 11; i++)  {   Console.WriteLine(r.ReadInt32()); } r.Close(); fs.Close(); Source: http://msdn.microsoft.com/en-us/library/36b93480.aspx
Naming Should BeClear inside Its Context Naming should be clear inside its context Method names should be clear in their class Methods should not repeat their class name Parameter names should be clear in the context of their method name Example of good class / property naming: 45 class Font {  public string Name { get; } // not FontName }
Naming Should BeClear inside Its Context (2) Example of good method & parameter naming: Name like CalcDistanceBetweenPoints is excessive – parameters say "between points" Parameter names still can be improved: Name like Calc can still be correct: 46 double CalcDistance(Point p1, Point p2) { … } double CalcDistance(Point firstPoint,   Point secondPoint) { … } class DistanceCalculator { static double Calc(Point p1, Point p1) { … } }
Naming Should BeClear inside Its Context (3) Incorrect example of method naming: It is unclear in this context what kind of calculation is performed by the method Incorrect example of parameter naming: 47 class Program {  int Calculation(int value) } What "f" means? An URL or FTP server or file path? class FileDownloader {   byte[] Download(string f); }
Code Formatting
Why Code Needs Formatting? 49 public   const    string                    FILE_NAME ="example.bin"  ;  static void Main   (             ){ FileStream   fs=     new FileStream(FILE_NAME,FileMode .   CreateNew)   // Create the writer      for data  . ;BinaryWriter w=new BinaryWriter     (    fs      );// Write data to                               Test.data. for(  int i=0;i<11;i++){w.Write((int)i);}w   .Close(); fs   .   Close  (  ) // Create the reader    for data. ;fs=new FileStream(FILE_NAME,FileMode.            Open ,  FileAccess.Read)     ;BinaryReader                r = new BinaryReader(fs);  // Read data from  Test.data.  for (int i = 0; i < 11; i++){ Console      .WriteLine (r.ReadInt32                                       ()) ;}r       .    Close   (   );  fs .  Close  (  )  ;  }
Code Formatting Fundamentals Good formatting goals To improve code readability To improve code maintainability Fundamental principle of code formatting: Any formatting style that follows the above principle is good Any other formatting is not good 50 The formating of the source code should disclose its logical structure.
Formatting Blocks in C# Put { and } alone on a line under the corresponding parent block Indent the block contents by a single [Tab] Don't indent with spaces Example: 51 if ( some condition ) {   // Block contents indented by a single [Tab]   // Don't use spaces for indentation }
Methods Indentation Methods should be indented with a single [Tab] from the class body Methods body should be indented with a single [Tab] as well 52 public class IndentationExample {   private int Zero()   {     return 0;   } } The entire method is indented with a single [Tab] Method body is also indented
Brackets in Methods Declaration Brackets in the method declaration should be formatted as follows: Don't  use spaces between the brackets: The same applies for if-conditions and for-loops: 53 private static ulong CalcFactorial(uint num) private static ulong CalcFactorial ( uint num )  private static ulong CalcFactorial (uint num)  if (condition) …
Separating Parameters Separate method parameters by comma followed by a space Don't put comma before the space Examples: Incorrect examples: 54 private void RegisterUser(string username, string password) RegisterUser("nakov", "s3cr3t!p@ssw0rd"); private void RegisterUser(string username,string password) private void RegisterUser(string username ,string password) private void RegisterUser(string username , string password)
Empty Lines between Methods Use empty line for separation between methods: 55 public class Factorial {   private static ulong CalcFactorial(uint num)   {     if (num == 0)       return 1;     else       return num * CalcFactorial(num - 1);   }   static void Main()   {     ulong factorial = CalcFactorial(5);     Console.WriteLine(factorial);   } } Always use { and } after if (there is no space to do it here) Empty line
Empty Lines in Method Body Use an empty line to separate logically related sequences of lines: 56 private List<Report> PrepareReports() {     List<Report> reports = new List<Report>();     // Create incomes reports     Report incomesSalesReport = PrepareIncomesSalesReport();     reports.Add(incomesSalesReport);     Report incomesSupportReport = PrepareIncomesSupportReport();     reports.Add(incomesSupportReport);     // Create expenses reports     Report expensesPayrollReport = PrepareExpensesPayrollReport();     reports.Add(expensesPayrollReport);     Report expensesMarketingReport = PrepareExpensesMarketingReport();     reports.Add(expensesMarketingReport);     return reports; } Empty line Empty line Empty line
Misplaced Empty Lines – Example 57 public static void PrintList(List<int> ints)  {   Console.Write("{ ");   foreach (int item in ints)   {     Console.Write(item);     Console.Write(" ");   }   Console.WriteLine("}"); } static void Main() {   // ... }
Formatting Types Formatting classes / structures / interfaces / enumerations Indent the class body with a single [Tab] Use the following order of definitions: Constants, delegates, inner types, fields, constructors, properties, methods Static members, public members, protected members,  internal members, private members The above order of definitions is not the only possible correct one 58
Formatting Types – Example 59 public class Dog {   // Static variables   public const string SPECIES =      "Canis Lupus Familiaris";   // Instance variables   private int age;   // Constructors   public Dog(string name, int age)   {     this.Name = name;     this.age = age;   }  (continues on the next slide)
Formatting Types – Example (2) 60   // Properties   public string Name { get; set; }   // Methods   public void Breath()   {     // TODO: breathing process   }   public void Bark()   {     Console.WriteLine("wow-wow");   } }
Formatting Conditional Statements and Loops Formatting conditional statements and loops Always use { } block after if / for / while, even when a single operator follows Indent the block body after if / for / while Never put the block after if / for / while on the same line! Always put the { on the next line Never indent with more than one [Tab] 61
Conditional Statements and Loops Formatting – Examples Example: Incorrect examples: 62 for (int i=0; i<10; i++) {   Console.WriteLine("i={0}", i); } for (int i=0; i<10; i++)   Console.WriteLine("i={0}", i); for (int i=0; i<10; i++) Console.WriteLine("i={0}", i); for (int i=0; i<10; i++) {   Console.WriteLine("i={0}", i); }
Breaking Long Lines Break long lines after punctuation Indent the second line by single [Tab] Do not additionally indent the third line Examples: 63 if (matrix[x, y] == 0 || matrix[x-1, y] == 0 ||   matrix[x+1, y] == 0 || matrix[x, y-1] == 0 ||   matrix[x, y+1] == 0) { … DictionaryEntry<K, V> newEntry =    new DictionaryEntry<K, V>(   oldEntry.Key, oldEntry.Value);
Incorrect Ways ToBreak Long Lines 64 if (matrix[x, y] == 0 || matrix[x-1, y] ==   0 || matrix[x+1, y] == 0 || matrix[x,    y-1] == 0 || matrix[x, y+1] == 0) { … if (matrix[x, y] == 0 || matrix[x-1, y] == 0 ||        matrix[x+1, y] == 0 || matrix[x, y-1] == 0 ||        matrix[x, y+1] == 0) { … DictionaryEntry<K, V> newEntry    = new DictionaryEntry<K, V>(oldEntry   .Key, oldEntry.Value);
Alignments All types of alignments are considered harmful Alignments are hard-to-maintain! Incorrect examples: 65 DateTime      date     = DateTime.Now.Date; int           count    = 0; Student       student  = new Strudent(); List<Student> students = new List<Student>(); matrix[x, y]                 == 0; matrix[x + 1, y + 1]         == 0; matrix[2 * x + y, 2 * y + x] == 0; matrix[x * y, x * y]         == 0;
High-Quality Classes How to Design High-Quality Classes? Abstraction, Cohesion and Coupling
High-Quality Classes: Abstraction Present a consistent level of abstraction in the class contract (publicly visible members) What abstraction the class is implementing? Does it represent only one thing? Does the class name well describe its purpose? Does the class define clear and easy to understand public interface? Does the class hide all its implementation details? 67
Good Abstraction – Example 68 public class Font {   public string Name { get; set; }   public float SizeInPoints { get; set; }   public FontStyle Style { get; set; }   public Font(string name, float sizeInPoints,  FontStyle style)   {     this.Name = name;     this.SizeInPoints = sizeInPoints;     this.Style = style;   }   public void DrawString(DrawingSurface surface,      string str, int x, int y) { ... }   public Size MeasureString(string str)  { ... } }
Bad Abstraction – Example 69 public class Program {   public string title;   public int size;   public Color color;   public void InitializeCommandStack();   public void PushCommand(Command command);   public Command PopCommand();   public void ShutdownCommandStack();   public void InitializeReportFormatting();   public void FormatReport(Report report);   public void PrintReport(Report report);   public void InitializeGlobalData();   public void ShutdownGlobalData(); } Does this class really represent a "program"? Is this name good? Does this class really have a single purpose?
Establishing Good Abstraction Define operations along with their opposites Example: Open() and Close() Move unrelated methods in another class Example: In class Employee if you need to calculate Age by given DateOfBirth ,[object Object],70
Establishing Good Abstraction (2) Beware of breaking the interface abstraction due to evolution Don't add public members inconsistent with class abstraction Example: in class called Employee at some time we add method for accessing the DB with SQL 71 class Employee {   public string firstName;   public string lastName;   …   public SqlCommand FindByPrimaryKeySqlCommand(int id); }
Encapsulation Minimize the visibility of classes and members Start from private and move to internal, protected and public if required Classes should hide their implementation details Anything which is not part of the class interface should be declared private Classes with good encapsulated classes are: less complex, easier to maintain, more loosely coupled Never declare fields public (except constants) Use methods or properties to access fields 72
Encapsulation (2) Don't violate encapsulation semantically! Don't rely on non-documented internal behavior or side effects Wrong example:  Skip calling ConnectToDB() because you just called FindEmployeeById() which should open connection Another wrong example: Use String.Empty instead of Titles.NoTitle because you know both values are the same 73
Inheritance Don't hide methods in a subclass Example: if the class Timer has private method Start(), don't define Start() in AtomTimer Move common interfaces, data, and behavior as high as possible in the inheritance tree This maximizes the code reuse Be suspicious of base classes of which there is only one derived class Do you really need this additional level of inheritance? 74
Inheritance (2) Be suspicious of classes that override a routine and do nothing inside Is the overridden routine used correctly? Avoid deep inheritance trees Don't create more than 6 levels of inheritance Avoid using a base class’s protected data fields in a derived class Provide protected accessor methods or properties instead 75
Inheritance (3) Prefer inheritance to extensive type checking: Consider inheriting Circle and Square from Shape and override the abstract action Draw() 76 switch (shape.Type) {   case Shape.Circle:     shape.DrawCircle();     break;   case Shape.Square:     shape.DrawSquare();     break;   ... }
Class Methods and Data Keep the number of methods in a class as small as possible  reduce complexity Minimize direct method calls to other classes Minimize indirect method calls to other classes Less external method calls == less coupling Minimize the extent to which a class collaborates with other classes Reduce coupling between classes 77
Class Constructors Initialize all member data in all constructors, if possible Uninitialized data is error prone Partially initialized data is even more evil Incorrect example: assign FirstName in class Person but leave LastName empty Initialize data members in the same order in which they are declared Prefer deep copies to shallow copies (ICloneable should make deep copy) 78
Use Design Patterns Use private constructor to prohibit direct class instantiation Use deign patterns for common design situations Creational patterns like singleton, factory method, abstract factory Structural patterns like adapter, bridge, composite, decorator, façade Behavioral patterns like command, iterator, observer, strategy, template method 79
Top Reasons to Create Class Model real-world objects with OOP classes Model abstract objects, processes, etc. Reduce complexity Work at higher level Isolate complexity Hide it in a class Hide implementation details  encapsulation Limit effects of changes Changes affect only their class 80
Top Reasons to Create Class (2) Hide global data Work through methods Group variables that are used together Make central points of control Single task should be done at single place Avoid duplicating code Facilitate code reuse Use class hierarchies and virtual methods Package related operations together 81
Namespaces Group related classes together in namespaces Follow consistent naming convention 82 namespace Utils {  class MathUtils { … }  class StringUtils { … } } namespace DataAccessLayer {  class GenericDAO<Key, Entity> { … }  class EmployeeDAO<int, Employee> { … }  class AddressDAO<int, Address> { … } }
High-Quality Methods How to Design and Implement High-Quality Methods? Understanding Cohesion and Coupling
Why We Need Methods? Methods are important in			 software development Reduce complexity Divide and conquer: complex problems can be split into composition of several simple ones Improve code readability Small methods with good method names make the code self-documenting Avoid duplicating code Duplicating code is hard to maintain 84
Why We Need Methods? (2) Methods simplify software development Hide implementation details Complex logic is encapsulated and hidden behind a simple interface Algorithms and data structures are hidden and can be transparently replaced later Increase the level of abstraction Methods address the business problem, not the technical implementation: 85 Bank.accounts[customer].deposit(500);
Using Methods: Fundamentals Fundamental principle of correct method usage: Methods should do exactly what their names say Nothing less Nothing more In case of incorrect input or incorrect preconditions, an error should be indicated 86 A method should do what its name says or should indicate an error. Any other behaviour is incorrect!
Good Methods – Examples 87 long Sum(int[] elements) {   long sum = 0;   foreach (int element in elements)   {       sum = sum + element;   }   return sum; } double CalcTriangleArea(double a, double b, double c) {   if (a <= 0 || b <= 0 || c <= 0)   {     throw new ArgumentException(     "Sides should be positive.");   }   double s = (a + b + c) / 2;   double area = Math.Sqrt(s * (s - a) * (s - b) * (s - c));   return area; }
Symptoms of Wrong Methods Method that does something different than its name says, is wrong for one of these reasons: The returned result is incorrect  bug The returned output is incorrect when its input is incorrect or unusual  low quality Acceptable for private methods only The method does too many things                    bad cohesion The method has side effects  spaghetti code Method returns strange value when an error condition happens  it should indicate the error 88
Wrong Methods – Examples 89 long Sum(int[] elements) {   long sum = 0;   for (int i = 0; i < elements.Length; i++)   {     sum = sum + elements[i];     elements[i] = 0;   }   return sum; } Hidden side effect double CalcTriangleArea(double a, double b, double c) {   if (a <= 0 || b <= 0 || c <= 0)   {     return 0;   }   double s = (a + b + c) / 2;   double area = Math.Sqrt(s * (s - a) * (s - b) * (s - c));   return area; } Incorrect result. Throw an exception instead.
Strong Cohesion Methods should have strong cohesion Should address single task and address it well Should have clear intent Methods that  address several tasks in the same time are hard to be named String cohesion is used in engineering In computer hardware any PC component solves a single task E.g. hard disk performs a single task – storage 90
Acceptable Types of Cohesion Functional cohesion(independent function) Method performs certain well-defined calculation and returns a single result The entire input is passed through parameters and the entire output is returned as result No external dependencies or side effects Examples: 91 Math.Sqrt(value)  square root Char.IsLetterOrDigit(ch) String.Substring(str, startIndex, length)
Acceptable Types of Cohesion (2) Sequential cohesion(algorithm) Method performs certain sequence of operations to perform a single task and achieve certain result It encapsulates an algorithm Example: Connect to mail server Send message headers Send message body Disconnect from the server 92 SendEmail(recipient, subject, body)
Acceptable Types of Cohesion (3) Communicational cohesion(common data) A set of operations used to process certain data and produce a result Example: Retrieve input data from database Perform internal calculations over retrieved data Build the report Format the report as Excel worksheet Display the Excel worksheet on the screen 93 DisplayAnnualExpensesReport(int employeeId)
Acceptable Types of Cohesion (4) Temporal cohesion (time related activities) Operations that are generally not related but need to happen in a certain moment Examples: Load user settings Check for updates Load all invoices from the database Sequence of actions to handle the event 94 InitializeApplication() ButtonConfirmClick()
Unacceptable Cohesion Logical cohesion Performs a different operation depending on an input parameter Incorrect example: Can be acceptable in event handlers (e.g. the KeyDown event in Windows Forms) 95 object ReadAll(int operationCode) {   if (operationCode == 1) … // Read person name   else if (operationCode == 2) … // Read address   else if (operationCode == 3) … // Read date   … }
Unacceptable Cohesion Coincidental cohesion (spaghetti) Not related (random) operations are grouped in a method for unclear reason Incorrect example: Prepares annual incomes report for given customer Sorts an array of integers in increasing order Calculates the square root of given number Converts given MP3 file into WMA format Sends email to given customer 96 HandleStuff(customerId, int[], ref sqrtValue,   mp3FileName, emailAddress)
Loose Coupling What is loose coupling? Minimal dependences of the method on the other parts of the source code Minimal dependences on the class members or external classes and their members No side effects If the coupling is loose, we can easily reuse a method or group of methods in a new project Tight coupling  spaghetti code 97
Loose Coupling (2) The ideal coupling A methods depends only on its parameters Does not have any other input or output Example: Math.Sqrt Real world Complex software cannot avoid coupling but could make it as loose as possible Example: complex encryption algorithm performs initialization, encryption, finalization 98
Coupling – Example Intentionally increased coupling for more flexibility (.NET cryptography API): 99 byte[] EncryptAES(byte[] inputData, byte[] secretKey) {   Rijndael cryptoAlg = new RijndaelManaged();   cryptoAlg.Key = secretKey;   cryptoAlg.GenerateIV();   MemoryStream destStream = new MemoryStream();   CryptoStream csEncryptor = new CryptoStream(     destStream, cryptoAlg.CreateEncryptor(),     CryptoStreamMode.Write);   csEncryptor.Write(inputData, 0, inputData.Length);   csEncryptor.FlushFinalBlock();   byte[] encryptedData = destStream.ToArray();   return encryptedData; }
Loose Coupling – Example To reduce coupling we can make utility classes that hide the complex logic and provide simple straightforward interface (a.k.a. façade): 100 byte[] EncryptAES(byte[] inputData, byte[] secretKey) {   MemoryStream inputStream =     new MemoryStream(inputData);   MemoryStream outputStream = new MemoryStream();   EncryptionUtils.EncryptAES(     inputStream, outputStream, secretKey);   byte[] encryptedData = outputStream.ToArray();   return encryptedData; }
Tight Coupling – Example Passing parameters through class fields Typical example of tight coupling Don't do this unless you have a good reason! 101 class Sumator {   public int a, b;   int Sum()   {     return a + b;   }   static void Main()   {     Sumator sumator = new Sumator() { a = 3, b = 5 };     Console.WriteLine(sumator.Sum());   } } Why don't pass the numbers as parameters?
Loose Coupling and OOP Reducing coupling with OOP techniques Abstraction Define a public interface and hide the implementation details Encapsulation Make methods and fields private unless they are definitely needed Define new members as private Increase visibility as soon as this is needed 102
Acceptable Coupling Method is coupled to its parameters This is the best type of coupling Method in a class is coupled to some class fields This coupling is usual, do not worry too much Method in a class is coupled to static methods, properties or constants in external class This is normal, usually is not a problem Method is coupled to external static fields Avoid this, classes should keep their fields private 103
Non-Acceptable Coupling Method in a class is coupled to static fields in external class Avoid it  consider refactoring Methods take as input data some fields that could be passed as parameters Check the intent of the method Is it designed to process internal class data or is utility method Method is defined public without being part of the public class's interface  possible coupling 104
Methods Parameters Put most important parameters first First put the main input parameters Put non-important optional parameters last Example: Incorrect examples: 105 void RegisterUser(string username, string password,   Date accountExpirationDate, Role[] roles) void RegisterUser(Role[] roles, string password,   string username, Date accountExpirationDate) void RegisterUser(string password, Date   accountExpirationDate, Role[] roles, string username)
Methods Parameters (2) Do not modify the input parameters Use new variable instead Incorrect example: Correct example: 106 bool CheckLogin(string username, string password) {   username = username.ToLower();   … // Check the username / password here } bool CheckLogin(string username, string password) {   string usernameLowercase = username.ToLower();   … // Check the username / password here }
Methods Parameters (3) Use parameters consistently Use the same names and the same order in all methods Incorrect example: Output parameters should be put last 107 void EncryptFile(Stream input, Stream output, string key); void DecryptFile(string key, Stream output, Stream input); FindCustomersAndIncomes(Region region,   out Customer[] customers, out decimal[] incomes)
Pass Entire Object or Its Fields? When should we pass an object containing few values and when these values separately? Sometime we pass an object and use only a single field of it – it is a good practice? Examples: Look at the method's level of abstraction Is it intended to operate with employees of with rates and months?  the first is incorrect 108 CalculateSalary(Employee employee, int months); CalculateSalary(double rate, int months);
How Much Parameters Methods Should Have? Limit the number of method parameters to 7 (+/-2) 7 is a magic number in psychology Human brain cannot process more than 7 (+/-2) things in the same time If the parameters need to be too much reconsider the method intent  does it have clear intent? Consider putting few parameters in a new class 109
Methods Length How long should a method be? There is no specific restriction Avoid methods longer than one screen (30 lines) Long methods are not always bad Be sure you have a good reason for their length Cohesion and coupling are more important than the method length! Long methods often contain portions that could be extracted as separate methods with good name and clear intent  check this! 110
Using Variables Best Practices
Retuning Result from a Method Always assign the result of a method in some variable before returning it. Benefits: Improved code readability The returned value has self-documenting name Simplified debugging Example: Incorrect example: 112 The intent of the formula is obvious int salary = days * hoursPerDay * ratePerHour; return salary; We can put a breakpoint at this line and check if the result is correct return days * hoursPerDay * ratePerHour;
Variable Initialization Initialize all variables before their first usage Class variables (fields) are automatically initialized with 0 / null by the C# compiler You still get a warning message Local variables should be manually initialized This C# code will result in compilation error: We can initialize variables at their declaration: 113 int value; Console.WriteLine(value); int value = 0; Console.WriteLine(value);
Partially Initialized Objects Ensure objects cannot get into partially initialized state Make all fields private and require valid values for all mandatory fields in all constructors Example: Student object is invalid unless it has Name and FacultyNumber 114 class Student {   private string name, facultyNumber;   public Student(string name, string facultyNumber)   { … } }
Variable Scope Variable scope defines how "famous" is a variable in the program Static variables are more "famous" than instance variables, and they are more "famous" than local Variables' visibility is directly related to their scope public, protected, internal, private Always try to reduce the variable's scope This reduces potential coupling Avoid public fields (exception: readonly / const) Access all fields through properties / methods 115
Exceeded Scope – Example 116 public class Globals {   public static int state = 0; } public class Genious  {   public static void PrintSomething()   {     if (Globals.state == 0)     {       Console.WriteLine("Hello.");     }     else     {       Console.WriteLine("Good bye.");     }   } }
Variable Span and Lifetime Variable span The average number of lines of code (LOC) between variable usages Variable lifetime The number of lines of code (LOC) between the first and the last variable usage in a block Keep variable span and lifetime as low as possible 117 Always define and initialize variables just before their first use and never before it!
Unneeded Large Variable Span and Lifetime int count; int[] numbers = new int[100]; for (int i = 0; i < numbers.Length; i++) {   numbers[i] = i; } count = 0; for (int i = 0; i < numbers.Length / 2; i++) {   numbers[i] = numbers[i] * numbers[i]; } for (int i = 0; i < numbers.Length; i++) {   if (numbers[i] % 3 == 0)   {     count++;   } } Console.WriteLine(count); 118 lifetime ("count") = 19 span = 19 / 4 =  4.75
Reduced Variable Span and Lifetime 119 int[] numbers = new int[100]; for (int i = 0; i < numbers.Length; i++) {   numbers[i] = i; } for (int i = 0; i < numbers.Length / 2; i++) {   numbers[i] = numbers[i] * numbers[i]; } int count = 0; for (int i = 0; i < numbers.Length; i++) {   if (numbers[i] % 3 == 0)   {     count++;   } } Console.WriteLine(count); lifetime = 9 span= 9 / 3 = 3
Single Purpose Variables should have single purpose Never use a single variable for multiple purposes! Economizing memory is not an excuse Can you choose a good name for variable that is used for several purposes? Example: variable used to count students of to keep the average of their grades Proposed name: studentsCountOrAvgGrade 120
Variables – Other Suggestions Don't define variables that are not used Compilers usually issues warnings Don't use variables with hidden purpose Incorrect example: Instead use enumeration: 121 int mode = 1; … if (mode == 1) …; // Read if (mode == 2) …; // Write if (mode == 3) …; // Read and write enum ResourceAccessMode { Read, Write, ReadWrite }
Using Expressions Best Practices
Avoid Complex Expressions Never use complex expressions in the code! Incorrect example: Complex expressions are evil because: Make code hard to read and understand, hard to debug, hard to modify and hard to maintain 123 What shall we do if we get at this line IndexOutOfRangeException? for (int i=0; i<xCoords.length; i++) {   for (int j=0; j<yCoords.length; j++) {     matrix[i][j] =        matrix[xCoords[findMax(i)+1]][yCoords[findMin(j)-1]] *       matrix[yCoords[findMax(j)+1]][xCoords[findMin(i)-1]];   } } There are 10 potential sources of IndexOutOfRangeException in this expression!
Simplifying Complex Expressions 124 for (int i = 0; i < xCoords.length; i++) {   for (int j = 0; j < yCoords.length; j++)   {     int maxStartIndex = findMax(i) + 1;     int minStartIndex = findMin(i) - 1;     int minXcoord = xCoords[minStartIndex];     int maxXcoord = xCoords[maxStartIndex];     int minYcoord = yCoords[minStartIndex];     int maxYcoord = yCoords[maxStartIndex];     int newValue =        matrix[maxXcoord][minYcoord] *       matrix[maxYcoord][minXcoord];     matrix[i][j] = newValue;   } }
Using Constants When and How to Use Constants?
Avoid Magic Numbers and Strings What is magic number or value? Magic numbers / values are all literals different than 0, 1, -1, null and "" (empty string) Avoid using magic numbers / values They are hard to maintain When change occurs, you need to modify all occurrences of the magic number / constant Their meaning is not obvious Example: what does the number 1024 mean? 126
The Evil Magic Numbers 127 public class GeometryUtils {   public static double CalcCircleArea(double radius)   {     double area = 3.14159206 * radius * radius;     return area;   }   public static double CalcCirclePerimeter(double radius)   {     double perimeter = 6.28318412 * radius;     return perimeter;   }   public static double CalcElipseArea(double axis1, double axis2)   {     double area = 3.14159206 * axis1 * axis2;     return area;   } }
Turning MagicNumbers into Constants 128 public class GeometryUtils {   public const double PI = 3.14159206;   public static double CalcCircleArea(double radius)   {     double area = PI * radius * radius;     return area;   }   public static double CalcCirclePerimeter(double radius)   {     double perimeter = 2 * PI * radius;     return perimeter;   }   public static double CalcElipseArea(    double axis1, double axis2)   {     double area = PI * axis1 * axis2;     return area;   } }
When to Use Constants? Constants should be used in the following cases: When we need to use numbers or other values and their logical meaning and value are not obvious File names Mathematical constants Bounds and ranges 129 public const string SettingsFileName =   "ApplicationSettings.xml"; public const double E = 2.7182818284; public const int READ_BUFFER_SIZE = 5 * 1024 *1024;
When to Avoid Constants? Sometime it is better to keep the magic values instead of using a constant Error messages and exception descriptions SQL commands for database operations Titles of GUI elements (labels, buttons, menus, dialogs, etc.) For internationalization purposes use resources, not constants 130
Using Control Constructs Using Conditional Statements and Loops Correctly
Using Conditional Statements Always use { and } for the conditional statements body, even when it is a single line: Why omitting the brackets could be harmful? This is misleading code + misleading formatting 132 if (condition) {   DoSometing(); } if (condition)   DoSomething();   DoAnotherThing(); DoDifferentThing();
Use Simple Conditions Do not use complex if conditions You can always simplify them by introducing boolean variables or boolean methods Incorrect example: Complex boolean expressions are harmful How you will find the problem if you get IndexOutOfRangeException? 133 if (x > 0 && y > 0 && x < Width-1 && y < Height-1 &&   matrix[x, y] == 0 && matrix[x-1, y] == 0 &&   matrix[x+1, y] == 0 && matrix[x, y-1] == 0 &&   matrix[x, y+1] == 0 && !visited[x, y])
Simplifying Boolean Conditions The last example can be easily refactored into self-documenting code: Now the code is: Easy to read – the logic of the condition is clear Easy to debug – breakpoint can be put at the if 134 bool inRange =    x > 0 && y > 0 && x < Width-1 && y < Height-1; bool emptyCellAndNeighbours =   matrix[x, y] == 0 && matrix[x-1, y] == 0 &&   matrix[x+1, y] == 0 && matrix[x, y-1] == 0 &&   matrix[x, y+1] == 0; if (inRange && emptyCellAndNeighbours && !visited[x, y])
Avoid Deep Nesting of Blocks Deep nesting of conditional statements and loops makes the code unclear Deeply nested code is complex and hard to read and understand Usually you can extract portions of the code in separate methods This simplifies the logic of the code Using good method name makes the code self-documenting 135
Deep Nesting – Example 136 if (maxElem != Int32.MaxValue) {   if (arr[i] < arr[i + 1])   {     if (arr[i + 1] < arr[i + 2])     {       if (arr[i + 2] < arr[i + 3])       {         maxElem = arr[i + 3];       }       else       {         maxElem = arr[i + 2];       }     }     else     {       if (arr[i + 1] < arr[i + 3])       {         maxElem = arr[i + 3];       }       else       {         maxElem = arr[i + 1];       }     }   } (continues on the next slide)
Deep Nesting – Example (2) 137   else   {     if (arr[i] < arr[i + 2])     {       if (arr[i + 2] < arr[i + 3])       {         maxElem = arr[i + 3];       }       else       {         maxElem = arr[i + 2];       }     }     else     {       if (arr[i] < arr[i + 3])       {         maxElem = arr[i + 3];       }       else       {         maxElem = arr[i];       }     }   } }
Avoiding Deep Nesting – Example 138 private static int Max(int i, int j) {   if (i < j)   {     return j;   }   else   {     return i;   } } private static int Max(int i, int j, int k) {   if (i < j)   {     int maxElem = Max(j, k);     return maxElem;   }   else   {     int maxElem = Max(i, k);     return maxElem;   } } (continues on the next slide)
Avoiding Deep Nesting – Example 139 private static int FindMax(int[] arr, int i) {   if (arr[i] < arr[i + 1])   {     int maxElem = Max(arr[i + 1], arr[i + 2], arr[i + 3]);     return maxElem;   }   else   {     int maxElem = Max(arr[i], arr[i + 2], arr[i + 3]);     return maxElem;   } } if (maxElem != Int32.MaxValue) {   maxElem = FindMax(arr, i); }
Using Case Statement Choose the most effective ordering of cases Put the normal (usual) case first Order cases by frequency Put the most unusual (exceptional) case last Order cases alphabetically or numerically Keep the actions of each case simple Extract complex logic in separate methods Use the default clause in a casestatement or the last elsein a chain of if-else to trap errors 140
Bad Case Statement 141 void ProcessNextChar(char ch) {   switch (parseState)   {     InTag:       if (ch == ">")       {         Console.WriteLine("Found tag: {0}", tag);         text = "";         parseState = ParseState.OutOfTag;       }       else       {         tag = tag + ch;       }       break;     OutOfTag:       …   } }
Improved Case Statement 142 void ProcessNextChar(char ch) {   switch (parseState)   {     InTag:       ProcessCharacterInTag(ch);       break;     OutOfTag:       ProcessCharacterOutOfTag(ch);       break;     default:       throw new Exception("Invalid parse state: " +         parseState);   } }
Using Loops Choosing the correct type of loop: Use for loop to repeat some block of code a certain number of times Use foreach loop to process each element of array or collection Use while / do-while loop when you don't know how many times a block should be repeated Avoid deep nesting of loops You can extract the loop body in a new method 143
Loops: Best Practices Keep loops simple This helps readers of your code Treat the inside of the loop as it were a routine Don’t make the reader look inside the loop to understand the loop control Think of a loop as a black box: 144 while (!inputFile.EndOfFile() && !hasErrors) { } (black box code)
Defensive Programming Using Assertions and Exceptions Correctly
Principles of Defensive Programming Fundamental principle of defensive programming Defensive programming means: To expect incorrect input and to handle it correctly To think not only about the usual execution flow, but to consider also unusual situations To ensure that incorrect input results to exception, not to incorrect output 146 Any public method should check its input data, preconditions and postconditions
Defensive Programming – Example 147 string Substring(string str, int startIndex, int length) {   if (str == null)   {     throw new NullReferenceException("Str is null.");   }   if (startIndex >= str.Length)   {     throw new ArgumentException(       "Invalid startIndex:" + startIndex);   }   if (startIndex + count > str.Length)   {     throw new ArgumentException("Invalid length:" + length);   }   …   Debug.Assert(result.Length == length); } Check the input and preconditions. Perform the method main logic. Check the postconditions.
Exceptions – Best Practices Choose a good name for your exception class Incorrect example: Example: Use descriptive error messages Incorrect example: Example: 148 throw new Exception("File error!"); throw new FileNotFoundException("Cannot find file " + fileName); throw new Exception("Error!"); throw new ArgumentException("The speed should be a number " +   "between " + MIN_SPEED + " and " + MAX_SPEED + ".");
Exceptions Handling Best Practices (2) Catch only exceptions that you are capable to process correctly Do not catch all exceptions! Incorrect example: What about OutOfMemoryException? 149 try {   ReadSomeFile(); } catch {   Console.WriteLine("File not found!"); }
Exceptions Handling Best Practices (3) Always include the exception cause when throwing a new exception 150 try {   WithdrawMoney(account, amount); } catch (DatabaseException dbex) {   throw new WithdrawException(String.Format(     "Can not withdraw the amount {0} from acoount {1}",     amount, account), dbex); } We include in the exceptions chain the original source of the problem.
Exceptions Handling Best Practices (4) Throw exceptions at the corresponding level of abstraction Example: Bank account withdrawal operation could throw InsufficientFundsException but cannot throw FileAccessDeniedException Display to the end users only messages that they could understand 151 or
Disposable Resources Handle disposable resources with care All classes implementing IDisposable should follow the try-finally / using pattern: 152 StreamReader reader =    new StreamReader("file.txt"); try {    String line = reader.ReadLine();  } finally {   reader.Close(); } StreamReader reader =    new StreamReader(     "file.txt"); using (reader) {    String line =     reader.ReadLine();  } ==
Comments and Code Documentation The Concept of Self-Documenting Code
Effective Comments Effective comments do not repeat the code They explain it at higher level and reveal non-obvious details The best software documentation is the source code itself – keep it clean and readable Self-documenting code is code that is self-explainable and does not need comments Simple design, small well named methods, strong cohesion and loose coupling, simple logic, good variable names, good formatting, …  154
Self-Documenting Code Self-documenting code fundamental principles 155 The best documentation is the code itself.  Make the code self-explainable and self-documenting, easy to read and understand. Do not document bad code, rewrite it!
Bad Comments – Example 156 public static List<int> FindPrimes(int start, int end) {     // Create new list of integers     List<int> primesList = new List<int>();     // Perform a loop from start to end     for (int num = start; num <= end; num++)     {         // Declare boolean variable, initially true         bool prime = true;         // Perform loop from 2 to sqrt(num)         for (int div = 2; div <= Math.Sqrt(num); div++)         {             // Check if div divides num with no remainder              if (num % div == 0)             {                 // We found a divider -> the number is not prime                 prime = false;                 // Exit from the loop                 break;             } (continues on the next slide)
Bad Comments – Example (2) 157           // Continue with the next loop value         }         // Check if the number is prime         if (prime)         {             // Add the number to the list of primes             primesList.Add(num);         }     }     // Return the list of primes     return primesList; }
Self-Documenting Code – Example 158 public static List<int> FindPrimes(int start, int end) {   List<int> primesList = new List<int>();   for (int num = start; num <= end; num++)   {     bool isPrime = IsPrime(num);     if (isPrime)     {       primesList.Add(num);     }   }   return primesList; } Good code does not need comments. It is self-explaining. (continues on the next slide)
Self-Documenting Code –Example (2) 159 private static bool IsPrime(int num) {   bool isPrime = true;   int maxDivider = Math.Sqrt(num);   for (int div = 2; div <= maxDivider; div++)   {     if (num % div == 0)     {       // We found a divider -> the number is not prime       isPrime = false;       break;     }   }   return isPrime; } Good methods have good name and are easy to read and understand. This comment explain non-obvious details. It does not repeat the code.
Code Refactoring Improving the Quality of the Existing Code
Code Refactoring What is refactoring of the source code? Improving the design and quality of existing source code without changing its behavior Step by step process that turns the bad code into good code (if possible) Why we need refactoring? Code constantly changes and its quality constantly degrades (unless refactored) Requirements often change and code needs to be changed to follow them 161
Rafactoring Patterns When should we perform refactoring of the code? Bad smells in the code indicate need of refactoring Unit tests guarantee that refactoring does not change the behavior Rafactoring patterns Large repeating code fragments  extract repeating code in separate method Large methods  split them logically Large loop body or deep nesting  extract method 162
Rafactoring Patterns (2) Refactoring patterns Class or method has weak cohesion  split into several classes / methods Single change carry out changes in several classes  classes have tight coupling  consider redesign Related data are always used together but are not part of a single class  group them in a class A method has too many parameters  create a class to groups parameters together A method calls more methods from another class than from its own class  move it 163
Rafactoring Patterns (3) Refactoring patterns Two classes are tightly coupled  merge them or redesign them to separate their responsibilities Public non-constant fields  make them private and define accessing properties Magic numbers in the code  consider extracting constants Bad named class / method / variable  rename it Complex boolean condition  split it to several expressions or method calls 164
Rafactoring Patterns (4) Refactoring patterns Complex expression  split it into few simple parts A set of constants is used as enumeration  convert it to enumeration Method logic is too complex and is hard to understand  extract several more simple methods or even create a new class Unused classes, methods, parameters, variables  remove them Large data is passed by value without a good reason  pass it by reference 165
Rafactoring Patterns (5) Refactoring patterns Few classes share repeating functionality  extract base class and reuse the common code Different classes need to be instantiated depending on configuration setting  use factory Code is not well formatted  reformat it Too many classes in a single namespace  split classes logically into more namespaces Unused using definitions  remove them Non-descriptive error messages  improve them Absence of defensive programming  add it 166
Refactoring of Bad Code Live Demo
Resources The bible of high-quality software construction: 168 ,[object Object]
http://codecourse.telerik.comCode Complete, 2nd edition, Steve McConnell, Microsoft Press, 2004, ISBN 0735619670, http://www.cc2e.com

More Related Content

What's hot

Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Asim Rais Siddiqui
 
Clean Code Principles
Clean Code PrinciplesClean Code Principles
Clean Code PrinciplesYeurDreamin'
 
Coding Best Practices
Coding Best PracticesCoding Best Practices
Coding Best Practicesmh_azad
 
Writing clean code in C# and .NET
Writing clean code in C# and .NETWriting clean code in C# and .NET
Writing clean code in C# and .NETDror Helper
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringEyob Lube
 
OOP Lecture 20-MultiThreading.pptx
OOP Lecture 20-MultiThreading.pptxOOP Lecture 20-MultiThreading.pptx
OOP Lecture 20-MultiThreading.pptxTanzila Kehkashan
 
Introduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita GanesanIntroduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita GanesanKavita Ganesan
 
JavaScript Control Statements I
JavaScript Control Statements IJavaScript Control Statements I
JavaScript Control Statements IReem Alattas
 
Constructors in java
Constructors in javaConstructors in java
Constructors in javachauhankapil
 
Structure of java program diff c- cpp and java
Structure of java program  diff c- cpp and javaStructure of java program  diff c- cpp and java
Structure of java program diff c- cpp and javaMadishetty Prathibha
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable codeGeshan Manandhar
 

What's hot (20)

Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#
 
Clean Code Principles
Clean Code PrinciplesClean Code Principles
Clean Code Principles
 
C# basics
 C# basics C# basics
C# basics
 
Templates
TemplatesTemplates
Templates
 
Coding Best Practices
Coding Best PracticesCoding Best Practices
Coding Best Practices
 
Writing clean code in C# and .NET
Writing clean code in C# and .NETWriting clean code in C# and .NET
Writing clean code in C# and .NET
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
 
Clean Code
Clean CodeClean Code
Clean Code
 
OOP Lecture 20-MultiThreading.pptx
OOP Lecture 20-MultiThreading.pptxOOP Lecture 20-MultiThreading.pptx
OOP Lecture 20-MultiThreading.pptx
 
Angular Directives
Angular DirectivesAngular Directives
Angular Directives
 
Introduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita GanesanIntroduction to Java Strings, By Kavita Ganesan
Introduction to Java Strings, By Kavita Ganesan
 
Java 8 lambda
Java 8 lambdaJava 8 lambda
Java 8 lambda
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
JavaScript Control Statements I
JavaScript Control Statements IJavaScript Control Statements I
JavaScript Control Statements I
 
Java String class
Java String classJava String class
Java String class
 
Coding standard
Coding standardCoding standard
Coding standard
 
Exception handling
Exception handlingException handling
Exception handling
 
Constructors in java
Constructors in javaConstructors in java
Constructors in java
 
Structure of java program diff c- cpp and java
Structure of java program  diff c- cpp and javaStructure of java program  diff c- cpp and java
Structure of java program diff c- cpp and java
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable code
 

Similar to Writing High Quality Code in C#

Agile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddAgile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddSrinivasa GV
 
21. High-Quality Programming Code
21. High-Quality Programming Code21. High-Quality Programming Code
21. High-Quality Programming CodeIntro C# Book
 
Advanced PowerShell Automation
Advanced PowerShell AutomationAdvanced PowerShell Automation
Advanced PowerShell Automationkieranjacobsen
 
Back-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldBack-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldDavid McCarter
 
Back-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldBack-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldDavid McCarter
 
Combating software entropy 2-roc1-
Combating software entropy 2-roc1-Combating software entropy 2-roc1-
Combating software entropy 2-roc1-Hammad Rajjoub
 
Dot Net Fundamentals
Dot Net FundamentalsDot Net Fundamentals
Dot Net FundamentalsLiquidHub
 
Top 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaTop 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaEdureka!
 
Thesis+of+laleh+eshkevari.ppt
Thesis+of+laleh+eshkevari.pptThesis+of+laleh+eshkevari.ppt
Thesis+of+laleh+eshkevari.pptPtidej Team
 
Best practices in enterprise applications
Best practices in enterprise applicationsBest practices in enterprise applications
Best practices in enterprise applicationsChandra Sekhar Saripaka
 

Similar to Writing High Quality Code in C# (20)

Code review
Code reviewCode review
Code review
 
Agile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddAgile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tdd
 
21. High-Quality Programming Code
21. High-Quality Programming Code21. High-Quality Programming Code
21. High-Quality Programming Code
 
Codings Standards
Codings StandardsCodings Standards
Codings Standards
 
Advanced PowerShell Automation
Advanced PowerShell AutomationAdvanced PowerShell Automation
Advanced PowerShell Automation
 
Back-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldBack-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real World
 
Back-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real WorldBack-2-Basics: .NET Coding Standards For The Real World
Back-2-Basics: .NET Coding Standards For The Real World
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Coding conventions
Coding conventionsCoding conventions
Coding conventions
 
Combating software entropy 2-roc1-
Combating software entropy 2-roc1-Combating software entropy 2-roc1-
Combating software entropy 2-roc1-
 
Dot Net Fundamentals
Dot Net FundamentalsDot Net Fundamentals
Dot Net Fundamentals
 
Abcxyz
AbcxyzAbcxyz
Abcxyz
 
Top 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | EdurekaTop 50 .NET Interview Questions and Answers 2019 | Edureka
Top 50 .NET Interview Questions and Answers 2019 | Edureka
 
csharp.docx
csharp.docxcsharp.docx
csharp.docx
 
Thesis+of+laleh+eshkevari.ppt
Thesis+of+laleh+eshkevari.pptThesis+of+laleh+eshkevari.ppt
Thesis+of+laleh+eshkevari.ppt
 
Best practices in enterprise applications
Best practices in enterprise applicationsBest practices in enterprise applications
Best practices in enterprise applications
 
Objc
ObjcObjc
Objc
 
Lecture No 13.ppt
Lecture No 13.pptLecture No 13.ppt
Lecture No 13.ppt
 
Bb Tequila Coding Style (Draft)
Bb Tequila Coding Style (Draft)Bb Tequila Coding Style (Draft)
Bb Tequila Coding Style (Draft)
 
Introduction to programming using c
Introduction to programming using cIntroduction to programming using c
Introduction to programming using c
 

More from Svetlin Nakov

BG-IT-Edu: отворено учебно съдържание за ИТ учители
BG-IT-Edu: отворено учебно съдържание за ИТ учителиBG-IT-Edu: отворено учебно съдържание за ИТ учители
BG-IT-Edu: отворено учебно съдържание за ИТ учителиSvetlin Nakov
 
Programming World in 2024
Programming World in 2024Programming World in 2024
Programming World in 2024Svetlin Nakov
 
AI Tools for Business and Startups
AI Tools for Business and StartupsAI Tools for Business and Startups
AI Tools for Business and StartupsSvetlin Nakov
 
AI Tools for Scientists - Nakov (Oct 2023)
AI Tools for Scientists - Nakov (Oct 2023)AI Tools for Scientists - Nakov (Oct 2023)
AI Tools for Scientists - Nakov (Oct 2023)Svetlin Nakov
 
AI Tools for Entrepreneurs
AI Tools for EntrepreneursAI Tools for Entrepreneurs
AI Tools for EntrepreneursSvetlin Nakov
 
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023Svetlin Nakov
 
AI Tools for Business and Personal Life
AI Tools for Business and Personal LifeAI Tools for Business and Personal Life
AI Tools for Business and Personal LifeSvetlin Nakov
 
Дипломна работа: учебно съдържание по ООП - Светлин Наков
Дипломна работа: учебно съдържание по ООП - Светлин НаковДипломна работа: учебно съдържание по ООП - Светлин Наков
Дипломна работа: учебно съдържание по ООП - Светлин НаковSvetlin Nakov
 
Дипломна работа: учебно съдържание по ООП
Дипломна работа: учебно съдържание по ООПДипломна работа: учебно съдържание по ООП
Дипломна работа: учебно съдържание по ООПSvetlin Nakov
 
Свободно ИТ учебно съдържание за учители по програмиране и ИТ
Свободно ИТ учебно съдържание за учители по програмиране и ИТСвободно ИТ учебно съдържание за учители по програмиране и ИТ
Свободно ИТ учебно съдържание за учители по програмиране и ИТSvetlin Nakov
 
AI and the Professions of the Future
AI and the Professions of the FutureAI and the Professions of the Future
AI and the Professions of the FutureSvetlin Nakov
 
Programming Languages Trends for 2023
Programming Languages Trends for 2023Programming Languages Trends for 2023
Programming Languages Trends for 2023Svetlin Nakov
 
IT Professions and How to Become a Developer
IT Professions and How to Become a DeveloperIT Professions and How to Become a Developer
IT Professions and How to Become a DeveloperSvetlin Nakov
 
GitHub Actions (Nakov at RuseConf, Sept 2022)
GitHub Actions (Nakov at RuseConf, Sept 2022)GitHub Actions (Nakov at RuseConf, Sept 2022)
GitHub Actions (Nakov at RuseConf, Sept 2022)Svetlin Nakov
 
IT Professions and Their Future
IT Professions and Their FutureIT Professions and Their Future
IT Professions and Their FutureSvetlin Nakov
 
How to Become a QA Engineer and Start a Job
How to Become a QA Engineer and Start a JobHow to Become a QA Engineer and Start a Job
How to Become a QA Engineer and Start a JobSvetlin Nakov
 
Призвание и цели: моята рецепта
Призвание и цели: моята рецептаПризвание и цели: моята рецепта
Призвание и цели: моята рецептаSvetlin Nakov
 
What Mongolian IT Industry Can Learn from Bulgaria?
What Mongolian IT Industry Can Learn from Bulgaria?What Mongolian IT Industry Can Learn from Bulgaria?
What Mongolian IT Industry Can Learn from Bulgaria?Svetlin Nakov
 
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)How to Become a Software Developer - Nakov in Mongolia (Oct 2022)
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)Svetlin Nakov
 
Blockchain and DeFi Overview (Nakov, Sept 2021)
Blockchain and DeFi Overview (Nakov, Sept 2021)Blockchain and DeFi Overview (Nakov, Sept 2021)
Blockchain and DeFi Overview (Nakov, Sept 2021)Svetlin Nakov
 

More from Svetlin Nakov (20)

BG-IT-Edu: отворено учебно съдържание за ИТ учители
BG-IT-Edu: отворено учебно съдържание за ИТ учителиBG-IT-Edu: отворено учебно съдържание за ИТ учители
BG-IT-Edu: отворено учебно съдържание за ИТ учители
 
Programming World in 2024
Programming World in 2024Programming World in 2024
Programming World in 2024
 
AI Tools for Business and Startups
AI Tools for Business and StartupsAI Tools for Business and Startups
AI Tools for Business and Startups
 
AI Tools for Scientists - Nakov (Oct 2023)
AI Tools for Scientists - Nakov (Oct 2023)AI Tools for Scientists - Nakov (Oct 2023)
AI Tools for Scientists - Nakov (Oct 2023)
 
AI Tools for Entrepreneurs
AI Tools for EntrepreneursAI Tools for Entrepreneurs
AI Tools for Entrepreneurs
 
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023
Bulgarian Tech Industry - Nakov at Dev.BG All in One Conference 2023
 
AI Tools for Business and Personal Life
AI Tools for Business and Personal LifeAI Tools for Business and Personal Life
AI Tools for Business and Personal Life
 
Дипломна работа: учебно съдържание по ООП - Светлин Наков
Дипломна работа: учебно съдържание по ООП - Светлин НаковДипломна работа: учебно съдържание по ООП - Светлин Наков
Дипломна работа: учебно съдържание по ООП - Светлин Наков
 
Дипломна работа: учебно съдържание по ООП
Дипломна работа: учебно съдържание по ООПДипломна работа: учебно съдържание по ООП
Дипломна работа: учебно съдържание по ООП
 
Свободно ИТ учебно съдържание за учители по програмиране и ИТ
Свободно ИТ учебно съдържание за учители по програмиране и ИТСвободно ИТ учебно съдържание за учители по програмиране и ИТ
Свободно ИТ учебно съдържание за учители по програмиране и ИТ
 
AI and the Professions of the Future
AI and the Professions of the FutureAI and the Professions of the Future
AI and the Professions of the Future
 
Programming Languages Trends for 2023
Programming Languages Trends for 2023Programming Languages Trends for 2023
Programming Languages Trends for 2023
 
IT Professions and How to Become a Developer
IT Professions and How to Become a DeveloperIT Professions and How to Become a Developer
IT Professions and How to Become a Developer
 
GitHub Actions (Nakov at RuseConf, Sept 2022)
GitHub Actions (Nakov at RuseConf, Sept 2022)GitHub Actions (Nakov at RuseConf, Sept 2022)
GitHub Actions (Nakov at RuseConf, Sept 2022)
 
IT Professions and Their Future
IT Professions and Their FutureIT Professions and Their Future
IT Professions and Their Future
 
How to Become a QA Engineer and Start a Job
How to Become a QA Engineer and Start a JobHow to Become a QA Engineer and Start a Job
How to Become a QA Engineer and Start a Job
 
Призвание и цели: моята рецепта
Призвание и цели: моята рецептаПризвание и цели: моята рецепта
Призвание и цели: моята рецепта
 
What Mongolian IT Industry Can Learn from Bulgaria?
What Mongolian IT Industry Can Learn from Bulgaria?What Mongolian IT Industry Can Learn from Bulgaria?
What Mongolian IT Industry Can Learn from Bulgaria?
 
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)How to Become a Software Developer - Nakov in Mongolia (Oct 2022)
How to Become a Software Developer - Nakov in Mongolia (Oct 2022)
 
Blockchain and DeFi Overview (Nakov, Sept 2021)
Blockchain and DeFi Overview (Nakov, Sept 2021)Blockchain and DeFi Overview (Nakov, Sept 2021)
Blockchain and DeFi Overview (Nakov, Sept 2021)
 

Recently uploaded

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 

Writing High Quality Code in C#

  • 1. High-Quality Programming Code Construction Revealing the Secrets of Self-Documenting Code http://schoolacademy.telerik.com For C# Developers Svetlin Nakov Telerik Corporation www.telerik.com
  • 2. Table of Contents What is High-Quality Programming Code? Naming Identifiers Naming classes, methods, variables, etc. Code Formatting Designing High-Quality Classes High-Quality Methods Cohesion and Coupling Using Variables Correctly Using Expressions Correctly 2
  • 3. Table of Contents (2) Using Constants Using Control-Flow Constructs Correctly Conditional Statements Loops Defensive Programming Assertions and Exceptions Comments and Documentation Code Refactoring 3
  • 4. What is High-Quality Programming Code?
  • 5. Why the Code Quality Is Important? static void Main() { int value=010, i=5, w; switch(value){case 10:w=5;Console.WriteLine(w);break;case 9:i=0;break; case 8:Console.WriteLine("8 ");break; default:Console.WriteLine("def ");{ Console.WriteLine("hoho "); } for (int k = 0; k < i; k++, Console.WriteLine(k - 'f'));break;} { Console.WriteLine("loop!"); } } What does this code do? Is it correct? 5
  • 6. Why the Code Quality Is Important? (2) static void Main() { int value = 010, i = 5, w; switch (value) { case 10: w = 5; Console.WriteLine(w); break; case 9: i = 0; break; case 8: Console.WriteLine("8 "); break; default: Console.WriteLine("def "); Console.WriteLine("hoho "); for (int k = 0; k < i; k++, Console.WriteLine(k -'f')); break; } Console.WriteLine("loop!"); } Now the code is formatted, but is still unclear. 6
  • 7. Software Quality External quality Does the software behave correctly? Are the produced results correct? Does the software runfast? Is the software UI easy-to-use? Internal quality It the code easy to read and understand? It the code well structured? Is the code easy to modify? 7
  • 8. What is High-Quality Programming Code? High-quality programming code: Easy to read and understand Easy to modify and maintain Correct behavior in all cases Well tested Well architectured and designed Well documented Self-documenting code Well formatted 8
  • 9. Code Conventions Code conventions are formal guidelines about the style of the source code: Code formatting conventions Indentation, whitespace, etc. Naming conventions PascalCase or camelCase, prefixes, suffixes, … Best practices Classes, interfaces, enumerations, structures, inheritance, exceptions, properties, events, constructors, fields, operators, etc. 9
  • 10. Code Conventions (2) Microsoft has official code conventions called Design Guidelines for Developing Class Libraries: http://msdn.microsoft.com/en-us/library/ms229042.aspx Large organizations follow strict conventions Code conventions can vary in different teams Most conventions developers follow the official Microsoft's recommendations but extend them High-quality code goes beyond code conventions Software quality is not just a set of conventions – its is a way of thinking 10
  • 11. Naming Identifiers Naming Classes, Interfaces, Enumerations, Methods, Variables and Constants
  • 12. General Naming Guidelines Always use English How you will feel if you read Vietnamese code with variables named in Vietnamese? English is the only language that all software developers speak Avoid abbreviations Example: scrpCnt vs. scriptsCount Avoid hard-to-pronounce names Example: dtbgRegExPtrn vs. dateTimeBulgarianRegExPattern 12
  • 13. Use Meaningful Names Always prefer using meaningful names Names should answer these questions: What does this class do? What is the intent of this variable? What is this variable / class used for? Examples: FactorialCalculator, studentsCount, Math.PI, configFileName, CreateReport Incorrect examples: k, k2,k3,junk,f33,KJJ,button1, variable, temp, tmp, temp_var, something, someValue 13
  • 14. Fake Meaningful Names Junior developers often use meaningful names that are in fact meaningless Bad naming examples: Topic6Exercise12, LoopsExercise12,Problem7, OOPLecture_LastExercise Yes, Topic6Exercise12 indicates that this is solution to exercise 12, but what is it about? Better naming: MaximalNumbersSubsequence 14
  • 15. Naming Types Naming types (classes, structures, etc.) Use PascalCase character casing Examples: RecursiveFactorialCalculator, TreeSet, XmlDocument, IEnumerable, Color, TreeNode, InvalidTransactionException, MainForm Incorrect examples: recursiveFactorialCalculator, recursive_factorial_calculator, RECURSIVE_FACTORIAL_CALCULATOR 15
  • 16. Naming Classes and Structures Use the following formats: [Noun] [Adjective] + [Noun] Examples: Student, FileSystem, BinaryTreeNode, Constants, MathUtils, TextBox, Calendar Incorrect examples: Move, FindUsers, Fast, Optimize, Extremly, FastFindInDatabase, Check 16
  • 17. Naming Interfaces Following formats are acceptable: 'I' + [Verb] + 'able' 'I' + [Noun], 'I' + [Adjective] + [Noun] Examples: IEnumerable, IFormattable, IDataReader, IList, IHttpModule, ICommandExecutor Incorrect examples: List, FindUsers, IFast, IMemoryOptimize, Optimizer, FastFindInDatabase, CheckBox 17
  • 18. Naming Enumerations Several formats are acceptable: [Noun] or [Verb] or [Adjective] Use the same style for all members Examples: enum Days {Monday, Tuesday, Wednesday, …}, enum AppState {Running, Finished, …} Incorrect examples: enum Color {red, green, blue, white}, enum PAGE_FORMAT {A4, A5, A3, LEGAL, …} 18
  • 19. Naming Special Classes Exceptions Add 'Exception' as suffix Use informative name Example: FileNotFoundException Incorrect example: FileNotFoundError Delegate Classes Add 'Delegate' or 'EventHandler' as suffix Example: DownloadFinishedDelegate Incorrect example: WakeUpNotification 19
  • 20. The Length of Class Names How long could be the name of a class / struct / interface / enum? The name should be as long as required Don't abbreviate the names if this could make them unclear Your IDE has autocomplete, right? Examples: FileNotFoundException, CustomerSupportNotificationService Incorrect examples: FNFException, CustSuppNotifSrvc 20
  • 21. Naming Projects / Folders Project naming guidelines Use PascalCase Following formats are preferable: ProductName Company [., -, _] ProductName Name project folders to match the project name / its component names Examples: Sitefinity, Telerik JustCode Incorrect example: ConsoleApplication17 21
  • 22. Naming Namespaces Namespaces naming guidelines Use PascalCase Following formats are acceptable: Company . Product . Component . … Product . Component . … Example: Telerik.WinControls.GridView Incorrect example: Telerik_WinControlsGridView, Classes 22
  • 23. Naming Assemblies Assembly names should follow the root namespace in its class hierarchy Examples: Telerik.WinControls.GridView.dll Oracle.DataAccess.dll Interop.CAPICOM.dll Incorrect examples: Telerik_WinControlsGridView.dll OracleDataAccess.dll 23
  • 24. Naming Methods Methods naming guidelines Method names should be meaningful Should answer the question: What does this method do? If you cannot find a good name for a method, think about does it have clear intent Examples: FindStudent, LoadReport, Sin Incorrect examples: Method1, DoSomething, HandleStuff, SampleMethod, DirtyHack 24
  • 25. Naming Methods (2) Use PascalCase character casing Example: LoadSettings, not loadSettings Prefer the following formats: [Verb] [Verb] + [Noun], [Verb] + [Adjective] + [Noun] Examples: Show, LoadSettingsFile, FindNodeByPattern, ToString, PrintList Incorrect examples: Student, Counter, White, Generator, Approximation, MathUtils 25
  • 26. Methods Returning a Value Methods returning values should describe the returned value Examples: ConvertMetersToInches, not MetersInches or Convert or ConvertUnit Meters2Inches is still acceptable CalculateSinis good Sin is still acceptable (like in the Math class) Ensure that the unit of measure of obvious Prefer MeasureFontInPixelsto MeasureFont 26
  • 27. Single Purpose of All Methods Methods should have a single purpose! Otherwise they cannot be named well How to name a method that creates annual incomes report, downloads updates from internet and scans the system for viruses? CreateAnnualIncomesReportDownloadUpdatesAndScanForViruses is a nice name, right? Methods that have multiple purposes (weak cohesion) are hard to be named Need to be refactored instead of named 27
  • 28. Consistency in Methods Naming Use consistent naming in the entire project LoadFile, LoadImageFromFile, LoadSettings, LoadFont, LoadLibrary, but not ReadTextFile Use consistently the opposites at the same level of abstraction: LoadLibrary vs. UnloadLibrary, but not FreeHandle OpenFile vs. CloseFile, but not DeallocateResource GetName vs. SetName, but not AssignName 28
  • 29. The Length of Method Names How long could be the name of a method? The name should be as long as required Don't abbreviate Your IDE has autocomplete Examples: LoadCustomerSupportNotificationService, CreateMonthlyAndAnnualIncomesReport Incorrect examples: LoadCustSuppSrvc, CreateMonthIncReport 29
  • 30. Naming Method Parameters Method parameters names Preferred form: [Noun] or [Adjective] + [Noun] Should be in camelCase Should be meaningful Unit of measure should be obvious Examples: firstName, report, usersList, fontSizeInPixels, speedKmH, font Incorrect examples: p, p1, p2, populate, LastName, last_name, convertImage 30
  • 31. Naming Variables Variable names Should be in camelCase Preferred form: [Noun] or [Adjective] + [Noun] Should explain the purpose of the variable If you can't find good name for a variable check if it has a single purpose Exception: variables with very small scope, e.g. the index variable in a 3-lines long for-loop Names should be consistent in the project 31
  • 32. Naming Variables – Examples Examples: firstName, report, usersList , fontSize, maxSpeed, font, startIndex, endIndex, charsCount, configSettingsXml, config, dbConnection, createUserSqlCommand Incorrect examples: foo, bar, p, p1, p2, populate, LastName, last_name, LAST_NAME, convertImage, moveMargin, MAXSpeed, _firstName, __temp, firstNameMiddleNameAndLastName 32
  • 33. More about Naming Variables The name should be addressed to the problem we solve, not to the means we use to solve it Prefer nouns from the business domain to computer terms Examples: accounts, customers, customerAddress, accountHolder, paymentPlan, vipPlayer Incorrect examples: accountsLinkedList, customersHashtable, paymentsPriorityQueue, playersArray 33
  • 34. Naming Boolean Variables Boolean variables should imply true or false Prefixes like is, has and can are useful Use positive boolean variable names Incorrect example: Examples: hasPendingPayment, customerFound, validAddress, positiveBalance, isPrime Incorrect examples: notFound, run, programStop, player, list, findCustomerById, isUnsuccessfull 34 if (! notFound) { … }
  • 35. Naming Special Variables Naming Counters Establish a convention, e.g. [Noun] + 'Count' Examples: ticketsCount, customersCount State Establish a convention, e.g. [Noun] + 'State' Examples: blogParseState, threadState Variables with small scope and span Short names can be used, e.g. index, i, u 35
  • 36. Temporary Variables Do really temporary variables exist? All variables in a program are temporary because they are used temporarily only during the program execution, right? Temporary variables can always be named better than temp or tmp: 36 // Swap a[i] and a[j] int temp = a[i]; a[i] = a[j]; a[j] = temp; // Swap a[i] and a[j] int swapValue = a[i]; a[i] = a[j]; a[j] = swapValue;
  • 37. The Length of Variable Names How long could be the name of a variable? Depends on the variable scope and lifetime More "famous" variables should have longer and more self-explaining name Acceptable naming examples: Unacceptable naming examples: 37 class Student { public string lastName; } for (int i=0; i<users.Length; i++) if (i % 2 == 0) sum += users[i].Weight; class Student { private int i; } class PairOfLists { public int Count { get; set; } }
  • 38. Prefixes / Suffixes and Hungarian Notation In C# prefix / suffix notations are not popular Hungarian notation Using prefixes to denote the variable types, e.g. lpcstrText, lpdwFlags, cbMultiByte, hWnd The Hungarian notation works well in unmanaged languages like C++ Do not use Hungarian notation in C# and .NET Don't use prefixes / suffixes to denote the variable data type 38
  • 39. Naming Properties Name properties in C# using a noun, noun phrase, or an adjective Use Pascal Case Examples: Incorrect examples: 39 public int Length { … } public Color BackgroundColor { … } public CacheMode CacheMode { … } public bool Loaded { … } public int Load { … } public Color BackgroundColor { … } public bool Font { … }
  • 40. Naming Constants Use CAPITAL_LETTERS for const fields and PascalCase for readonly fields Use meaningful names that describe their value Examples: Incorrect examples: 40 private const int READ_BUFFER_SIZE = 8192; public static readonly PageSize DefaultPageSize = PageSize.A4; private const int FONT_SIZE_IN_POINTS = 16; public const int MAX = 512; // Max what? Apples or Oranges? public const int BUF256 = 256; // What about BUF256 = 1024? public const string GREATER = "&gt;"; // GREATER_HTML_ENTITY public const int FONT_SIZE = 16; // 16pt or 16px? public const PageSize PAGE = PageSize.A4; // Maybe PAGE_SIZE?
  • 41. Names to Avoid Don't use numbers in the identifiers names Example: PrintReport and PrintReport2 What is the difference? Exceptions: When the number is part of the name itself, e.g. RS232Port, COM3, Win32APIFunctions Don't use Cyrillic or letters from other alphabets E.g. FindСтудентByName, CalcΩ2Protein 41
  • 42. Never Give a Misleading Name! Giving a misleading name is worse than giving a totally unclear name Example: Consider a method that calculates the sum of all elements in an array It should be named Sum or CalculateSum What about naming it CalculateAverageor Max or CheckForNegativeNumber? It's crazy, but be careful with "copy-paste" 42
  • 43. Don't Believe Microsoft! Microsoft sometimes use really bad naming in their API libraries (especially in Win32 API) Examples: Navigateand Navigate2methods in Internet Explorer ActiveX control (MSHTML.DLL) WNetAddConnection3method in Multiple Provider Router Networking API (MPR.DLL) LPWKSTA_USER_INFO_1structure in Win32 Don't follow them blindly, just think a bit! 43
  • 44. What's Wrong with This Code? 44 FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew); // Create the writer for data. BinaryWriter w = new BinaryWriter(fs); // Write data to Test.data. for (int i = 0; i < 11; i++) { w.Write( (int) i); } w.Close(); fs.Close(); // Create the reader for data. fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); // Read data from Test.data. for (int i = 0; i < 11; i++) { Console.WriteLine(r.ReadInt32()); } r.Close(); fs.Close(); Source: http://msdn.microsoft.com/en-us/library/36b93480.aspx
  • 45. Naming Should BeClear inside Its Context Naming should be clear inside its context Method names should be clear in their class Methods should not repeat their class name Parameter names should be clear in the context of their method name Example of good class / property naming: 45 class Font { public string Name { get; } // not FontName }
  • 46. Naming Should BeClear inside Its Context (2) Example of good method & parameter naming: Name like CalcDistanceBetweenPoints is excessive – parameters say "between points" Parameter names still can be improved: Name like Calc can still be correct: 46 double CalcDistance(Point p1, Point p2) { … } double CalcDistance(Point firstPoint, Point secondPoint) { … } class DistanceCalculator { static double Calc(Point p1, Point p1) { … } }
  • 47. Naming Should BeClear inside Its Context (3) Incorrect example of method naming: It is unclear in this context what kind of calculation is performed by the method Incorrect example of parameter naming: 47 class Program { int Calculation(int value) } What "f" means? An URL or FTP server or file path? class FileDownloader { byte[] Download(string f); }
  • 49. Why Code Needs Formatting? 49 public const string FILE_NAME ="example.bin" ; static void Main ( ){ FileStream fs= new FileStream(FILE_NAME,FileMode . CreateNew) // Create the writer for data . ;BinaryWriter w=new BinaryWriter ( fs );// Write data to Test.data. for( int i=0;i<11;i++){w.Write((int)i);}w .Close(); fs . Close ( ) // Create the reader for data. ;fs=new FileStream(FILE_NAME,FileMode. Open , FileAccess.Read) ;BinaryReader r = new BinaryReader(fs); // Read data from Test.data. for (int i = 0; i < 11; i++){ Console .WriteLine (r.ReadInt32 ()) ;}r . Close ( ); fs . Close ( ) ; }
  • 50. Code Formatting Fundamentals Good formatting goals To improve code readability To improve code maintainability Fundamental principle of code formatting: Any formatting style that follows the above principle is good Any other formatting is not good 50 The formating of the source code should disclose its logical structure.
  • 51. Formatting Blocks in C# Put { and } alone on a line under the corresponding parent block Indent the block contents by a single [Tab] Don't indent with spaces Example: 51 if ( some condition ) { // Block contents indented by a single [Tab] // Don't use spaces for indentation }
  • 52. Methods Indentation Methods should be indented with a single [Tab] from the class body Methods body should be indented with a single [Tab] as well 52 public class IndentationExample { private int Zero() { return 0; } } The entire method is indented with a single [Tab] Method body is also indented
  • 53. Brackets in Methods Declaration Brackets in the method declaration should be formatted as follows: Don't use spaces between the brackets: The same applies for if-conditions and for-loops: 53 private static ulong CalcFactorial(uint num) private static ulong CalcFactorial ( uint num ) private static ulong CalcFactorial (uint num) if (condition) …
  • 54. Separating Parameters Separate method parameters by comma followed by a space Don't put comma before the space Examples: Incorrect examples: 54 private void RegisterUser(string username, string password) RegisterUser("nakov", "s3cr3t!p@ssw0rd"); private void RegisterUser(string username,string password) private void RegisterUser(string username ,string password) private void RegisterUser(string username , string password)
  • 55. Empty Lines between Methods Use empty line for separation between methods: 55 public class Factorial { private static ulong CalcFactorial(uint num) { if (num == 0) return 1; else return num * CalcFactorial(num - 1); } static void Main() { ulong factorial = CalcFactorial(5); Console.WriteLine(factorial); } } Always use { and } after if (there is no space to do it here) Empty line
  • 56. Empty Lines in Method Body Use an empty line to separate logically related sequences of lines: 56 private List<Report> PrepareReports() { List<Report> reports = new List<Report>(); // Create incomes reports Report incomesSalesReport = PrepareIncomesSalesReport(); reports.Add(incomesSalesReport); Report incomesSupportReport = PrepareIncomesSupportReport(); reports.Add(incomesSupportReport); // Create expenses reports Report expensesPayrollReport = PrepareExpensesPayrollReport(); reports.Add(expensesPayrollReport); Report expensesMarketingReport = PrepareExpensesMarketingReport(); reports.Add(expensesMarketingReport); return reports; } Empty line Empty line Empty line
  • 57. Misplaced Empty Lines – Example 57 public static void PrintList(List<int> ints) { Console.Write("{ "); foreach (int item in ints) { Console.Write(item); Console.Write(" "); } Console.WriteLine("}"); } static void Main() { // ... }
  • 58. Formatting Types Formatting classes / structures / interfaces / enumerations Indent the class body with a single [Tab] Use the following order of definitions: Constants, delegates, inner types, fields, constructors, properties, methods Static members, public members, protected members, internal members, private members The above order of definitions is not the only possible correct one 58
  • 59. Formatting Types – Example 59 public class Dog { // Static variables public const string SPECIES = "Canis Lupus Familiaris"; // Instance variables private int age; // Constructors public Dog(string name, int age) { this.Name = name; this.age = age; } (continues on the next slide)
  • 60. Formatting Types – Example (2) 60 // Properties public string Name { get; set; } // Methods public void Breath() { // TODO: breathing process } public void Bark() { Console.WriteLine("wow-wow"); } }
  • 61. Formatting Conditional Statements and Loops Formatting conditional statements and loops Always use { } block after if / for / while, even when a single operator follows Indent the block body after if / for / while Never put the block after if / for / while on the same line! Always put the { on the next line Never indent with more than one [Tab] 61
  • 62. Conditional Statements and Loops Formatting – Examples Example: Incorrect examples: 62 for (int i=0; i<10; i++) { Console.WriteLine("i={0}", i); } for (int i=0; i<10; i++) Console.WriteLine("i={0}", i); for (int i=0; i<10; i++) Console.WriteLine("i={0}", i); for (int i=0; i<10; i++) { Console.WriteLine("i={0}", i); }
  • 63. Breaking Long Lines Break long lines after punctuation Indent the second line by single [Tab] Do not additionally indent the third line Examples: 63 if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) { … DictionaryEntry<K, V> newEntry = new DictionaryEntry<K, V>( oldEntry.Key, oldEntry.Value);
  • 64. Incorrect Ways ToBreak Long Lines 64 if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) { … if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) { … DictionaryEntry<K, V> newEntry = new DictionaryEntry<K, V>(oldEntry .Key, oldEntry.Value);
  • 65. Alignments All types of alignments are considered harmful Alignments are hard-to-maintain! Incorrect examples: 65 DateTime date = DateTime.Now.Date; int count = 0; Student student = new Strudent(); List<Student> students = new List<Student>(); matrix[x, y] == 0; matrix[x + 1, y + 1] == 0; matrix[2 * x + y, 2 * y + x] == 0; matrix[x * y, x * y] == 0;
  • 66. High-Quality Classes How to Design High-Quality Classes? Abstraction, Cohesion and Coupling
  • 67. High-Quality Classes: Abstraction Present a consistent level of abstraction in the class contract (publicly visible members) What abstraction the class is implementing? Does it represent only one thing? Does the class name well describe its purpose? Does the class define clear and easy to understand public interface? Does the class hide all its implementation details? 67
  • 68. Good Abstraction – Example 68 public class Font { public string Name { get; set; } public float SizeInPoints { get; set; } public FontStyle Style { get; set; } public Font(string name, float sizeInPoints, FontStyle style) { this.Name = name; this.SizeInPoints = sizeInPoints; this.Style = style; } public void DrawString(DrawingSurface surface, string str, int x, int y) { ... } public Size MeasureString(string str) { ... } }
  • 69. Bad Abstraction – Example 69 public class Program { public string title; public int size; public Color color; public void InitializeCommandStack(); public void PushCommand(Command command); public Command PopCommand(); public void ShutdownCommandStack(); public void InitializeReportFormatting(); public void FormatReport(Report report); public void PrintReport(Report report); public void InitializeGlobalData(); public void ShutdownGlobalData(); } Does this class really represent a "program"? Is this name good? Does this class really have a single purpose?
  • 70.
  • 71. Establishing Good Abstraction (2) Beware of breaking the interface abstraction due to evolution Don't add public members inconsistent with class abstraction Example: in class called Employee at some time we add method for accessing the DB with SQL 71 class Employee { public string firstName; public string lastName; … public SqlCommand FindByPrimaryKeySqlCommand(int id); }
  • 72. Encapsulation Minimize the visibility of classes and members Start from private and move to internal, protected and public if required Classes should hide their implementation details Anything which is not part of the class interface should be declared private Classes with good encapsulated classes are: less complex, easier to maintain, more loosely coupled Never declare fields public (except constants) Use methods or properties to access fields 72
  • 73. Encapsulation (2) Don't violate encapsulation semantically! Don't rely on non-documented internal behavior or side effects Wrong example: Skip calling ConnectToDB() because you just called FindEmployeeById() which should open connection Another wrong example: Use String.Empty instead of Titles.NoTitle because you know both values are the same 73
  • 74. Inheritance Don't hide methods in a subclass Example: if the class Timer has private method Start(), don't define Start() in AtomTimer Move common interfaces, data, and behavior as high as possible in the inheritance tree This maximizes the code reuse Be suspicious of base classes of which there is only one derived class Do you really need this additional level of inheritance? 74
  • 75. Inheritance (2) Be suspicious of classes that override a routine and do nothing inside Is the overridden routine used correctly? Avoid deep inheritance trees Don't create more than 6 levels of inheritance Avoid using a base class’s protected data fields in a derived class Provide protected accessor methods or properties instead 75
  • 76. Inheritance (3) Prefer inheritance to extensive type checking: Consider inheriting Circle and Square from Shape and override the abstract action Draw() 76 switch (shape.Type) { case Shape.Circle: shape.DrawCircle(); break; case Shape.Square: shape.DrawSquare(); break; ... }
  • 77. Class Methods and Data Keep the number of methods in a class as small as possible  reduce complexity Minimize direct method calls to other classes Minimize indirect method calls to other classes Less external method calls == less coupling Minimize the extent to which a class collaborates with other classes Reduce coupling between classes 77
  • 78. Class Constructors Initialize all member data in all constructors, if possible Uninitialized data is error prone Partially initialized data is even more evil Incorrect example: assign FirstName in class Person but leave LastName empty Initialize data members in the same order in which they are declared Prefer deep copies to shallow copies (ICloneable should make deep copy) 78
  • 79. Use Design Patterns Use private constructor to prohibit direct class instantiation Use deign patterns for common design situations Creational patterns like singleton, factory method, abstract factory Structural patterns like adapter, bridge, composite, decorator, façade Behavioral patterns like command, iterator, observer, strategy, template method 79
  • 80. Top Reasons to Create Class Model real-world objects with OOP classes Model abstract objects, processes, etc. Reduce complexity Work at higher level Isolate complexity Hide it in a class Hide implementation details  encapsulation Limit effects of changes Changes affect only their class 80
  • 81. Top Reasons to Create Class (2) Hide global data Work through methods Group variables that are used together Make central points of control Single task should be done at single place Avoid duplicating code Facilitate code reuse Use class hierarchies and virtual methods Package related operations together 81
  • 82. Namespaces Group related classes together in namespaces Follow consistent naming convention 82 namespace Utils { class MathUtils { … } class StringUtils { … } } namespace DataAccessLayer { class GenericDAO<Key, Entity> { … } class EmployeeDAO<int, Employee> { … } class AddressDAO<int, Address> { … } }
  • 83. High-Quality Methods How to Design and Implement High-Quality Methods? Understanding Cohesion and Coupling
  • 84. Why We Need Methods? Methods are important in software development Reduce complexity Divide and conquer: complex problems can be split into composition of several simple ones Improve code readability Small methods with good method names make the code self-documenting Avoid duplicating code Duplicating code is hard to maintain 84
  • 85. Why We Need Methods? (2) Methods simplify software development Hide implementation details Complex logic is encapsulated and hidden behind a simple interface Algorithms and data structures are hidden and can be transparently replaced later Increase the level of abstraction Methods address the business problem, not the technical implementation: 85 Bank.accounts[customer].deposit(500);
  • 86. Using Methods: Fundamentals Fundamental principle of correct method usage: Methods should do exactly what their names say Nothing less Nothing more In case of incorrect input or incorrect preconditions, an error should be indicated 86 A method should do what its name says or should indicate an error. Any other behaviour is incorrect!
  • 87. Good Methods – Examples 87 long Sum(int[] elements) { long sum = 0; foreach (int element in elements) { sum = sum + element; } return sum; } double CalcTriangleArea(double a, double b, double c) { if (a <= 0 || b <= 0 || c <= 0) { throw new ArgumentException( "Sides should be positive."); } double s = (a + b + c) / 2; double area = Math.Sqrt(s * (s - a) * (s - b) * (s - c)); return area; }
  • 88. Symptoms of Wrong Methods Method that does something different than its name says, is wrong for one of these reasons: The returned result is incorrect  bug The returned output is incorrect when its input is incorrect or unusual  low quality Acceptable for private methods only The method does too many things  bad cohesion The method has side effects  spaghetti code Method returns strange value when an error condition happens  it should indicate the error 88
  • 89. Wrong Methods – Examples 89 long Sum(int[] elements) { long sum = 0; for (int i = 0; i < elements.Length; i++) { sum = sum + elements[i]; elements[i] = 0; } return sum; } Hidden side effect double CalcTriangleArea(double a, double b, double c) { if (a <= 0 || b <= 0 || c <= 0) { return 0; } double s = (a + b + c) / 2; double area = Math.Sqrt(s * (s - a) * (s - b) * (s - c)); return area; } Incorrect result. Throw an exception instead.
  • 90. Strong Cohesion Methods should have strong cohesion Should address single task and address it well Should have clear intent Methods that address several tasks in the same time are hard to be named String cohesion is used in engineering In computer hardware any PC component solves a single task E.g. hard disk performs a single task – storage 90
  • 91. Acceptable Types of Cohesion Functional cohesion(independent function) Method performs certain well-defined calculation and returns a single result The entire input is passed through parameters and the entire output is returned as result No external dependencies or side effects Examples: 91 Math.Sqrt(value)  square root Char.IsLetterOrDigit(ch) String.Substring(str, startIndex, length)
  • 92. Acceptable Types of Cohesion (2) Sequential cohesion(algorithm) Method performs certain sequence of operations to perform a single task and achieve certain result It encapsulates an algorithm Example: Connect to mail server Send message headers Send message body Disconnect from the server 92 SendEmail(recipient, subject, body)
  • 93. Acceptable Types of Cohesion (3) Communicational cohesion(common data) A set of operations used to process certain data and produce a result Example: Retrieve input data from database Perform internal calculations over retrieved data Build the report Format the report as Excel worksheet Display the Excel worksheet on the screen 93 DisplayAnnualExpensesReport(int employeeId)
  • 94. Acceptable Types of Cohesion (4) Temporal cohesion (time related activities) Operations that are generally not related but need to happen in a certain moment Examples: Load user settings Check for updates Load all invoices from the database Sequence of actions to handle the event 94 InitializeApplication() ButtonConfirmClick()
  • 95. Unacceptable Cohesion Logical cohesion Performs a different operation depending on an input parameter Incorrect example: Can be acceptable in event handlers (e.g. the KeyDown event in Windows Forms) 95 object ReadAll(int operationCode) { if (operationCode == 1) … // Read person name else if (operationCode == 2) … // Read address else if (operationCode == 3) … // Read date … }
  • 96. Unacceptable Cohesion Coincidental cohesion (spaghetti) Not related (random) operations are grouped in a method for unclear reason Incorrect example: Prepares annual incomes report for given customer Sorts an array of integers in increasing order Calculates the square root of given number Converts given MP3 file into WMA format Sends email to given customer 96 HandleStuff(customerId, int[], ref sqrtValue, mp3FileName, emailAddress)
  • 97. Loose Coupling What is loose coupling? Minimal dependences of the method on the other parts of the source code Minimal dependences on the class members or external classes and their members No side effects If the coupling is loose, we can easily reuse a method or group of methods in a new project Tight coupling  spaghetti code 97
  • 98. Loose Coupling (2) The ideal coupling A methods depends only on its parameters Does not have any other input or output Example: Math.Sqrt Real world Complex software cannot avoid coupling but could make it as loose as possible Example: complex encryption algorithm performs initialization, encryption, finalization 98
  • 99. Coupling – Example Intentionally increased coupling for more flexibility (.NET cryptography API): 99 byte[] EncryptAES(byte[] inputData, byte[] secretKey) { Rijndael cryptoAlg = new RijndaelManaged(); cryptoAlg.Key = secretKey; cryptoAlg.GenerateIV(); MemoryStream destStream = new MemoryStream(); CryptoStream csEncryptor = new CryptoStream( destStream, cryptoAlg.CreateEncryptor(), CryptoStreamMode.Write); csEncryptor.Write(inputData, 0, inputData.Length); csEncryptor.FlushFinalBlock(); byte[] encryptedData = destStream.ToArray(); return encryptedData; }
  • 100. Loose Coupling – Example To reduce coupling we can make utility classes that hide the complex logic and provide simple straightforward interface (a.k.a. façade): 100 byte[] EncryptAES(byte[] inputData, byte[] secretKey) { MemoryStream inputStream = new MemoryStream(inputData); MemoryStream outputStream = new MemoryStream(); EncryptionUtils.EncryptAES( inputStream, outputStream, secretKey); byte[] encryptedData = outputStream.ToArray(); return encryptedData; }
  • 101. Tight Coupling – Example Passing parameters through class fields Typical example of tight coupling Don't do this unless you have a good reason! 101 class Sumator { public int a, b; int Sum() { return a + b; } static void Main() { Sumator sumator = new Sumator() { a = 3, b = 5 }; Console.WriteLine(sumator.Sum()); } } Why don't pass the numbers as parameters?
  • 102. Loose Coupling and OOP Reducing coupling with OOP techniques Abstraction Define a public interface and hide the implementation details Encapsulation Make methods and fields private unless they are definitely needed Define new members as private Increase visibility as soon as this is needed 102
  • 103. Acceptable Coupling Method is coupled to its parameters This is the best type of coupling Method in a class is coupled to some class fields This coupling is usual, do not worry too much Method in a class is coupled to static methods, properties or constants in external class This is normal, usually is not a problem Method is coupled to external static fields Avoid this, classes should keep their fields private 103
  • 104. Non-Acceptable Coupling Method in a class is coupled to static fields in external class Avoid it  consider refactoring Methods take as input data some fields that could be passed as parameters Check the intent of the method Is it designed to process internal class data or is utility method Method is defined public without being part of the public class's interface  possible coupling 104
  • 105. Methods Parameters Put most important parameters first First put the main input parameters Put non-important optional parameters last Example: Incorrect examples: 105 void RegisterUser(string username, string password, Date accountExpirationDate, Role[] roles) void RegisterUser(Role[] roles, string password, string username, Date accountExpirationDate) void RegisterUser(string password, Date accountExpirationDate, Role[] roles, string username)
  • 106. Methods Parameters (2) Do not modify the input parameters Use new variable instead Incorrect example: Correct example: 106 bool CheckLogin(string username, string password) { username = username.ToLower(); … // Check the username / password here } bool CheckLogin(string username, string password) { string usernameLowercase = username.ToLower(); … // Check the username / password here }
  • 107. Methods Parameters (3) Use parameters consistently Use the same names and the same order in all methods Incorrect example: Output parameters should be put last 107 void EncryptFile(Stream input, Stream output, string key); void DecryptFile(string key, Stream output, Stream input); FindCustomersAndIncomes(Region region, out Customer[] customers, out decimal[] incomes)
  • 108. Pass Entire Object or Its Fields? When should we pass an object containing few values and when these values separately? Sometime we pass an object and use only a single field of it – it is a good practice? Examples: Look at the method's level of abstraction Is it intended to operate with employees of with rates and months?  the first is incorrect 108 CalculateSalary(Employee employee, int months); CalculateSalary(double rate, int months);
  • 109. How Much Parameters Methods Should Have? Limit the number of method parameters to 7 (+/-2) 7 is a magic number in psychology Human brain cannot process more than 7 (+/-2) things in the same time If the parameters need to be too much reconsider the method intent  does it have clear intent? Consider putting few parameters in a new class 109
  • 110. Methods Length How long should a method be? There is no specific restriction Avoid methods longer than one screen (30 lines) Long methods are not always bad Be sure you have a good reason for their length Cohesion and coupling are more important than the method length! Long methods often contain portions that could be extracted as separate methods with good name and clear intent  check this! 110
  • 111. Using Variables Best Practices
  • 112. Retuning Result from a Method Always assign the result of a method in some variable before returning it. Benefits: Improved code readability The returned value has self-documenting name Simplified debugging Example: Incorrect example: 112 The intent of the formula is obvious int salary = days * hoursPerDay * ratePerHour; return salary; We can put a breakpoint at this line and check if the result is correct return days * hoursPerDay * ratePerHour;
  • 113. Variable Initialization Initialize all variables before their first usage Class variables (fields) are automatically initialized with 0 / null by the C# compiler You still get a warning message Local variables should be manually initialized This C# code will result in compilation error: We can initialize variables at their declaration: 113 int value; Console.WriteLine(value); int value = 0; Console.WriteLine(value);
  • 114. Partially Initialized Objects Ensure objects cannot get into partially initialized state Make all fields private and require valid values for all mandatory fields in all constructors Example: Student object is invalid unless it has Name and FacultyNumber 114 class Student { private string name, facultyNumber; public Student(string name, string facultyNumber) { … } }
  • 115. Variable Scope Variable scope defines how "famous" is a variable in the program Static variables are more "famous" than instance variables, and they are more "famous" than local Variables' visibility is directly related to their scope public, protected, internal, private Always try to reduce the variable's scope This reduces potential coupling Avoid public fields (exception: readonly / const) Access all fields through properties / methods 115
  • 116. Exceeded Scope – Example 116 public class Globals { public static int state = 0; } public class Genious { public static void PrintSomething() { if (Globals.state == 0) { Console.WriteLine("Hello."); } else { Console.WriteLine("Good bye."); } } }
  • 117. Variable Span and Lifetime Variable span The average number of lines of code (LOC) between variable usages Variable lifetime The number of lines of code (LOC) between the first and the last variable usage in a block Keep variable span and lifetime as low as possible 117 Always define and initialize variables just before their first use and never before it!
  • 118. Unneeded Large Variable Span and Lifetime int count; int[] numbers = new int[100]; for (int i = 0; i < numbers.Length; i++) { numbers[i] = i; } count = 0; for (int i = 0; i < numbers.Length / 2; i++) { numbers[i] = numbers[i] * numbers[i]; } for (int i = 0; i < numbers.Length; i++) { if (numbers[i] % 3 == 0) { count++; } } Console.WriteLine(count); 118 lifetime ("count") = 19 span = 19 / 4 = 4.75
  • 119. Reduced Variable Span and Lifetime 119 int[] numbers = new int[100]; for (int i = 0; i < numbers.Length; i++) { numbers[i] = i; } for (int i = 0; i < numbers.Length / 2; i++) { numbers[i] = numbers[i] * numbers[i]; } int count = 0; for (int i = 0; i < numbers.Length; i++) { if (numbers[i] % 3 == 0) { count++; } } Console.WriteLine(count); lifetime = 9 span= 9 / 3 = 3
  • 120. Single Purpose Variables should have single purpose Never use a single variable for multiple purposes! Economizing memory is not an excuse Can you choose a good name for variable that is used for several purposes? Example: variable used to count students of to keep the average of their grades Proposed name: studentsCountOrAvgGrade 120
  • 121. Variables – Other Suggestions Don't define variables that are not used Compilers usually issues warnings Don't use variables with hidden purpose Incorrect example: Instead use enumeration: 121 int mode = 1; … if (mode == 1) …; // Read if (mode == 2) …; // Write if (mode == 3) …; // Read and write enum ResourceAccessMode { Read, Write, ReadWrite }
  • 123. Avoid Complex Expressions Never use complex expressions in the code! Incorrect example: Complex expressions are evil because: Make code hard to read and understand, hard to debug, hard to modify and hard to maintain 123 What shall we do if we get at this line IndexOutOfRangeException? for (int i=0; i<xCoords.length; i++) { for (int j=0; j<yCoords.length; j++) { matrix[i][j] = matrix[xCoords[findMax(i)+1]][yCoords[findMin(j)-1]] * matrix[yCoords[findMax(j)+1]][xCoords[findMin(i)-1]]; } } There are 10 potential sources of IndexOutOfRangeException in this expression!
  • 124. Simplifying Complex Expressions 124 for (int i = 0; i < xCoords.length; i++) { for (int j = 0; j < yCoords.length; j++) { int maxStartIndex = findMax(i) + 1; int minStartIndex = findMin(i) - 1; int minXcoord = xCoords[minStartIndex]; int maxXcoord = xCoords[maxStartIndex]; int minYcoord = yCoords[minStartIndex]; int maxYcoord = yCoords[maxStartIndex]; int newValue = matrix[maxXcoord][minYcoord] * matrix[maxYcoord][minXcoord]; matrix[i][j] = newValue; } }
  • 125. Using Constants When and How to Use Constants?
  • 126. Avoid Magic Numbers and Strings What is magic number or value? Magic numbers / values are all literals different than 0, 1, -1, null and "" (empty string) Avoid using magic numbers / values They are hard to maintain When change occurs, you need to modify all occurrences of the magic number / constant Their meaning is not obvious Example: what does the number 1024 mean? 126
  • 127. The Evil Magic Numbers 127 public class GeometryUtils { public static double CalcCircleArea(double radius) { double area = 3.14159206 * radius * radius; return area; } public static double CalcCirclePerimeter(double radius) { double perimeter = 6.28318412 * radius; return perimeter; } public static double CalcElipseArea(double axis1, double axis2) { double area = 3.14159206 * axis1 * axis2; return area; } }
  • 128. Turning MagicNumbers into Constants 128 public class GeometryUtils { public const double PI = 3.14159206; public static double CalcCircleArea(double radius) { double area = PI * radius * radius; return area; } public static double CalcCirclePerimeter(double radius) { double perimeter = 2 * PI * radius; return perimeter; } public static double CalcElipseArea( double axis1, double axis2) { double area = PI * axis1 * axis2; return area; } }
  • 129. When to Use Constants? Constants should be used in the following cases: When we need to use numbers or other values and their logical meaning and value are not obvious File names Mathematical constants Bounds and ranges 129 public const string SettingsFileName = "ApplicationSettings.xml"; public const double E = 2.7182818284; public const int READ_BUFFER_SIZE = 5 * 1024 *1024;
  • 130. When to Avoid Constants? Sometime it is better to keep the magic values instead of using a constant Error messages and exception descriptions SQL commands for database operations Titles of GUI elements (labels, buttons, menus, dialogs, etc.) For internationalization purposes use resources, not constants 130
  • 131. Using Control Constructs Using Conditional Statements and Loops Correctly
  • 132. Using Conditional Statements Always use { and } for the conditional statements body, even when it is a single line: Why omitting the brackets could be harmful? This is misleading code + misleading formatting 132 if (condition) { DoSometing(); } if (condition) DoSomething(); DoAnotherThing(); DoDifferentThing();
  • 133. Use Simple Conditions Do not use complex if conditions You can always simplify them by introducing boolean variables or boolean methods Incorrect example: Complex boolean expressions are harmful How you will find the problem if you get IndexOutOfRangeException? 133 if (x > 0 && y > 0 && x < Width-1 && y < Height-1 && matrix[x, y] == 0 && matrix[x-1, y] == 0 && matrix[x+1, y] == 0 && matrix[x, y-1] == 0 && matrix[x, y+1] == 0 && !visited[x, y])
  • 134. Simplifying Boolean Conditions The last example can be easily refactored into self-documenting code: Now the code is: Easy to read – the logic of the condition is clear Easy to debug – breakpoint can be put at the if 134 bool inRange = x > 0 && y > 0 && x < Width-1 && y < Height-1; bool emptyCellAndNeighbours = matrix[x, y] == 0 && matrix[x-1, y] == 0 && matrix[x+1, y] == 0 && matrix[x, y-1] == 0 && matrix[x, y+1] == 0; if (inRange && emptyCellAndNeighbours && !visited[x, y])
  • 135. Avoid Deep Nesting of Blocks Deep nesting of conditional statements and loops makes the code unclear Deeply nested code is complex and hard to read and understand Usually you can extract portions of the code in separate methods This simplifies the logic of the code Using good method name makes the code self-documenting 135
  • 136. Deep Nesting – Example 136 if (maxElem != Int32.MaxValue) { if (arr[i] < arr[i + 1]) { if (arr[i + 1] < arr[i + 2]) { if (arr[i + 2] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 2]; } } else { if (arr[i + 1] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 1]; } } } (continues on the next slide)
  • 137. Deep Nesting – Example (2) 137 else { if (arr[i] < arr[i + 2]) { if (arr[i + 2] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i + 2]; } } else { if (arr[i] < arr[i + 3]) { maxElem = arr[i + 3]; } else { maxElem = arr[i]; } } } }
  • 138. Avoiding Deep Nesting – Example 138 private static int Max(int i, int j) { if (i < j) { return j; } else { return i; } } private static int Max(int i, int j, int k) { if (i < j) { int maxElem = Max(j, k); return maxElem; } else { int maxElem = Max(i, k); return maxElem; } } (continues on the next slide)
  • 139. Avoiding Deep Nesting – Example 139 private static int FindMax(int[] arr, int i) { if (arr[i] < arr[i + 1]) { int maxElem = Max(arr[i + 1], arr[i + 2], arr[i + 3]); return maxElem; } else { int maxElem = Max(arr[i], arr[i + 2], arr[i + 3]); return maxElem; } } if (maxElem != Int32.MaxValue) { maxElem = FindMax(arr, i); }
  • 140. Using Case Statement Choose the most effective ordering of cases Put the normal (usual) case first Order cases by frequency Put the most unusual (exceptional) case last Order cases alphabetically or numerically Keep the actions of each case simple Extract complex logic in separate methods Use the default clause in a casestatement or the last elsein a chain of if-else to trap errors 140
  • 141. Bad Case Statement 141 void ProcessNextChar(char ch) { switch (parseState) { InTag: if (ch == ">") { Console.WriteLine("Found tag: {0}", tag); text = ""; parseState = ParseState.OutOfTag; } else { tag = tag + ch; } break; OutOfTag: … } }
  • 142. Improved Case Statement 142 void ProcessNextChar(char ch) { switch (parseState) { InTag: ProcessCharacterInTag(ch); break; OutOfTag: ProcessCharacterOutOfTag(ch); break; default: throw new Exception("Invalid parse state: " + parseState); } }
  • 143. Using Loops Choosing the correct type of loop: Use for loop to repeat some block of code a certain number of times Use foreach loop to process each element of array or collection Use while / do-while loop when you don't know how many times a block should be repeated Avoid deep nesting of loops You can extract the loop body in a new method 143
  • 144. Loops: Best Practices Keep loops simple This helps readers of your code Treat the inside of the loop as it were a routine Don’t make the reader look inside the loop to understand the loop control Think of a loop as a black box: 144 while (!inputFile.EndOfFile() && !hasErrors) { } (black box code)
  • 145. Defensive Programming Using Assertions and Exceptions Correctly
  • 146. Principles of Defensive Programming Fundamental principle of defensive programming Defensive programming means: To expect incorrect input and to handle it correctly To think not only about the usual execution flow, but to consider also unusual situations To ensure that incorrect input results to exception, not to incorrect output 146 Any public method should check its input data, preconditions and postconditions
  • 147. Defensive Programming – Example 147 string Substring(string str, int startIndex, int length) { if (str == null) { throw new NullReferenceException("Str is null."); } if (startIndex >= str.Length) { throw new ArgumentException( "Invalid startIndex:" + startIndex); } if (startIndex + count > str.Length) { throw new ArgumentException("Invalid length:" + length); } … Debug.Assert(result.Length == length); } Check the input and preconditions. Perform the method main logic. Check the postconditions.
  • 148. Exceptions – Best Practices Choose a good name for your exception class Incorrect example: Example: Use descriptive error messages Incorrect example: Example: 148 throw new Exception("File error!"); throw new FileNotFoundException("Cannot find file " + fileName); throw new Exception("Error!"); throw new ArgumentException("The speed should be a number " + "between " + MIN_SPEED + " and " + MAX_SPEED + ".");
  • 149. Exceptions Handling Best Practices (2) Catch only exceptions that you are capable to process correctly Do not catch all exceptions! Incorrect example: What about OutOfMemoryException? 149 try { ReadSomeFile(); } catch { Console.WriteLine("File not found!"); }
  • 150. Exceptions Handling Best Practices (3) Always include the exception cause when throwing a new exception 150 try { WithdrawMoney(account, amount); } catch (DatabaseException dbex) { throw new WithdrawException(String.Format( "Can not withdraw the amount {0} from acoount {1}", amount, account), dbex); } We include in the exceptions chain the original source of the problem.
  • 151. Exceptions Handling Best Practices (4) Throw exceptions at the corresponding level of abstraction Example: Bank account withdrawal operation could throw InsufficientFundsException but cannot throw FileAccessDeniedException Display to the end users only messages that they could understand 151 or
  • 152. Disposable Resources Handle disposable resources with care All classes implementing IDisposable should follow the try-finally / using pattern: 152 StreamReader reader = new StreamReader("file.txt"); try { String line = reader.ReadLine(); } finally { reader.Close(); } StreamReader reader = new StreamReader( "file.txt"); using (reader) { String line = reader.ReadLine(); } ==
  • 153. Comments and Code Documentation The Concept of Self-Documenting Code
  • 154. Effective Comments Effective comments do not repeat the code They explain it at higher level and reveal non-obvious details The best software documentation is the source code itself – keep it clean and readable Self-documenting code is code that is self-explainable and does not need comments Simple design, small well named methods, strong cohesion and loose coupling, simple logic, good variable names, good formatting, … 154
  • 155. Self-Documenting Code Self-documenting code fundamental principles 155 The best documentation is the code itself. Make the code self-explainable and self-documenting, easy to read and understand. Do not document bad code, rewrite it!
  • 156. Bad Comments – Example 156 public static List<int> FindPrimes(int start, int end) { // Create new list of integers List<int> primesList = new List<int>(); // Perform a loop from start to end for (int num = start; num <= end; num++) { // Declare boolean variable, initially true bool prime = true; // Perform loop from 2 to sqrt(num) for (int div = 2; div <= Math.Sqrt(num); div++) { // Check if div divides num with no remainder if (num % div == 0) { // We found a divider -> the number is not prime prime = false; // Exit from the loop break; } (continues on the next slide)
  • 157. Bad Comments – Example (2) 157 // Continue with the next loop value } // Check if the number is prime if (prime) { // Add the number to the list of primes primesList.Add(num); } } // Return the list of primes return primesList; }
  • 158. Self-Documenting Code – Example 158 public static List<int> FindPrimes(int start, int end) { List<int> primesList = new List<int>(); for (int num = start; num <= end; num++) { bool isPrime = IsPrime(num); if (isPrime) { primesList.Add(num); } } return primesList; } Good code does not need comments. It is self-explaining. (continues on the next slide)
  • 159. Self-Documenting Code –Example (2) 159 private static bool IsPrime(int num) { bool isPrime = true; int maxDivider = Math.Sqrt(num); for (int div = 2; div <= maxDivider; div++) { if (num % div == 0) { // We found a divider -> the number is not prime isPrime = false; break; } } return isPrime; } Good methods have good name and are easy to read and understand. This comment explain non-obvious details. It does not repeat the code.
  • 160. Code Refactoring Improving the Quality of the Existing Code
  • 161. Code Refactoring What is refactoring of the source code? Improving the design and quality of existing source code without changing its behavior Step by step process that turns the bad code into good code (if possible) Why we need refactoring? Code constantly changes and its quality constantly degrades (unless refactored) Requirements often change and code needs to be changed to follow them 161
  • 162. Rafactoring Patterns When should we perform refactoring of the code? Bad smells in the code indicate need of refactoring Unit tests guarantee that refactoring does not change the behavior Rafactoring patterns Large repeating code fragments  extract repeating code in separate method Large methods  split them logically Large loop body or deep nesting  extract method 162
  • 163. Rafactoring Patterns (2) Refactoring patterns Class or method has weak cohesion  split into several classes / methods Single change carry out changes in several classes  classes have tight coupling  consider redesign Related data are always used together but are not part of a single class  group them in a class A method has too many parameters  create a class to groups parameters together A method calls more methods from another class than from its own class  move it 163
  • 164. Rafactoring Patterns (3) Refactoring patterns Two classes are tightly coupled  merge them or redesign them to separate their responsibilities Public non-constant fields  make them private and define accessing properties Magic numbers in the code  consider extracting constants Bad named class / method / variable  rename it Complex boolean condition  split it to several expressions or method calls 164
  • 165. Rafactoring Patterns (4) Refactoring patterns Complex expression  split it into few simple parts A set of constants is used as enumeration  convert it to enumeration Method logic is too complex and is hard to understand  extract several more simple methods or even create a new class Unused classes, methods, parameters, variables  remove them Large data is passed by value without a good reason  pass it by reference 165
  • 166. Rafactoring Patterns (5) Refactoring patterns Few classes share repeating functionality  extract base class and reuse the common code Different classes need to be instantiated depending on configuration setting  use factory Code is not well formatted  reformat it Too many classes in a single namespace  split classes logically into more namespaces Unused using definitions  remove them Non-descriptive error messages  improve them Absence of defensive programming  add it 166
  • 167. Refactoring of Bad Code Live Demo
  • 168.
  • 169. http://codecourse.telerik.comCode Complete, 2nd edition, Steve McConnell, Microsoft Press, 2004, ISBN 0735619670, http://www.cc2e.com
  • 170. High-Quality Programming Code Construction ? ? ? ? ?