high-quality programming code construction

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

Upload: lucio

Post on 23-Mar-2016

37 views

Category:

Documents


0 download

DESCRIPTION

High-Quality Programming Code Construction. Revealing the Secrets of Self-Documenting Code. 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. - PowerPoint PPT Presentation

TRANSCRIPT

High-Quality Programming Code Construction

High-Quality Programming Code ConstructionRevealing the Secrets of Self-Documenting CodeSvetlin Nakov

Telerik Corporation

www.telerik.comFor C# Developers

Table of ContentsWhat is High-Quality Programming Code?Naming IdentifiersNaming classes, methods, variables, etc.Code FormattingDesigning High-Quality ClassesHigh-Quality MethodsCohesion and CouplingUsing Variables CorrectlyUsing Expressions Correctly2

Table of Contents (2)Using ConstantsUsing Control-Flow Constructs CorrectlyConditional StatementsLoopsDefensive ProgrammingAssertions and ExceptionsComments and DocumentationCode Refactoring3

What is High-Quality Programming Code?

Why the Code Quality Is Important?What does this code do? Is it correct?5static 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!"); }}

Why the Code Quality Is Important? (2)Now the code is formatted, but is still unclear.6static 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!");}

Software QualityExternal qualityDoes the software behave correctly?Are the produced results correct?Does the software run fast?Is the software UI easy-to-use?Internal qualityIt 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 understandEasy to modify and maintainCorrect behavior in all casesWell testedWell architectured and designedWell documentedSelf-documenting code Well formatted8

Code ConventionsCode conventions are formal guidelines about the style of the source code:Code formatting conventionsIndentation, whitespace, etc.Naming conventionsPascalCase or camelCase, prefixes, suffixes, etc.Best practicesClasses, interfaces, enumerations, structures, inheritance, exceptions, properties, events, constructors, fields, operators, etc.9

Code Conventions (2)Microsoft has official code conventions calledDesign Guidelines for Developing Class Libraries: http://msdn.microsoft.com/en-us/library/ms229042.aspxLarge organizations follow strict conventionsCode conventions can vary in different teamsMost conventions developers follow the official Microsoft's recommendations but extend themHigh-quality code goes beyond code conventionsSoftware quality is not just a set of conventions its is a way of thinking10Naming IdentifiersNaming Classes, Interfaces, Enumerations, Methods, Variables and Constants

General Naming GuidelinesAlways use EnglishHow you will feel if you read Vietnamese code with variables named in Vietnamese?English is the only language that all software developers speakAvoid abbreviationsExample: scrpCnt vs. scriptsCountAvoid hard-to-pronounce namesExample: dtbgRegExPtrn vs. dateTimeBulgarianRegExPattern12

Use Meaningful NamesAlways prefer using meaningful namesNames 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, CreateReportIncorrect examples: k, k2, k3, junk, f33, KJJ, button1, variable, temp, tmp, temp_var, something, someValue13

Fake Meaningful NamesJunior developers often use meaningful names that are in fact meaninglessBad naming examples:Topic6Exercise12, LoopsExercise12, Problem7, OOPLecture_LastExerciseYes, Topic6Exercise12 indicates that this is solution to exercise 12, but what is it about?Better naming:MaximalNumbersSubsequence14

Naming TypesNaming types (classes, structures, etc.)Use PascalCase character casingExamples:RecursiveFactorialCalculator, TreeSet, XmlDocument, IEnumerable, Color, TreeNode, InvalidTransactionException, MainFormIncorrect examples: recursiveFactorialCalculator, recursive_factorial_calculator, RECURSIVE_FACTORIAL_CALCULATOR15Naming Classes and StructuresUse the following formats:[Noun][Adjective] + [Noun]Examples:Student, FileSystem, BinaryTreeNode, Constants, MathUtils, TextBox, CalendarIncorrect examples:Move, FindUsers, Fast, Optimize, Extremly, FastFindInDatabase, Check16

Naming InterfacesFollowing formats are acceptable:'I' + [Verb] + 'able''I' + [Noun], 'I' + [Adjective] + [Noun]Examples:IEnumerable, IFormattable, IDataReader, IList, IHttpModule, ICommandExecutorIncorrect examples:List, FindUsers, IFast, IMemoryOptimize, Optimizer, FastFindInDatabase, CheckBox17

Naming EnumerationsSeveral formats are acceptable:[Noun] or [Verb] or [Adjective]Use the same style for all membersExamples: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 ClassesExceptionsAdd 'Exception' as suffixUse informative nameExample: FileNotFoundExceptionIncorrect example: FileNotFoundErrorDelegate ClassesAdd 'Delegate' or 'EventHandler' as suffixExample: DownloadFinishedDelegateIncorrect example: WakeUpNotification19

The Length of Class NamesHow long could be the name of a class / struct / interface / enum?The name should be as long as requiredDon't abbreviate the names if this could make them unclearYour IDE has autocomplete, right?Examples: FileNotFoundException, CustomerSupportNotificationServiceIncorrect examples: FNFException, CustSuppNotifSrvc20

Naming NamespacesNamespaces naming guidelinesUse PascalCaseFollowing formats are acceptable:Company . Product . Component . Product . Component . Example:Telerik.WinControls.GridViewIncorrect example: Telerik_WinControlsGridView, Classes21

Naming AssembliesAssembly names should follow the root namespace in its class hierarchyExamples:Telerik.WinControls.GridView.dllOracle.DataAccess.dllInterop.CAPICOM.dllIncorrect examples:Telerik_WinControlsGridView.dllOracleDataAccess.dll22

Naming MethodsMethods naming guidelinesMethod names should be meaningfulShould answer the question:What does this method do?If you cannot find a good name for a method, think about does it have clear intentExamples: FindStudent, LoadReport, SinusIncorrect examples: Method1, DoSomething, HandleStuff, SampleMethod, DirtyHack23

Naming Methods (2)Use PascalCase character casingExample: LoadSettings, not loadSettingsPrefer the following formats:[Verb][Verb] + [Noun], [Verb] + [Adjective] + [Noun]Examples: Show, LoadSettingsFile, FindNodeByPattern, ToString, PrintListIncorrect examples: Student, Counter, White, Generator, Approximation, MathUtils24

Methods Returning a ValueMethods returning values should describe the returned valueExamples:ConvertMetersToInches, not MetersInches or Convert or ConvertUnitMeters2Inches is still acceptableCalculateSinus is goodSinus is still acceptableEnsure that the unit of measure of obviousPrefer MeasureFontInPixels to MeasureFont25

Single Purpose of All MethodsMethods should have a single purpose!Otherwise they cannot be named wellHow 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 namedNeed to be refactored instead of named26Consistency in Methods NamingUse consistent naming in the entire projectLoadFile, LoadImageFromFile, LoadSettings, LoadFont, LoadLibrary, but not ReadTextFileUse consistently the opposites at the same level of abstraction:LoadLibrary vs. UnloadLibrary, but not FreeHandleOpenFile vs. CloseFile, but not DeallocateResourceGetName vs. SetName, but not AssignName27

The Length of Method NamesHow long could be the name of a method?The name should be as long as requiredDon't abbreviateYour IDE has autocompleteExamples:LoadCustomerSupportNotificationService, CreateMonthlyAndAnnualIncomesReportIncorrect examples:LoadCustSuppSrvc, CreateMonthIncReport28

Naming Method ParametersMethod parameters namesPreferred form: [Noun] or [Adjective] + [Noun]Should be in camelCaseShould be meaningfulUnit of measure should be obviousExamples: firstName, report, usersList, fontSizeInPixels, speedKmH, fontIncorrect examples: p, p1, p2, populate, LastName, last_name, convertImage29

Naming VariablesVariable namesShould be in camelCasePreferred form: [Noun] or [Adjective] + [Noun]Should explain the purpose of the variableIf you can't find good name for a variable check if it has a single purposeException: variables with very small scope, e.g. the index variable in a 3-lines long for-loopNames should be consistent in the project30

Naming Variables ExampleExamples:firstName, report, usersList , fontSize, maxSpeed, font, startIndex, endIndex, charsCount, configSettingsXml, config, dbConnection, createUserSqlCommandIncorrect examples:foo, bar, p, p1, p2, populate, LastName, last_name, LAST_NAME, convertImage, moveMargin, MAXSpeed, _firstName, __temp, firstNameMiddleNameAndLastName31

More about Naming VariablesThe name should be addressed to the problem we solve, not to the means we use to solve itPrefer nouns from the business domain to computer termsExamples:accounts, customers, customerAddress, accountHolder, paymentPlan, vipPlayerIncorrect examples:accountsLinkedList, customersHashtable, paymentsPriorityQueue, playersArray32Naming Boolean VariablesBoolean variables should imply true or falsePrefixes like is, has and can are usefulUse positive boolean variable namesIncorrect example:Examples:hasPendingPayment, customerFound, validAddress, positiveBalance, isPrimeIncorrect examples:notFound, run, programStop, player, list, findCustomerById, isUnsuccessfull33if (! notFound) { }Naming Special VariablesNaming CountersEstablish a convention, e.g. [Noun] + 'Count'Examples: ticketsCount, customersCountStateEstablish a convention, e.g. [Noun] + 'State'Examples: blogParseState, threadStateVariables with small scope and spanShort names can be used, e.g. index, i, u34

Temporary VariablesDo 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:35// 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;The Length of Variable NamesHow long could be the name of a variable?Depends on the variable scope and lifetimeMore "famous" variables should have longer and more self-explaining nameAcceptable naming examples:

Unacceptable naming examples:36for (int i=0; i= 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 PracticesChoose a good name for your exception classIncorrect example:

Example:

Use descriptive error messagesIncorrect example:Example:144throw 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 correctlyDo not catch all exceptions!Incorrect example:

What about OutOfMemoryException?145try{ ReadSomeFile();}catch{ Console.WriteLine("File not found!");}Exceptions Handling Best Practices (3)Always include the exception cause when throwing a new exception146try{ 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 abstractionExample: Bank account withdrawal operation could throw InsufficientFundsException but cannot throw FileAccessDeniedExceptionDisplay to the end users only messages that they could understand

147

orDisposable ResourcesHandle disposable resources with careAll classes implementing IDisposable should follow the try-finally / using pattern:148StreamReader 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 DocumentationThe Concept of Self-Documenting CodeEffective CommentsEffective comments do not repeat the codeThey explain it at higher level and reveal non-obvious detailsThe best software documentation is the source code itself keep it clean and readableSelf-documenting code is code that is self-explainable and does not need commentsSimple design, small well named methods, strong cohesion and loose coupling, simple logic, good variable names, good formatting, 150Self-Documenting CodeSelf-documenting code fundamental principles151The best documentation is the code itself. Do not document bad code, rewrite it!Make the code self-explainable and self-documenting, easy to read and understand.

Bad Comments Example152public static List FindPrimes(int start, int end){ // Create new list of integers List primesList = new List(); // Perform a loop from start to end for (int num = start; num