Presentation is loading. Please wait.

Presentation is loading. Please wait.

Revealing the Secrets of Self-Documenting Code Svetlin Nakov Telerik Corporation www.telerik.com For C# Developers.

Similar presentations


Presentation on theme: "Revealing the Secrets of Self-Documenting Code Svetlin Nakov Telerik Corporation www.telerik.com For C# Developers."— Presentation transcript:

1 Revealing the Secrets of Self-Documenting Code Svetlin Nakov Telerik Corporation For C# Developers

2 What is High-Quality Programming Code? What is High-Quality Programming Code? External and Internal Code Quality External and Internal Code Quality Naming Identifiers Naming Identifiers Naming Types, Classes, Interfaces, Enumerations, Properties, Methods, Parameters, Variables, Constants, etc. Naming Types, Classes, Interfaces, Enumerations, Properties, Methods, Parameters, Variables, Constants, etc. Code Formatting Code Formatting Designing High-Quality Classes Designing High-Quality Classes Abstraction, Encapsulation, Inheritance, Reasons to Create a Class Abstraction, Encapsulation, Inheritance, Reasons to Create a Class 2

3

4 What does this code do? Is it correct? 4 static void Main() { int value=010, i=5, w; int value=010, i=5, w; switch(value){case 10:w=5;Console.WriteLine(w);break;case 9:i=0;break; switch(value){case 10:w=5;Console.WriteLine(w);break;case 9:i=0;break; case 8:Console.WriteLine("8 ");break; case 8:Console.WriteLine("8 ");break; default:Console.WriteLine("def ");{ default:Console.WriteLine("def ");{ Console.WriteLine("hoho ");} Console.WriteLine("hoho ");} for (int k = 0; k < i; k++, Console.WriteLine(k - 'f'));break;} { Console.WriteLine("loop!"); } for (int k = 0; k < i; k++, Console.WriteLine(k - 'f'));break;} { Console.WriteLine("loop!"); }}

5 Now the code is formatted, but is still unclear. 5 static void Main() { int value = 010, i = 5, w; int value = 010, i = 5, w; switch (value) switch (value) { case 10: w = 5; Console.WriteLine(w); break; case 10: w = 5; Console.WriteLine(w); break; case 9: i = 0; break; case 9: i = 0; break; case 8: Console.WriteLine("8 "); break; case 8: Console.WriteLine("8 "); break; default: default: Console.WriteLine("def "); Console.WriteLine("def "); Console.WriteLine("hoho "); Console.WriteLine("hoho "); for (int k = 0; k < i; k++, Console.WriteLine(k - 'f')) ; for (int k = 0; k < i; k++, Console.WriteLine(k - 'f')) ; break; break; } Console.WriteLine("loop!"); Console.WriteLine("loop!");}

6 External quality External quality Does the software behave correctly? Does the software behave correctly? Are the produced results correct? Are the produced results correct? Does the software run fast? Does the software run fast? Is the software UI easy-to-use? Is the software UI easy-to-use? Internal quality Internal quality It the code easy to read and understand? It the code easy to read and understand? It the code well structured? It the code well structured? Is the code easy to modify? Is the code easy to modify? 6

7 High-quality programming code: High-quality programming code: Easy to read and understand Easy to read and understand Easy to modify and maintain Easy to modify and maintain Correct behavior in all cases Correct behavior in all cases Well tested Well tested Well architectured and designed Well architectured and designed Well documented Well documented Self-documenting code Self-documenting code Well formatted Well formatted 7

8 Code conventions are formal guidelines about the style of the source code: Code conventions are formal guidelines about the style of the source code: Code formatting conventions Code formatting conventions Indentation, whitespace, etc. Indentation, whitespace, etc. Naming conventions Naming conventions PascalCase or camelCase, prefixes, suffixes, etc. PascalCase or camelCase, prefixes, suffixes, etc. Best practices Best practices Classes, interfaces, enumerations, structures, inheritance, exceptions, properties, events, constructors, fields, operators, etc. Classes, interfaces, enumerations, structures, inheritance, exceptions, properties, events, constructors, fields, operators, etc. 8

9 Microsoft has official code conventions called Microsoft has official code conventions called Design Guidelines for Developing Class Libraries: Design Guidelines for Developing Class Libraries: Large organizations follow strict conventions Large organizations follow strict conventions Code conventions can vary in different teams Code conventions can vary in different teams Most conventions developers follow the official Microsoft's recommendations but extend them Most conventions developers follow the official Microsoft's recommendations but extend them High-quality code goes beyond code conventions High-quality code goes beyond code conventions Software quality is not just a set of conventions – its is a way of thinking Software quality is not just a set of conventions – its is a way of thinking 9

10 Managing complexity plays a central role in software construction Managing complexity plays a central role in software construction Minimize the amount of complexity that anyones brain has to deal with at certain time Minimize the amount of complexity that anyones brain has to deal with at certain time Architecture and design challenges Architecture and design challenges Design modules and classes to reduce complexity Design modules and classes to reduce complexity Code construction challenges Code construction challenges Apply good software construction practices: classes, methods, variables, naming, statements, error handling, formatting, comments, etc. Apply good software construction practices: classes, methods, variables, naming, statements, error handling, formatting, comments, etc. 10

11 Key to being an effective programmer: Key to being an effective programmer: Maximizing the portion of a program that you can safely ignore while working on any one section of code Maximizing the portion of a program that you can safely ignore while working on any one section of code Most practices discussed later propose ways to achieve this important goal Most practices discussed later propose ways to achieve this important goal 11

12 Correct behavior Correct behavior Conforming to the requirements Conforming to the requirements Stable, no hangs, no crashes Stable, no hangs, no crashes Bug free Bug free Correct response to incorrect usage Correct response to incorrect usage Easy to read Easy to read Easy to understand Easy to understand Maintainable – easy to modify when required Maintainable – easy to modify when required 12

13 Naming Classes, Interfaces, Enumerations, Methods, Variables and Constants

14 Always use English Always use English How you will feel if you read Vietnamese code with variables named in Vietnamese? How you will feel if you read Vietnamese code with variables named in Vietnamese? English is the only language that all software developers speak English is the only language that all software developers speak Avoid abbreviations Avoid abbreviations Example: scrpCnt vs. scriptsCount Example: scrpCnt vs. scriptsCount Avoid hard-to-pronounce names Avoid hard-to-pronounce names Example: dtbgRegExPtrn vs. dateTimeBulgarianRegExPattern Example: dtbgRegExPtrn vs. dateTimeBulgarianRegExPattern 14

15 Always prefer using meaningful names Always prefer using meaningful names Names should answer these questions: Names should answer these questions: What does this class do? What is the intent of this variable? What is this variable / class used for? What does this class do? What is the intent of this variable? What is this variable / class used for? Examples: Examples: FactorialCalculator, studentsCount, Math.PI, configFileName, CreateReport FactorialCalculator, studentsCount, Math.PI, configFileName, CreateReport Incorrect examples: Incorrect examples: k, k2, k3, junk, f33, KJJ, button1, variable, temp, tmp, temp_var, something, someValue k, k2, k3, junk, f33, KJJ, button1, variable, temp, tmp, temp_var, something, someValue 15

16 Whether a name is meaningful or not depends on its context (its enclosing type) Whether a name is meaningful or not depends on its context (its enclosing type) Examples of meaningful names: Examples of meaningful names: Generate() in the class LabyrinthGenerator Generate() in the class LabyrinthGenerator Find(string fileName) in the class FileFinder Find(string fileName) in the class FileFinder Deposit(decimal amount) in the class Account Deposit(decimal amount) in the class Account Examples of meaningless names: Examples of meaningless names: Generate() in the class Program Generate() in the class Program Find(string fileName) in the class Program Find(string fileName) in the class Program 16

17 Junior developers often use meaningful names that are in fact meaningless Junior developers often use meaningful names that are in fact meaningless Bad naming examples: Bad naming examples: Topic6Exercise12, LoopsExercise12, Problem7, OOPLecture_LastExercise Topic6Exercise12, LoopsExercise12, Problem7, OOPLecture_LastExercise Yes, Topic6Exercise12 indicates that this is solution to exercise 12, but what is it about? Yes, Topic6Exercise12 indicates that this is solution to exercise 12, but what is it about? Better naming: Better naming: MaximalNumbersSubsequence MaximalNumbersSubsequence 17

18 Naming types (classes, structures, etc.) Naming types (classes, structures, etc.) Use PascalCase character casing Use PascalCase character casing Examples: Examples: RecursiveFactorialCalculator, TreeSet, XmlDocument, IEnumerable, Color, TreeNode, InvalidTransactionException, MainForm RecursiveFactorialCalculator, TreeSet, XmlDocument, IEnumerable, Color, TreeNode, InvalidTransactionException, MainForm Incorrect examples: Incorrect examples: recursiveFactorialCalculator, recursive_factorial_calculator, RECURSIVE_FACTORIAL_CALCULATOR recursiveFactorialCalculator, recursive_factorial_calculator, RECURSIVE_FACTORIAL_CALCULATOR 18

19 Use the following formats: Use the following formats: [Noun] [Noun] [Adjective] + [Noun] [Adjective] + [Noun] Examples: Examples: Student, FileSystem, BinaryTreeNode, Constants, MathUtils, TextBox, Calendar Student, FileSystem, BinaryTreeNode, Constants, MathUtils, TextBox, Calendar Incorrect examples: Incorrect examples: Move, FindUsers, Fast, Optimize, Extremly, FastFindInDatabase, Check Move, FindUsers, Fast, Optimize, Extremly, FastFindInDatabase, Check 19

20 Following formats are acceptable: Following formats are acceptable: ' I ' + [Verb] + ' able ' ' I ' + [Verb] + ' able ' ' I ' + [Noun], ' I ' + [Adjective] + [Noun] ' I ' + [Noun], ' I ' + [Adjective] + [Noun] Examples: Examples: IEnumerable, IFormattable, IDataReader, IList, IHttpModule, ICommandExecutor IEnumerable, IFormattable, IDataReader, IList, IHttpModule, ICommandExecutor Incorrect examples: Incorrect examples: List, FindUsers, IFast, IMemoryOptimize, Optimizer, FastFindInDatabase, CheckBox List, FindUsers, IFast, IMemoryOptimize, Optimizer, FastFindInDatabase, CheckBox 20

21 Several formats are acceptable: Several formats are acceptable: [Noun] or [Verb] or [Adjective] [Noun] or [Verb] or [Adjective] Use the same style for all members Use the same style for all members Examples: Examples: enum Day {Monday, Tuesday, Wednesday, …}, enum AppState {Running, Finished, …}, enum WindowState {Normal, Maximized, …} enum Day {Monday, Tuesday, Wednesday, …}, enum AppState {Running, Finished, …}, enum WindowState {Normal, Maximized, …} Incorrect examples: Incorrect examples: enum Color {red, green, blue, white}, enum PAGE_FORMAT {A4, A5, A3, LEGAL, …} enum Color {red, green, blue, white}, enum PAGE_FORMAT {A4, A5, A3, LEGAL, …} 21

22 Exceptions Exceptions Add 'Exception ' as suffix Add 'Exception ' as suffix Use informative name Use informative name Example: FileNotFoundException Example: FileNotFoundException Incorrect example: FileNotFoundError Incorrect example: FileNotFoundError Delegate Classes Delegate Classes Add 'Delegate ' or ' EventHandler ' as suffix Add 'Delegate ' or ' EventHandler ' as suffix Example: DownloadFinishedDelegate Example: DownloadFinishedDelegate Incorrect example: WakeUpNotification Incorrect example: WakeUpNotification 22

23 How long could be the name of a class / struct / interface / enum? How long could be the name of a class / struct / interface / enum? The name should be as long as required The name should be as long as required Don't abbreviate the names if this could make them unclear Don't abbreviate the names if this could make them unclear Your IDE has autocomplete, right? Your IDE has autocomplete, right? Examples: FileNotFoundException, CustomerSupportNotificationService Examples: FileNotFoundException, CustomerSupportNotificationService Incorrect examples: FNFException, CustSuppNotifSrvc Incorrect examples: FNFException, CustSuppNotifSrvc 23

24 Namespaces naming guidelines Namespaces naming guidelines Use PascalCase Use PascalCase Following formats are acceptable: Following formats are acceptable: Company.Product.Component. … Company.Product.Component. … Product.Component.… Product.Component.… Example: Example: Telerik.WinControls.GridView Telerik.WinControls.GridView Incorrect example: Incorrect example: Telerik_WinControlsGridView, Classes Telerik_WinControlsGridView, Classes 24

25 Assembly names should follow the root namespace in its class hierarchy Assembly names should follow the root namespace in its class hierarchy Examples: Examples: Telerik.WinControls.GridView.dll Telerik.WinControls.GridView.dll Oracle.DataAccess.dll Oracle.DataAccess.dll Interop.CAPICOM.dll Interop.CAPICOM.dll Incorrect examples: Incorrect examples: Telerik_WinControlsGridView.dll Telerik_WinControlsGridView.dll OracleDataAccess.dll OracleDataAccess.dll 25

26 Methods naming guidelines Methods naming guidelines Method names should be meaningful Method names should be meaningful Should answer the question: Should answer the question: What does this method do? What does this method do? If you cannot find a good name for a method, think about does it have clear intent If you cannot find a good name for a method, think about does it have clear intent Examples: FindStudent, LoadReport, Sinus Examples: FindStudent, LoadReport, Sinus Incorrect examples: Method1, DoSomething, HandleStuff, SampleMethod, DirtyHack Incorrect examples: Method1, DoSomething, HandleStuff, SampleMethod, DirtyHack 26

27 Use PascalCase character casing Use PascalCase character casing Example: LoadSettings, not loadSettings Example: LoadSettings, not loadSettings Prefer the following formats: Prefer the following formats: [Verb] [Verb] [Verb] + [Noun], [Verb] + [Adjective] + [Noun] [Verb] + [Noun], [Verb] + [Adjective] + [Noun] Examples: Show, LoadSettingsFile, FindNodeByPattern, ToString, PrintList Examples: Show, LoadSettingsFile, FindNodeByPattern, ToString, PrintList Incorrect examples: Student, Counter, White, Generator, Approximation, MathUtils Incorrect examples: Student, Counter, White, Generator, Approximation, MathUtils 27

28 Methods returning values should describe the returned value Methods returning values should describe the returned value Examples: Examples: ConvertMetersToInches, not MetersInches or Convert or ConvertUnit ConvertMetersToInches, not MetersInches or Convert or ConvertUnit Meters2Inches is still acceptable Meters2Inches is still acceptable CalculateSinus is good CalculateSinus is good Sinus is also acceptable Sinus is also acceptable Ensure that the unit of measure of obvious Ensure that the unit of measure of obvious Prefer MeasureFontInPixels to MeasureFont Prefer MeasureFontInPixels to MeasureFont 28

29 Methods should have a single purpose! Methods should have a single purpose! Otherwise they cannot be named well 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? How to name a method that creates annual incomes report, downloads updates from internet and scans the system for viruses? CreateAnnualIncomesReportDownloadUpda tesAndScanForViruses is a nice name, right? CreateAnnualIncomesReportDownloadUpda tesAndScanForViruses is a nice name, right? Methods that have multiple purposes (weak cohesion) are hard to be named Methods that have multiple purposes (weak cohesion) are hard to be named Need to be refactored instead of named Need to be refactored instead of named 29

30 Use consistent naming in the entire project Use consistent naming in the entire project LoadFile, LoadImageFromFile, LoadSettings, LoadFont, LoadLibrary, but not ReadTextFile LoadFile, LoadImageFromFile, LoadSettings, LoadFont, LoadLibrary, but not ReadTextFile Use consistently the opposites at the same level of abstraction: Use consistently the opposites at the same level of abstraction: LoadLibrary vs. UnloadLibrary, but not FreeHandle LoadLibrary vs. UnloadLibrary, but not FreeHandle OpenFile vs. CloseFile, but not DeallocateResource OpenFile vs. CloseFile, but not DeallocateResource GetName vs. SetName, but not AssignName GetName vs. SetName, but not AssignName 30

31 How long could be the name of a method? How long could be the name of a method? The name should be as long as required The name should be as long as required Don't abbreviate Don't abbreviate Your IDE has autocomplete Your IDE has autocomplete Examples: Examples: LoadCustomerSupportNotificationService, CreateMonthlyAndAnnualIncomesReport LoadCustomerSupportNotificationService, CreateMonthlyAndAnnualIncomesReport Incorrect examples: Incorrect examples: LoadCustSuppSrvc, CreateMonthIncReport LoadCustSuppSrvc, CreateMonthIncReport 31

32 Method parameters names Method parameters names Preferred form: [Noun] or [Adjective] + [Noun] Preferred form: [Noun] or [Adjective] + [Noun] Should be in camelCase Should be in camelCase Should be meaningful Should be meaningful Unit of measure should be obvious Unit of measure should be obvious Examples: firstName, report, usersList, fontSizeInPixels, speedKmH, font Examples: firstName, report, usersList, fontSizeInPixels, speedKmH, font Incorrect examples: p, p1, p2, populate, LastName, last_name, convertImage Incorrect examples: p, p1, p2, populate, LastName, last_name, convertImage 32

33 Variable names Variable names Should be in camelCase Should be in camelCase Preferred form: [Noun] or [Adjective] + [Noun] Preferred form: [Noun] or [Adjective] + [Noun] Should explain the purpose of the variable Should explain the purpose of the variable If you can't find good name for a variable check if it has a single purpose 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 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 Names should be consistent in the project 33

34 Examples: Examples: firstName, report, usersList, fontSize, maxSpeed, font, startIndex, endIndex, charsCount, configSettingsXml, config, dbConnection, sqlCommandCreateUser firstName, report, usersList, fontSize, maxSpeed, font, startIndex, endIndex, charsCount, configSettingsXml, config, dbConnection, sqlCommandCreateUser Incorrect examples: Incorrect examples: foo, bar, p, p1, p2, populate, LastName, last_name, LAST_NAME, convertImage, moveMargin, MAXSpeed, _firstName, __temp, firstNameMiddleNameAndLastName foo, bar, p, p1, p2, populate, LastName, last_name, LAST_NAME, convertImage, moveMargin, MAXSpeed, _firstName, __temp, firstNameMiddleNameAndLastName 34

35 The name should be addressed to the problem we solve, not to the means we use to solve it 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 Prefer nouns from the business domain to computer terms Examples: Examples: accounts, customers, customerAddress, accountHolder, paymentPlan, vipPlayer accounts, customers, customerAddress, accountHolder, paymentPlan, vipPlayer Incorrect examples: Incorrect examples: accountsLinkedList, customersHashtable, paymentsPriorityQueue, playersArray accountsLinkedList, customersHashtable, paymentsPriorityQueue, playersArray 35

36 Boolean variables should imply true or false Boolean variables should imply true or false Prefixes like is, has and can are useful Prefixes like is, has and can are useful Use positive boolean variable names Use positive boolean variable names Incorrect example: Incorrect example: Examples: Examples: hasPendingPayment, customerFound, validAddress, positiveBalance, isPrime hasPendingPayment, customerFound, validAddress, positiveBalance, isPrime Incorrect examples: Incorrect examples: notFound, run, programStop, player, list, findCustomerById, isUnsuccessfull notFound, run, programStop, player, list, findCustomerById, isUnsuccessfull 36 if (! notFound) { … }

37 Naming Counters Naming Counters Establish a convention, e.g. [Noun] + ' Count ' Establish a convention, e.g. [Noun] + ' Count ' Examples: ticketsCount, customersCount Examples: ticketsCount, customersCount State State Establish a convention, e.g. [Noun] + ' State ' Establish a convention, e.g. [Noun] + ' State ' Examples: blogParseState, threadState Examples: blogParseState, threadState Variables with small scope and span Variables with small scope and span Short names can be used, e.g. index, i, u Short names can be used, e.g. index, i, u 37

38 Do really temporary variables exist? Do really temporary variables exist? All variables in a program are temporary because they are used temporarily only during the program execution, right? 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 : Temporary variables can always be named better than temp or tmp : 38 // Swap a[i] and a[j] int temp = a[i]; a[i] = a[j]; a[j] = temp; // Swap a[i] and a[j] int oldValue = a[i]; a[i] = a[j]; a[j] = oldValue;

39 How long could be the name of a variable? How long could be the name of a variable? Depends on the variable scope and lifetime Depends on the variable scope and lifetime More "famous" variables should have longer and more self-explaining name More "famous" variables should have longer and more self-explaining name Acceptable naming examples: Acceptable naming examples: Unacceptable naming examples: Unacceptable naming examples: 39 for (int i=0; i

40 In C# prefix / suffix notations are not popular In C# prefix / suffix notations are not popular Hungarian notation Hungarian notation Using prefixes to denote the variable types, e.g. lpcstrText, lpdwFlags, cbMultiByte, hWnd Using prefixes to denote the variable types, e.g. lpcstrText, lpdwFlags, cbMultiByte, hWnd The Hungarian notation works well in unmanaged languages like C++ The Hungarian notation works well in unmanaged languages like C++ Do not use Hungarian notation in C# and.NET Do not use Hungarian notation in C# and.NET Don't use prefixes / suffixes to denote the variable data type Don't use prefixes / suffixes to denote the variable data type 40

41 Name properties in C# using a noun, noun phrase, or an adjective Name properties in C# using a noun, noun phrase, or an adjective Use Pascal Case Use Pascal Case Examples: Examples: Incorrect examples: Incorrect examples: 41 public int Length { … } public Color BackgroundColor { … } public CacheMode CacheMode { … } public bool Loaded { … } public int Load { … } public Color backgroundColor { … } public bool Font { … }

42 Use CAPITAL_LETTERS for const fields and PascalCase for readonly fields Use CAPITAL_LETTERS for const fields and PascalCase for readonly fields Use meaningful names that describe their value Use meaningful names that describe their value Examples: Examples: Incorrect examples: Incorrect examples: 42 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 = ">"; // GREATER_HTML_ENTITY public const int FONT_SIZE = 16; // 16pt or 16px? public const PageSize PAGE = PageSize.A4; // Maybe PAGE_SIZE?

43 Don't use numbers in the identifiers names Don't use numbers in the identifiers names Example: Example: PrintReport and PrintReport2 PrintReport and PrintReport2 What is the difference? What is the difference? Exceptions: Exceptions: When the number is part of the name itself, e.g. RS232Port, COM3, Win32APIFunctions When the number is part of the name itself, e.g. RS232Port, COM3, Win32APIFunctions Don't use Cyrillic or letters from other alphabets Don't use Cyrillic or letters from other alphabets E.g. FindСтудентByName, CalcΩ2Protein E.g. FindСтудентByName, CalcΩ2Protein 43

44 Giving a misleading name is worse than giving a totally unclear name Giving a misleading name is worse than giving a totally unclear name Example: Example: Consider a method that calculates the sum of all elements in an array Consider a method that calculates the sum of all elements in an array Its should be named Sum or CalculateSum Its should be named Sum or CalculateSum What about naming it CalculateAverage or Max or CheckForNegativeNumber ? What about naming it CalculateAverage or Max or CheckForNegativeNumber ? It's crazy, but be careful with "copy-paste" It's crazy, but be careful with "copy-paste" 44

45 Microsoft sometimes use really bad naming in their API libraries (especially in Win32 API) Microsoft sometimes use really bad naming in their API libraries (especially in Win32 API) Examples: Examples: Navigate and Navigate2 methods in Internet Explorer ActiveX control ( MSHTML.DLL ) Navigate and Navigate2 methods in Internet Explorer ActiveX control ( MSHTML.DLL ) WNetAddConnection3 method in Multiple Provider Router Networking API ( MPR.DLL ) WNetAddConnection3 method in Multiple Provider Router Networking API ( MPR.DLL ) LPWKSTA_USER_INFO_1 structure in Win32 LPWKSTA_USER_INFO_1 structure in Win32 Don't follow them blindly, just think a bit! Don't follow them blindly, just think a bit! 45

46 46 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.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()); Console.WriteLine(r.ReadInt32());}r.Close();fs.Close(); Source:

47

48 48 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 for (int i = 0; i < 11; i++){ Console.WriteLine (r.ReadInt32 ()) ;}r. Close ( ); fs. Close ( ) ; }

49 Good formatting goals Good formatting goals To improve code readability To improve code readability To improve code maintainability To improve code maintainability Fundamental principle of code formatting: Fundamental principle of code formatting: Any formatting style that follows the above principle is good Any formatting style that follows the above principle is good Any other formatting is not good Any other formatting is not good 49 The formating of the source code should disclose its logical structure.

50 Put { and } alone on a line under the corresponding parent block Put { and } alone on a line under the corresponding parent block Indent the block contents by a single [Tab] Indent the block contents by a single [Tab] Don't indent with spaces Don't indent with spaces Example: Example: 50 if ( some condition ) { // Block contents indented by a single [Tab] // Block contents indented by a single [Tab] // Don't use spaces for indentation // Don't use spaces for indentation}

51 Methods should be indented with a single [Tab] from the class body Methods should be indented with a single [Tab] from the class body Methods body should be indented with a single [Tab] as well Methods body should be indented with a single [Tab] as well 51 public class IndentationExample { private int Zero() private int Zero() { return 0; return 0; }} The entire method is indented with a single [Tab] Method body is also indented

52 Brackets in the method declaration should be formatted as follows: Brackets in the method declaration should be formatted as follows: Don't use spaces between the brackets: Don't use spaces between the brackets: The same applies for if -conditions and for - loops: The same applies for if -conditions and for - loops: 52 private static ulong CalcFactorial(uint num) if (condition) …

53 Separate method parameters by comma followed by a space Separate method parameters by comma followed by a space Don't put comma before the space Don't put comma before the space Examples: Examples: Incorrect examples: Incorrect examples: 53 private void RegisterUser(string username, string password) RegisterUser("nakov",

54 Use empty line for separation between methods: Use empty line for separation between methods: 54 public class Factorial { private static ulong CalcFactorial(uint num) private static ulong CalcFactorial(uint num) { if (num == 0) if (num == 0) return 1; return 1; else else return num * CalcFactorial(num - 1); return num * CalcFactorial(num - 1); } static void Main() static void Main() { ulong factorial = CalcFactorial(5); ulong factorial = CalcFactorial(5); Console.WriteLine(factorial); Console.WriteLine(factorial); }} Empty line Always use { and } after if (there is no space to do it here)

55 Use an empty line to separate logically related sequences of lines: Use an empty line to separate logically related sequences of lines: 55 private List PrepareReports() { List reports = new List (); List reports = new List (); // Create incomes reports // Create incomes reports Report incomesSalesReport = PrepareIncomesSalesReport(); Report incomesSalesReport = PrepareIncomesSalesReport(); reports.Add(incomesSalesReport); reports.Add(incomesSalesReport); Report incomesSupportReport = PrepareIncomesSupportReport(); Report incomesSupportReport = PrepareIncomesSupportReport(); reports.Add(incomesSupportReport); reports.Add(incomesSupportReport); // Create expenses reports // Create expenses reports Report expensesPayrollReport = PrepareExpensesPayrollReport(); Report expensesPayrollReport = PrepareExpensesPayrollReport(); reports.Add(expensesPayrollReport); reports.Add(expensesPayrollReport); Report expensesMarketingReport = PrepareExpensesMarketingReport(); Report expensesMarketingReport = PrepareExpensesMarketingReport(); reports.Add(expensesMarketingReport); reports.Add(expensesMarketingReport); return reports; return reports;} Empty line

56 56 public static void PrintList(List ints) { Console.Write("{ "); Console.Write("{ "); foreach (int item in ints) foreach (int item in ints) { Console.Write(item); Console.Write(item); Console.Write(" "); Console.Write(" "); } Console.WriteLine("}"); Console.WriteLine("}");} static void Main() { //... //...}

57 Formatting classes / structures / interfaces / enumerations Formatting classes / structures / interfaces / enumerations Indent the class body with a single [Tab] Indent the class body with a single [Tab] Use the following order of definitions: Use the following order of definitions: Constants, delegates, inner types, fields, constructors, properties, methods Constants, delegates, inner types, fields, constructors, properties, methods Static members, public members, protected members, internal members, private members Static members, public members, protected members, internal members, private members The above order of definitions is not the only possible correct one The above order of definitions is not the only possible correct one 57

58 58 public class Dog { // Static variables // Static variables public const string SPECIES = public const string SPECIES = "Canis Lupus Familiaris"; "Canis Lupus Familiaris"; // Instance variables // Instance variables private int age; private int age; // Constructors // Constructors public Dog(string name, int age) public Dog(string name, int age) { this.Name = name; this.Name = name; this.age = age; this.age = age; } (continues on the next slide)

59 59 // Properties // Properties public string Name { get; set; } public string Name { get; set; } // Methods // Methods public void Breath() public void Breath() { // TODO: breathing process // TODO: breathing process } public void Bark() public void Bark() { Console.WriteLine("wow-wow"); Console.WriteLine("wow-wow"); }}

60 Formatting conditional statements and loops Formatting conditional statements and loops Always use { } block after if / for / while, even when a single operator follows Always use { } block after if / for / while, even when a single operator follows Indent the block body after if / for / while Indent the block body after if / for / while Never put the block after if / for / while on the same line! Never put the block after if / for / while on the same line! Always put the { on the next line Always put the { on the next line Never indent with more than one [Tab] Never indent with more than one [Tab] 60

61 Example: Example: Incorrect examples: Incorrect examples: 61 for (int i=0; i<10; i++) { Console.WriteLine("i={0}", i); Console.WriteLine("i={0}", i);} for (int i=0; i<10; i++) Console.WriteLine("i={0}", 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); Console.WriteLine("i={0}", i);}

62 Break long lines after punctuation Break long lines after punctuation Indent the second line by single [Tab] Indent the second line by single [Tab] Do not additionally indent the third line Do not additionally indent the third line Examples: Examples: 62 DictionaryEntry newEntry = new DictionaryEntry ( new DictionaryEntry ( oldEntry.Key, oldEntry.Value); oldEntry.Key, oldEntry.Value); if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) matrix[x, y+1] == 0) { …

63 63 if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) 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+1, y] == 0 || matrix[x, y-1] == 0 || matrix[x, y+1] == 0) matrix[x, y+1] == 0) { … DictionaryEntry newEntry = new DictionaryEntry (oldEntry = new DictionaryEntry (oldEntry.Key, oldEntry.Value);.Key, oldEntry.Value);

64 All types of alignments are considered harmful All types of alignments are considered harmful Alignments are hard-to-maintain! Alignments are hard-to-maintain! Incorrect examples: Incorrect examples: 64 DateTime date = DateTime.Now.Date; int count = 0; Student student = new Strudent(); List students = new List (); matrix[x, y] == 0; matrix[x + 1, y + 1] == 0; matrix[2 * x + y, 2 * y + x] == 0; matrix[x * y, x * y] == 0;

65 How to Design High-Quality Classes? Abstraction, Cohesion and Coupling

66 Present a consistent level of abstraction in the class contract (publicly visible members) Present a consistent level of abstraction in the class contract (publicly visible members) What abstraction the class is implementing? What abstraction the class is implementing? Does it represent only one thing? Does it represent only one thing? Does the class name well describe its purpose? Does the class name well describe its purpose? Does the class define clear and easy to understand public interface? Does the class define clear and easy to understand public interface? Does the class hide all its implementation details? Does the class hide all its implementation details? 66

67 67 public class Font { public string Name { get; set; } public string Name { get; set; } public float SizeInPoints { get; set; } public float SizeInPoints { get; set; } public FontStyle Style { get; set; } public FontStyle Style { get; set; } public Font(string name, float sizeInPoints, FontStyle style) public Font(string name, float sizeInPoints, FontStyle style) { this.Name = name; this.Name = name; this.SizeInPoints = sizeInPoints; this.SizeInPoints = sizeInPoints; this.Style = style; this.Style = style; } public void DrawString(DrawingSurface surface, public void DrawString(DrawingSurface surface, string str, int x, int y) {... } string str, int x, int y) {... } public Size MeasureString(string str) {... } public Size MeasureString(string str) {... }}

68 68 public class Program { public string title; public string title; public int size; public int size; public Color color; public Color color; public void InitializeCommandStack(); public void InitializeCommandStack(); public void PushCommand(Command command); public void PushCommand(Command command); public Command PopCommand(); public Command PopCommand(); public void ShutdownCommandStack(); public void ShutdownCommandStack(); public void InitializeReportFormatting(); public void InitializeReportFormatting(); public void FormatReport(Report report); public void FormatReport(Report report); public void PrintReport(Report report); public void PrintReport(Report report); public void InitializeGlobalData(); public void InitializeGlobalData(); public void ShutdownGlobalData(); public void ShutdownGlobalData();} Does this class really represent a "program"? Is this name good? Does this class really have a single purpose?

69 Define operations along with their opposites Define operations along with their opposites Example: Example: Open() and Close() Open() and Close() Move unrelated methods in another class Move unrelated methods in another class Example: Example: In class Employee if you need to calculate Age by given DateOfBirth In class Employee if you need to calculate Age by given DateOfBirth Create static method CalcAge in a separate class DateUtils Create static method CalcAge in a separate class DateUtils 69

70 Beware of breaking the interface abstraction due to evolution Beware of breaking the interface abstraction due to evolution Don't add public members inconsistent with class abstraction 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 Example: in class called Employee at some time we add method for accessing the DB with SQL 70 class Employee { public string firstName; public string firstName; public string lastName; public string lastName; … public SqlCommand FindByPrimaryKeySqlCommand(int id); public SqlCommand FindByPrimaryKeySqlCommand(int id);}

71 Minimize the visibility of classes and members Minimize the visibility of classes and members Start from private and move to internal, protected and public if required Start from private and move to internal, protected and public if required Classes should hide their implementation details Classes should hide their implementation details Anything which is not part of the class interface should be declared private 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 Classes with good encapsulated classes are: less complex, easier to maintain, more loosely coupled Never declare fields public (except constants) Never declare fields public (except constants) Use methods or properties to access fields Use methods or properties to access fields 71

72 Don't violate encapsulation semantically! Don't violate encapsulation semantically! Don't rely on non-documented internal behavior or side effects Don't rely on non-documented internal behavior or side effects Wrong example: Wrong example: Skip calling ConnectToDB() because you just called FindEmployeeById() which should open connection Skip calling ConnectToDB() because you just called FindEmployeeById() which should open connection Another wrong example: Another wrong example: Use String.Empty instead of Titles.NoTitle because you know both values are the same Use String.Empty instead of Titles.NoTitle because you know both values are the same 72

73 Don't hide methods in a subclass Don't hide methods in a subclass Example: if the class Timer has private method Start(), don't define Start() in AtomTimer 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 Move common interfaces, data, and behavior as high as possible in the inheritance tree This maximizes the code reuse This maximizes the code reuse Be suspicious of base classes of which there is only one derived class Be suspicious of base classes of which there is only one derived class Do you really need this additional level of inheritance? Do you really need this additional level of inheritance? 73

74 Be suspicious of classes that override a routine and do nothing inside Be suspicious of classes that override a routine and do nothing inside Is the overridden routine used correctly? Is the overridden routine used correctly? Avoid deep inheritance trees Avoid deep inheritance trees Don't create more than 6 levels of inheritance Don't create more than 6 levels of inheritance Avoid using a base classs protected data fields in a derived class Avoid using a base classs protected data fields in a derived class Provide protected accessor methods or properties instead Provide protected accessor methods or properties instead 74

75 Prefer inheritance to extensive type checking: Prefer inheritance to extensive type checking: Consider inheriting Circle and Square from Shape and override the abstract action Draw() Consider inheriting Circle and Square from Shape and override the abstract action Draw() 75 switch (shape.Type) { case Shape.Circle: case Shape.Circle: shape.DrawCircle(); shape.DrawCircle(); break; break; case Shape.Square: case Shape.Square: shape.DrawSquare(); shape.DrawSquare(); break; break;......}

76 Keep the number of methods in a class as small as possible reduce complexity Keep the number of methods in a class as small as possible reduce complexity Minimize direct method calls to other classes Minimize direct method calls to other classes Minimize indirect method calls to other classes Minimize indirect method calls to other classes Less external method calls == less coupling Less external method calls == less coupling Minimize the extent to which a class collaborates with other classes Minimize the extent to which a class collaborates with other classes Reduce coupling between classes Reduce coupling between classes 76

77 Initialize all member data in all constructors, if possible Initialize all member data in all constructors, if possible Uninitialized data is error prone Uninitialized data is error prone Partially initialized data is even more evil Partially initialized data is even more evil Incorrect example: assign FirstName in class Person but leave LastName empty Incorrect example: assign FirstName in class Person but leave LastName empty Initialize data members in the same order in which they are declared Initialize data members in the same order in which they are declared Prefer deep copies to shallow copies ( ICloneable should make deep copy) Prefer deep copies to shallow copies ( ICloneable should make deep copy) 77

78 Use private constructor to prohibit direct class instantiation Use private constructor to prohibit direct class instantiation Use deign patterns for common design situations Use deign patterns for common design situations Creational patterns like singleton, factory method, abstract factory Creational patterns like singleton, factory method, abstract factory Structural patterns like adapter, bridge, composite, decorator, façade Structural patterns like adapter, bridge, composite, decorator, façade Behavioral patterns like command, iterator, observer, strategy, template method Behavioral patterns like command, iterator, observer, strategy, template method 78

79 Model real-world objects with OOP classes Model real-world objects with OOP classes Model abstract objects, processes, etc. Model abstract objects, processes, etc. Reduce complexity Reduce complexity Work at higher level Work at higher level Isolate complexity Isolate complexity Hide it in a class Hide it in a class Hide implementation details encapsulation Hide implementation details encapsulation Limit effects of changes Limit effects of changes Changes affect only their class Changes affect only their class 79

80 Hide global data Hide global data Work through methods Work through methods Group variables that are used together Group variables that are used together Make central points of control Make central points of control Single task should be done at single place Single task should be done at single place Avoid duplicating code Avoid duplicating code Facilitate code reuse Facilitate code reuse Use class hierarchies and virtual methods Use class hierarchies and virtual methods Package related operations together Package related operations together 80

81 Group related classes together in namespaces Group related classes together in namespaces Follow consistent naming convention Follow consistent naming convention 81 namespace Utils { class MathUtils { … } class MathUtils { … } class StringUtils { … } class StringUtils { … } class DateUtils { … } class DateUtils { … }} namespace DataAccessLayer { class GenericDAO { … } class GenericDAO { … } class EmployeeDAO { … } class EmployeeDAO { … } class AddressDAO { … } class AddressDAO { … }}

82 Live Demo

83 The bible of high-quality software construction: The bible of high-quality software construction: 83 Code Complete, 2 nd edition, Steve McConnell, Microsoft Press, 2004, ISBN , Code Complete, 2 nd edition, Steve McConnell, Microsoft Press, 2004, ISBN , The "High-Quality Programming Code" course at Telerik Academy: The "High-Quality Programming Code" course at Telerik Academy:

84 Questions?Questions?

85 1. You are given a source code trying to solve the "Game 15" puzzle. Your task is to improve the code quality without changing its functionality (only bug fixes are allowed): a)Reformat the code following the guidelines defined in the "Code Formatting" section. b)Following the guidelines in the "Naming Identifiers" section rename the identifiers in the program: solution name, project name, class names, method names, parameter names, variables, etc. c)Split the functionality into classes with good abstraction and strong cohesion. 85


Download ppt "Revealing the Secrets of Self-Documenting Code Svetlin Nakov Telerik Corporation www.telerik.com For C# Developers."

Similar presentations


Ads by Google