High-Quality High-Quality Programming Code Programming Code
Construction – Part IConstruction – Part IRevealing the Secrets of Self-Revealing the Secrets of Self-
Documenting CodeDocumenting Code
Svetlin NakovSvetlin NakovTelerik Telerik
CorporationCorporationwww.telerik.com
For C# DevelopersFor C# Developers
Table of ContentsTable of Contents What is High-Quality Programming What is High-Quality Programming
Code?Code? External and Internal Code QualityExternal and Internal Code Quality
Naming IdentifiersNaming Identifiers Naming Types, Classes, Interfaces, Naming Types, Classes, Interfaces,
Enumerations, Properties, Methods, Enumerations, Properties, Methods, Parameters, Variables, Constants, etc.Parameters, Variables, Constants, etc.
Code FormattingCode Formatting Designing High-Quality ClassesDesigning High-Quality Classes
Abstraction, Encapsulation,Abstraction, Encapsulation, Inheritance, Reasons to Create a ClassInheritance, Reasons to Create a Class
2
What is High-Quality What is High-Quality Programming Code?Programming Code?
Why the Code Quality Is Why the Code Quality Is Important?Important?
What does this code do? Is it correct?What does this code do? Is it correct?
4
static void Main()static void Main(){{ int value=010, i=5, w;int value=010, i=5, w; switch(value){case switch(value){case 10:w=5;Console.WriteLine(w);break;case 9:i=0;break;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 for (int k = 0; k < i; k++, Console.WriteLine(k - 'f'));break;} { Console.WriteLine("loop!"); }- 'f'));break;} { Console.WriteLine("loop!"); }}}
Why the Code Quality Is Why the Code Quality Is Important? (2)Important? (2)
Now the code is formatted, but is still unclear.Now the code is formatted, but is still unclear.5
static void Main()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 - for (int k = 0; k < i; k++, Console.WriteLine(k - 'f')) ; 'f')) ; break;break; }} Console.WriteLine("loop!");Console.WriteLine("loop!");}}
Software QualitySoftware Quality External qualityExternal quality
Does the software behave correctly?Does the software behave correctly? Are the produced results correct?Are the produced results correct? Does the software runDoes the software run fast?fast? Is the software UI easy-to-use?Is the software UI easy-to-use?
Internal qualityInternal quality It the code easy to read and It the code easy to read and
understand?understand? It the code well structured?It the code well structured? Is the code easy to modify?Is the code easy to modify?
6
What is High-Quality What is High-Quality Programming Code?Programming Code?
High-quality programming code:High-quality programming code: Easy to read and understandEasy to read and understand
Easy to modify and maintainEasy to modify and maintain
Correct behavior in all casesCorrect behavior in all cases Well testedWell tested
Well architectured and designedWell architectured and designed Well documentedWell documented
Self-documenting code Self-documenting code
Well formattedWell formatted7
Code ConventionsCode Conventions Code conventionsCode conventions are formal guidelines are formal guidelines
about the style of the source code:about the style of the source code: Code formatting conventionsCode formatting conventions
Indentation, whitespace, etc.Indentation, whitespace, etc.
Naming conventionsNaming conventions PascalCasePascalCase or or camelCasecamelCase, prefixes, suffixes, , prefixes, suffixes,
etc.etc.
Best practicesBest practices Classes, interfaces, enumerations, Classes, interfaces, enumerations,
structures, inheritance, exceptions, structures, inheritance, exceptions, properties, events, constructors, fields, properties, events, constructors, fields, operators, etc.operators, etc.
8
Code Conventions (2)Code Conventions (2) Microsoft has official code conventions calledMicrosoft has official code conventions called
Design Guidelines for Developing Class Design Guidelines for Developing Class Libraries: Libraries: http://msdn.microsoft.com/en-us/library/ms229042.aspx
Large organizations follow strict Large organizations follow strict conventionsconventions Code conventions can vary in different teamsCode conventions can vary in different teams
Most conventions developers follow the official Most conventions developers follow the official Microsoft's recommendations but extend themMicrosoft's recommendations but extend them
High-quality code goes beyond code High-quality code goes beyond code conventionsconventions Software quality is not just a set of Software quality is not just a set of
conventions – its is a way of thinkingconventions – its is a way of thinking 9
Managing ComplexityManaging Complexity Managing complexity Managing complexity plays a central role plays a central role
in software constructionin software construction Minimize the amount of complexity that Minimize the amount of complexity that
anyone’s brain has to deal with at certain anyone’s brain has to deal with at certain time time
Architecture and design challengesArchitecture and design challenges Design modules and classes to reduce Design modules and classes to reduce
complexitycomplexity Code construction challengesCode construction challenges
Apply good software construction Apply good software construction practices: classes, methods, variables, practices: classes, methods, variables, naming, statements, error handling, naming, statements, error handling, formatting, comments, etc.formatting, comments, etc. 10
Managing Complexity Managing Complexity (2)(2)
Key to being an effective Key to being an effective programmer:programmer: Maximizing the portion of a Maximizing the portion of a
program that you can safely ignore program that you can safely ignore while working on any one section of while working on any one section of codecode
Most practices discussed later Most practices discussed later propose ways to achieve this propose ways to achieve this important goalimportant goal
11
Key Key Characteristics Characteristics of High-Quality of High-Quality
CodeCode Correct behaviorCorrect behavior
Conforming to the requirementsConforming to the requirements Stable, no hangs, no crashesStable, no hangs, no crashes Bug freeBug free Correct response to incorrect usageCorrect response to incorrect usage
Easy to readEasy to read Easy to understandEasy to understand Maintainable – easy to modify Maintainable – easy to modify
when requiredwhen required 12
Naming IdentifiersNaming IdentifiersNaming Classes, Interfaces, Naming Classes, Interfaces,
Enumerations, Methods, Variables Enumerations, Methods, Variables and Constantsand Constants
General Naming General Naming GuidelinesGuidelines
Always use EnglishAlways use English How you will feel if you read How you will feel if you read
Vietnamese code with variables Vietnamese code with variables named in Vietnamese?named in Vietnamese?
English is the only language that all English is the only language that all software developers speaksoftware developers speak
Avoid abbreviationsAvoid abbreviations Example: Example: scrpCntscrpCnt vs. vs. scriptsCountscriptsCount
Avoid hard-to-pronounce namesAvoid hard-to-pronounce names Example: Example: dtbgRegExPtrndtbgRegExPtrn vs. vs. dateTimeBulgarianRegExPatterndateTimeBulgarianRegExPattern 14
Use Meaningful NamesUse Meaningful Names Always prefer using meaningful namesAlways prefer using meaningful names
Names should answer these questions:Names should answer these questions: What does this class do? What is the intent What does this class do? What is the intent
of this variable? What is this variable / class of this variable? What is this variable / class used for?used for?
Examples:Examples: FactorialCalculatorFactorialCalculator, , studentsCountstudentsCount, , Math.PIMath.PI, , configFileNameconfigFileName, , CreateReportCreateReport
Incorrect examples: Incorrect examples: kk, , k2k2,, k3k3,, junkjunk,, f33f33,, KJJKJJ,, button1button1, , variablevariable,, temp temp, , tmptmp, , temp_vartemp_var, , somethingsomething, , someValuesomeValue
15
Names Should be Names Should be Meaningful in Their Meaningful in Their
ContextContext Whether a name is meaningful or not Whether a name is meaningful or not
depends on its context (its enclosing type)depends on its context (its enclosing type) Examples of meaningful names:Examples of meaningful names:
Generate()Generate() in the class in the class LabyrinthGeneratorLabyrinthGenerator
Find(stringFind(string fileName)fileName) in the class in the class FileFinderFileFinder
Deposit(decimalDeposit(decimal amount)amount) in the class in the class AccountAccount Examples of meaningless names:Examples of meaningless names:
Generate()Generate() in the class in the class ProgramProgram
Find(stringFind(string fileName)fileName) in the class in the class ProgramProgram
16
Fake Meaningful NamesFake Meaningful Names Junior developers often use Junior developers often use
meaningful names that are in fact meaningful names that are in fact meaninglessmeaningless Bad naming examples:Bad naming examples:
Topic6Exercise12Topic6Exercise12, , LoopsExercise12LoopsExercise12,, Problem7Problem7, , OOPLecture_LastExerciseOOPLecture_LastExercise
Yes, Yes, Topic6Exercise12Topic6Exercise12 indicates that indicates that this is solution to exercise 12, but this is solution to exercise 12, but what is it about?what is it about?
Better naming:Better naming: MaximalNumbersSubsequenceMaximalNumbersSubsequence 17
Naming TypesNaming Types Naming types (classes, structures, Naming types (classes, structures,
etc.)etc.) Use Use PascalCasePascalCase character casing character casing Examples:Examples:
RecursiveFactorialCalculatorRecursiveFactorialCalculator, , TreeSetTreeSet, , XmlDocumentXmlDocument, , IEnumerableIEnumerable, , ColorColor, , TreeNodeTreeNode, , InvalidTransactionExceptionInvalidTransactionException, , MainFormMainForm
Incorrect examples: Incorrect examples: recursiveFactorialCalculatorrecursiveFactorialCalculator, , recursive_factorial_calculatorrecursive_factorial_calculator, , RECURSIVE_FACTORIAL_CALCULATORRECURSIVE_FACTORIAL_CALCULATOR 18
Naming Classes and Naming Classes and StructuresStructures
Use the following formats:Use the following formats: [Noun][Noun] [Adjective] + [Noun][Adjective] + [Noun]
Examples:Examples: StudentStudent, , FileSystemFileSystem, , BinaryTreeNodeBinaryTreeNode, , ConstantsConstants, , MathUtilsMathUtils, , TextBoxTextBox, , CalendarCalendar
Incorrect examples:Incorrect examples: MoveMove, , FindUsersFindUsers, , FastFast, , OptimizeOptimize, , ExtremlyExtremly, , FastFindInDatabaseFastFindInDatabase, , CheckCheck
19
Naming InterfacesNaming Interfaces Following formats are acceptable:Following formats are acceptable:
''II' + [Verb] + '' + [Verb] + 'ableable'' ''II' + [Noun], '' + [Noun], 'II' + [Adjective] + [Noun]' + [Adjective] + [Noun]
Examples:Examples: IEnumerableIEnumerable, , IFormattableIFormattable, , IDataReaderIDataReader,, IList IList, , IHttpModuleIHttpModule,, ICommandExecutorICommandExecutor
Incorrect examples:Incorrect examples: ListList, , FindUsersFindUsers, , IFastIFast, , IMemoryOptimizeIMemoryOptimize, , OptimizerOptimizer, , FastFindInDatabaseFastFindInDatabase, , CheckBoxCheckBox 20
Naming EnumerationsNaming Enumerations Several formats are acceptable:Several formats are acceptable:
[Noun] or [Verb] or [Adjective][Noun] or [Verb] or [Adjective] Use the same style for all membersUse the same style for all members Examples:Examples:
enum Day {Monday,enum Day {Monday, Tuesday,Tuesday, Wednesday,Wednesday, …}…}, , enum AppState {Running,enum AppState {Running, Finished,Finished, …}…}, ,
enum WindowState {Normal,enum WindowState {Normal, Maximized,Maximized, …}…}
Incorrect examples:Incorrect examples: enum Color {red, green, blue, white}enum Color {red, green, blue, white}, , enum PAGE_FORMAT {A4, A5, A3, LEGAL, …}enum PAGE_FORMAT {A4, A5, A3, LEGAL, …}
21
Naming Special ClassesNaming Special Classes ExceptionsExceptions
Add Add ''ExceptionException' as suffix' as suffix
Use informative nameUse informative name
Example: Example: FileNotFoundExceptionFileNotFoundException
Incorrect example: Incorrect example: FileNotFoundErrorFileNotFoundError Delegate ClassesDelegate Classes
Add Add ''DelegateDelegate' or '' or 'EventHandlerEventHandler' as ' as suffixsuffix
Example: Example: DownloadFinishedDelegateDownloadFinishedDelegate
Incorrect example: Incorrect example: WakeUpNotificationWakeUpNotification22
The Length of Class The Length of Class NamesNames
How long could be the name of a class How long could be the name of a class / struct / interface / enum?/ struct / interface / enum? The name should be as long as The name should be as long as
requiredrequired Don't abbreviate the names if this Don't abbreviate the names if this
could make them unclearcould make them unclear Your IDE has autocomplete, right?Your IDE has autocomplete, right?
Examples: Examples: FileNotFoundExceptionFileNotFoundException, , CustomerSupportNotificationServiceCustomerSupportNotificationService
Incorrect examples: Incorrect examples: FNFExceptionFNFException, , CustSuppNotifSrvcCustSuppNotifSrvc
23
Naming NamespacesNaming Namespaces Namespaces naming guidelinesNamespaces naming guidelines
Use PascalCaseUse PascalCase Following formats are acceptable:Following formats are acceptable:
Company.Product.Component. …Company.Product.Component. … Product.Component.…Product.Component.…
Example:Example: Telerik.WinControls.GridViewTelerik.WinControls.GridView
Incorrect example:Incorrect example: Telerik_WinControlsGridViewTelerik_WinControlsGridView, , ClassesClasses
24
Naming AssembliesNaming Assemblies Assembly names should follow the Assembly names should follow the
root namespace in its class root namespace in its class hierarchyhierarchy
Examples:Examples: Telerik.WinControls.GridView.dllTelerik.WinControls.GridView.dll Oracle.DataAccess.dllOracle.DataAccess.dll Interop.CAPICOM.dllInterop.CAPICOM.dll
Incorrect examples:Incorrect examples: Telerik_WinControlsGridView.dllTelerik_WinControlsGridView.dll OracleDataAccess.dllOracleDataAccess.dll 25
Naming MethodsNaming Methods Methods naming guidelinesMethods naming guidelines
Method names should be meaningfulMethod 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 If you cannot find a good name for a method, think about does it have clear method, think about does it have clear intentintent
Examples: Examples: FindStudentFindStudent, , LoadReportLoadReport, , SinusSinus Incorrect examples: Incorrect examples: Method1Method1, , DoSomethingDoSomething, , HandleStuffHandleStuff, , SampleMethodSampleMethod, , DirtyHackDirtyHack
26
Naming Methods (2)Naming Methods (2) Use PascalCase character casingUse PascalCase character casing
Example: Example: LoadSettingsLoadSettings, not , not loadSettingsloadSettings Prefer the following formats:Prefer the following formats:
[Verb][Verb] [Verb] + [Noun], [Verb] + [Adjective] + [Verb] + [Noun], [Verb] + [Adjective] +
[Noun][Noun] Examples: Examples: ShowShow, , LoadSettingsFileLoadSettingsFile, , FindNodeByPatternFindNodeByPattern, , ToStringToString, , PrintListPrintList
Incorrect examples: Incorrect examples: StudentStudent, , CounterCounter, , WhiteWhite, , GeneratorGenerator, , ApproximationApproximation, , MathUtilsMathUtils
27
Methods Returning a Methods Returning a ValueValue
Methods returning values should Methods returning values should describe the returned valuedescribe the returned value
Examples:Examples: ConvertMetersToInchesConvertMetersToInches, not , not MetersInchesMetersInches
or or ConvertConvert or or ConvertUnitConvertUnit Meters2InchesMeters2Inches is still acceptable is still acceptable CalculateSinusCalculateSinus is good is good
SinusSinus is also acceptable is also acceptable
Ensure that the unit of measure of Ensure that the unit of measure of obviousobvious
Prefer Prefer MeasureFontInPixelsMeasureFontInPixels to to MeasureFontMeasureFont28
Single Purpose of All Single Purpose of All MethodsMethods
Methods should have a single purpose!Methods should have a single purpose! Otherwise they cannot be named wellOtherwise they cannot be named well How to name a method that creates How to name a method that creates
annual incomes report, downloads annual incomes report, downloads updates from internet and scans the updates from internet and scans the system for viruses?system for viruses?
CreateAnnualIncomesReportDownloadUpdatCreateAnnualIncomesReportDownloadUpdatesAndScanForVirusesesAndScanForViruses is a nice name, is a nice name, right?right?
Methods that have multiple purposes Methods that have multiple purposes (weak cohesion) are hard to be named(weak cohesion) are hard to be named Need to be refactored instead of namedNeed to be refactored instead of named 29
Consistency in Methods Consistency in Methods NamingNaming
Use consistent naming in the entire Use consistent naming in the entire projectproject LoadFileLoadFile, , LoadImageFromFileLoadImageFromFile, , LoadSettingsLoadSettings, , LoadFontLoadFont, , LoadLibraryLoadLibrary, but not , but not ReadTextFileReadTextFile
Use consistently the opposites at the Use consistently the opposites at the same level of abstraction:same level of abstraction: LoadLibraryLoadLibrary vs. vs. UnloadLibraryUnloadLibrary, but not , but not FreeHandleFreeHandle
OpenFileOpenFile vs. vs. CloseFileCloseFile, but not , but not DeallocateResourceDeallocateResource
GetNameGetName vs. vs. SetNameSetName, but not , but not AssignNameAssignName 30
The Length of Method The Length of Method NamesNames
How long could be the name of a How long could be the name of a method?method? The name should be as long as The name should be as long as
requiredrequired Don't abbreviateDon't abbreviate Your IDE has autocompleteYour IDE has autocomplete
Examples:Examples: LoadCustomerSupportNotificationServiceLoadCustomerSupportNotificationService, , CreateMonthlyAndAnnualIncomesReportCreateMonthlyAndAnnualIncomesReport
Incorrect examples:Incorrect examples: LoadCustSuppSrvcLoadCustSuppSrvc, , CreateMonthIncReportCreateMonthIncReport31
Naming Method Naming Method ParametersParameters
Method parameters namesMethod parameters names Preferred form: [Noun] or [Adjective] + Preferred form: [Noun] or [Adjective] +
[Noun][Noun] Should be in camelCaseShould be in camelCase Should be meaningfulShould be meaningful Unit of measure should be obviousUnit of measure should be obvious
Examples: Examples: firstNamefirstName, , reportreport, , usersListusersList, , fontSizeInPixelsfontSizeInPixels, , speedKmHspeedKmH, , fontfont
Incorrect examples: Incorrect examples: pp, , p1p1, , p2p2, , populatepopulate, , LastNameLastName, , last_namelast_name, , convertImageconvertImage 32
Naming VariablesNaming Variables Variable namesVariable names
Should be in camelCaseShould be in camelCase Preferred form: [Noun] or [Adjective] + Preferred form: [Noun] or [Adjective] +
[Noun][Noun] Should explain the purpose of the variableShould explain the purpose of the variable
If you can't find good name for a variable If you can't find good name for a variable check if it has a single purposecheck if it has a single purpose
Exception: variables with very small scope, Exception: variables with very small scope, e.g. the index variable in a 3-lines long for-e.g. the index variable in a 3-lines long for-looploop
Names should be consistent in the projectNames should be consistent in the project
33
Naming Variables – Naming Variables – ExampleExample
Examples:Examples: firstNamefirstName, , reportreport, , usersListusersList , , fontSizefontSize, , maxSpeedmaxSpeed, , fontfont, , startIndexstartIndex, , endIndexendIndex, , charsCountcharsCount, , configSettingsXmlconfigSettingsXml, , configconfig, , dbConnectiondbConnection, , sqlCommandCreateUsersqlCommandCreateUser
Incorrect examples:Incorrect examples: foofoo, , barbar, , pp, , p1p1, , p2p2, , populatepopulate, , LastNameLastName, , last_namelast_name, , LAST_NAMELAST_NAME, , convertImageconvertImage, , moveMarginmoveMargin, , MAXSpeedMAXSpeed, , _firstName_firstName, , __temp__temp, , firstNameMiddleNameAndLastNamefirstNameMiddleNameAndLastName 34
More about Naming More about Naming VariablesVariables
The name should be addressed to the The name should be addressed to the problem we solve, not to the means problem we solve, not to the means we use to solve itwe use to solve it Prefer nouns from the business domain Prefer nouns from the business domain
to computer termsto computer terms Examples:Examples:
accountsaccounts, , customerscustomers, , customerAddresscustomerAddress, , accountHolderaccountHolder, , paymentPlanpaymentPlan, , vipPlayervipPlayer
Incorrect examples:Incorrect examples: accountsLinkedListaccountsLinkedList, , customersHashtablecustomersHashtable, , paymentsPriorityQueuepaymentsPriorityQueue, , playersArrayplayersArray
35
Naming Boolean Naming Boolean VariablesVariables
Boolean variables should imply Boolean variables should imply truetrue or or falsefalse
Prefixes like Prefixes like isis, , hashas and and cancan are useful are useful Use positive boolean variable namesUse positive boolean variable names
Incorrect example:Incorrect example: Examples:Examples:
hasPendingPaymenthasPendingPayment, , customerFoundcustomerFound, , validAddressvalidAddress, , positiveBalancepositiveBalance, , isPrimeisPrime
Incorrect examples:Incorrect examples: notFoundnotFound, , runrun, , programStopprogramStop, , playerplayer, , listlist, , findCustomerByIdfindCustomerById, , isUnsuccessfullisUnsuccessfull
36
if (! notFound) { … if (! notFound) { … }}
Naming Special Naming Special VariablesVariables
Naming CountersNaming Counters Establish a convention, e.g. [Noun] + Establish a convention, e.g. [Noun] +
''CountCount'' Examples: Examples: ticketsCountticketsCount, , customersCountcustomersCount
StateState Establish a convention, e.g. [Noun] + Establish a convention, e.g. [Noun] +
''StateState'' Examples: Examples: blogParseStateblogParseState, , threadStatethreadState
Variables with small scope and spanVariables with small scope and span Short names can be used, e.g. Short names can be used, e.g. indexindex, , ii, , uu 37
Temporary VariablesTemporary Variables
Do really Do really temporary variables temporary variables exist?exist? All variables in a program are All variables in a program are
temporary because they are used temporary because they are used temporarily only during the temporarily only during the program execution, right?program execution, right?
Temporary variables can always be Temporary variables can always be named better than named better than temptemp or or tmptmp::
38
// Swap a[i] and // Swap a[i] and a[j]a[j]int int temptemp = a[i]; = a[i];a[i] = a[j];a[i] = a[j];a[j] = a[j] = temptemp;;
// Swap a[i] and // Swap a[i] and a[j]a[j]int int oldValueoldValue = a[i]; = a[i];a[i] = a[j];a[i] = a[j];a[j] = a[j] = oldValueoldValue;;
The Length of Variable The Length of Variable NamesNames
How long could be the name of a How long could be the name of a variable?variable? Depends on the variable scope and Depends on the variable scope and
lifetimelifetime
More "famous" variables should have More "famous" variables should have longer and more self-explaining namelonger and more self-explaining name
Acceptable naming examples:Acceptable naming examples:
Unacceptable naming examples:Unacceptable naming examples:
39
for (int i=0; i<users.Length; for (int i=0; i<users.Length; i++)i++) if (i % 2 == 0)if (i % 2 == 0) sum += users[i].Weight;sum += users[i].Weight;
class Student {class Student { public string public string lastName;lastName;}}
class Student {class Student { private int i;private int i;}}
class PairOfLists {class PairOfLists { public int Count { get; public int Count { get; set; }set; }}}
Prefixes / Suffixes and Prefixes / Suffixes and Hungarian NotationHungarian Notation
In C# prefix / suffix notations are not In C# prefix / suffix notations are not popularpopular
Hungarian notationHungarian notation Using prefixes to denote the variable Using prefixes to denote the variable
types, e.g. types, e.g. lpcstrTextlpcstrText, , lpdwFlagslpdwFlags, , cbMultiBytecbMultiByte, , hWndhWnd
The Hungarian notation works well in The Hungarian notation works well in unmanaged languages like C++unmanaged languages like C++ Do not use Hungarian notation in C# Do not use Hungarian notation in C#
and .NETand .NET Don't use prefixes / suffixes to denote the Don't use prefixes / suffixes to denote the
variable data typevariable data type 40
Naming PropertiesNaming Properties Name properties in C# using a noun, Name properties in C# using a noun,
noun phrase, or an adjectivenoun phrase, or an adjective Use Pascal CaseUse Pascal Case Examples:Examples:
Incorrect examples:Incorrect examples:
41
public int Length { … }public int Length { … }public Color BackgroundColor { … }public Color BackgroundColor { … }public CacheMode CacheMode { … }public CacheMode CacheMode { … }public bool Loaded { … }public bool Loaded { … }
public int Load { … }public int Load { … }public Color backgroundColor { … }public Color backgroundColor { … }public bool Font { … }public bool Font { … }
Naming ConstantsNaming Constants Use CAPITAL_LETTERS for Use CAPITAL_LETTERS for constconst fields fields
and and PascalCasePascalCase for for readonlyreadonly fields fields Use meaningful names that describe Use meaningful names that describe
their valuetheir value Examples:Examples:
Incorrect examples:Incorrect examples:
42
private const int READ_BUFFER_SIZE = 8192;private const int READ_BUFFER_SIZE = 8192;public static readonly PageSize DefaultPageSize = public static readonly PageSize DefaultPageSize = PageSize.A4;PageSize.A4;private const int FONT_SIZE_IN_POINTS = 16;private const int FONT_SIZE_IN_POINTS = 16;
public const int MAX = 512; // Max what? Apples or public const int MAX = 512; // Max what? Apples or Oranges?Oranges?public const int BUF256 = 256; // What about BUF256 = public const int BUF256 = 256; // What about BUF256 = 1024?1024?public const string GREATER = ">"; // public const string GREATER = ">"; // GREATER_HTML_ENTITYGREATER_HTML_ENTITYpublic const int FONT_SIZE = 16; // 16pt or 16px?public const int FONT_SIZE = 16; // 16pt or 16px?public const PageSize PAGE = PageSize.A4; // Maybe public const PageSize PAGE = PageSize.A4; // Maybe PAGE_SIZE?PAGE_SIZE?
Names to AvoidNames to Avoid Don't use numbers in the identifiers Don't use numbers in the identifiers
namesnames Example: Example:
PrintReportPrintReport and and PrintReport2PrintReport2
What is the difference?What is the difference?
Exceptions:Exceptions: When the number is part of the name When the number is part of the name
itself, e.g. itself, e.g. RS232PortRS232Port, , COM3COM3, , Win32APIFunctionsWin32APIFunctions
Don't use Cyrillic or letters from other Don't use Cyrillic or letters from other alphabetsalphabets E.g. E.g. FindСтудентByNameFindСтудентByName, , CalcΩ2ProteinCalcΩ2Protein 43
Never Give a Never Give a Misleading Name!Misleading Name!
Giving a misleading name is worse Giving a misleading name is worse than giving a totally unclear namethan giving a totally unclear name
Example:Example: Consider a method that calculates the Consider a method that calculates the
sum of all elements in an arraysum of all elements in an array Its should be named Its should be named SumSum or or CalculateSumCalculateSum
What about naming it What about naming it CalculateAverageCalculateAverage or or MaxMax or or CheckForNegativeNumberCheckForNegativeNumber??
It's crazy, but be careful with "copy-It's crazy, but be careful with "copy-paste"paste"
44
Don't Believe Microsoft!Don't Believe Microsoft! Microsoft sometimes use really bad Microsoft sometimes use really bad
naming in their API libraries (especially naming in their API libraries (especially in Win32 API)in Win32 API) Examples:Examples:
NavigateNavigate and and Navigate2Navigate2 methods in methods in Internet Explorer ActiveX control Internet Explorer ActiveX control ((MSHTML.DLLMSHTML.DLL))
WNetAddConnection3WNetAddConnection3 method in Multiple method in Multiple Provider Router Networking API (Provider Router Networking API (MPR.DLLMPR.DLL))
LPWKSTA_USER_INFO_1LPWKSTA_USER_INFO_1 structure in Win32 structure in Win32
Don't follow them blindly, just think a Don't follow them blindly, just think a bit!bit!
45
What's Wrong with This What's Wrong with This Code?Code?
46
FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);FileStream fs = new FileStream(FILE_NAME, FileMode.CreateNew);
// Create the writer for data.// Create the writer for data.BinaryWriter w = new BinaryWriter(fs);BinaryWriter w = new BinaryWriter(fs);
// Write data to Test.data.// Write data to Test.data.for (int i = 0; i < 11; i++) for (int i = 0; i < 11; i++) {{ w.Write( (int) i);w.Write( (int) i);}}
w.Close();w.Close();fs.Close();fs.Close();
// Create the reader for data.// Create the reader for data.fs = new FileStream(FILE_NAME, FileMode.Open, fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);FileAccess.Read);BinaryReader r = new BinaryReader(fs);BinaryReader r = new BinaryReader(fs);
// Read data from Test.data.// Read data from Test.data.for (int i = 0; i < 11; i++) for (int i = 0; i < 11; i++) {{ Console.WriteLine(r.ReadInt32());Console.WriteLine(r.ReadInt32());}}
r.Close();r.Close();fs.Close();fs.Close();
Source: http://msdn.microsoft.com/en-us/library/36b93480.aspx
Code Code FormattingFormatting
Why Code Needs Why Code Needs Formatting?Formatting?
48
public const string public const string FILE_NAMEFILE_NAME="example.bin" ; static void Main ( ="example.bin" ; static void Main ( ){ ){FileStream fs= new FileStream fs= new FileStream(FILE_NAME,FileModeFileStream(FILE_NAME,FileMode. CreateNew) // Create the writer for . CreateNew) // Create the writer for data .data .;BinaryWriter w=new BinaryWriter ( fs ;BinaryWriter w=new BinaryWriter ( fs );// Write data to );// Write data to Test.data.Test.data.for( int i=0;i<11;i++)for( int i=0;i<11;i++){w.Write((int)i);}w .Close();{w.Write((int)i);}w .Close();fs . Close ( ) // Create the reader for fs . Close ( ) // Create the reader for data.data.;fs=new FileStream(FILE_NAME,FileMode. ;fs=new FileStream(FILE_NAME,FileMode. OpenOpen, FileAccess.Read) ;BinaryReader , FileAccess.Read) ;BinaryReader r r= new BinaryReader(fs); // Read data from = new BinaryReader(fs); // Read data from Test.data.Test.data. for (int i = 0; i < 11; i++)for (int i = 0; i < 11; i++){ Console .WriteLine{ Console .WriteLine(r.ReadInt32 (r.ReadInt32 ()) ());}r . Close ( ); fs . Close ( ) ;}r . Close ( ); fs . Close ( ) ; }; }
Code Formatting Code Formatting FundamentalsFundamentals
Good formatting goalsGood formatting goals To improve code readabilityTo improve code readability To improve code maintainabilityTo improve code maintainability
Fundamental principle of code Fundamental principle of code formatting:formatting:
Any formatting style that follows Any formatting style that follows the above principle is goodthe above principle is good
Any other formatting is not goodAny other formatting is not good 49
The formating of the source The formating of the source code should disclose its logical code should disclose its logical structure.structure.
Formatting Blocks in Formatting Blocks in C#C#
Put Put {{ and and }} alone on a line under alone on a line under the corresponding parent blockthe corresponding parent block
Indent the block contents by a Indent the block contents by a single [Tab]single [Tab] Don't indent with spacesDon't indent with spaces
Example:Example:
50
if ( some condition )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}}
Methods IndentationMethods Indentation
Methods should be indented with a Methods should be indented with a single [Tab] from the class bodysingle [Tab] from the class body
Methods body should be indented Methods body should be indented with a single [Tab] as wellwith a single [Tab] as well
51
public class IndentationExamplepublic class IndentationExample{{ private int Zero()private int Zero() {{ return 0;return 0; }}}}
The entire method The entire method is indented with a is indented with a
single [Tab]single [Tab]
Method body is also Method body is also indentedindented
Brackets in Methods Brackets in Methods DeclarationDeclaration
Brackets in the method declaration Brackets in the method declaration should be formatted as follows:should be formatted as follows:
Don't use spaces between the Don't use spaces between the brackets:brackets:
The same applies for The same applies for ifif-conditions -conditions and and forfor-loops:-loops:
52
private static ulong CalcFactorial(uint num)private static ulong CalcFactorial(uint num)
private static ulong CalcFactorial ( uint num ) private static ulong CalcFactorial ( uint num )
private static ulong CalcFactorial (uint num) private static ulong CalcFactorial (uint num)
if (condition) …if (condition) …
Separating ParametersSeparating Parameters Separate method parameters by Separate method parameters by
comma followed by a spacecomma followed by a space Don't put comma before the spaceDon't put comma before the space Examples:Examples:
Incorrect examples:Incorrect examples:
53
private void RegisterUser(string username, string private void RegisterUser(string username, string password)password)
private void RegisterUser(string username,string private void RegisterUser(string username,string password)password)private void RegisterUser(string username ,string private void RegisterUser(string username ,string password)password)private void RegisterUser(string username , string private void RegisterUser(string username , string password)password)
RegisterUser("nakov", "s3cr3t!p@ssw0rd");RegisterUser("nakov", "s3cr3t!p@ssw0rd");
Empty Lines between Empty Lines between MethodsMethods
Use empty line for separation Use empty line for separation between methods:between methods:
54
public class Factorialpublic class Factorial{{ private static ulong CalcFactorial(uint num)private static ulong CalcFactorial(uint num) {{ if (num == 0)if (num == 0) return 1;return 1; elseelse 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 Empty lineline
Always use Always use {{ and and }} after after ifif
(there is no space to (there is no space to do it here)do it here)
Empty Lines in Method Empty Lines in Method BodyBody
Use an empty line to separate Use an empty line to separate logically related sequences of lines:logically related sequences of lines:
55
private List<Report> PrepareReports()private List<Report> PrepareReports(){{ List<Report> reports = new List<Report>();List<Report> reports = new List<Report>();
// 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 = Report expensesMarketingReport = PrepareExpensesMarketingReport();PrepareExpensesMarketingReport(); reports.Add(expensesMarketingReport);reports.Add(expensesMarketingReport);
return reports;return reports;}}
Empty Empty lineline
Empty Empty lineline
Empty Empty lineline
Misplaced Empty Lines – Misplaced Empty Lines – ExampleExample
56
public static void PrintList(List<int> ints) public static void PrintList(List<int> 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()static void Main(){{ // ...// ...}}
Formatting TypesFormatting Types Formatting classes / structures / Formatting classes / structures /
interfaces / enumerationsinterfaces / enumerations Indent the class body with a single Indent the class body with a single
[Tab][Tab] Use the following order of definitions:Use the following order of definitions:
Constants, delegates, inner types, Constants, delegates, inner types, fields, constructors, properties, methodsfields, constructors, properties, methods
Static members, public members, Static members, public members, protected members, internal members, protected members, internal members, private membersprivate members
The above order of definitions is not The above order of definitions is not the only possible correct onethe only possible correct one 57
Formatting Types – Formatting Types – ExampleExample
58
public class Dogpublic 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)
Formatting Types – Formatting Types – Example (2)Example (2)
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"); }}
}}
Formatting Conditional Formatting Conditional Statements and LoopsStatements and Loops
Formatting conditional statements and Formatting conditional statements and loopsloops Always use Always use { }{ } block after block after ifif / / forfor / / whilewhile, even when a single operator , even when a single operator followsfollows
Indent the block body after Indent the block body after ifif / / forfor / / whilewhile
Never put the block after Never put the block after ifif / / forfor / / whilewhile on the same line!on the same line!
Always put the Always put the {{ on the next line on the next line
Never indent with more than one [Tab]Never indent with more than one [Tab] 60
Conditional Statements Conditional Statements and Loops Formatting – and Loops Formatting –
ExamplesExamples Example:Example:
Incorrect examples:Incorrect examples:
61
for (int i=0; i<10; 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++)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}", for (int i=0; i<10; i++) Console.WriteLine("i={0}", i);i);
for (int i=0; i<10; i++) {for (int i=0; i<10; i++) { Console.WriteLine("i={0}", i);Console.WriteLine("i={0}", i);}}
Breaking Long LinesBreaking Long Lines Break long lines after punctuationBreak long lines after punctuation Indent the second line by single [Tab]Indent the second line by single [Tab] Do not additionally indent the third Do not additionally indent the third
lineline Examples:Examples:
62
DictionaryEntry<K, V> newEntry = DictionaryEntry<K, V> newEntry = new DictionaryEntry<K, V>(new DictionaryEntry<K, V>( oldEntry.Key, oldEntry.Value);oldEntry.Key, oldEntry.Value);
if (matrix[x, y] == 0 || matrix[x-1, y] == 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){ …{ …
Incorrect Ways ToIncorrect Ways ToBreak Long LinesBreak Long Lines
63
if (matrix[x, y] == 0 || matrix[x-1, y] ==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 || if (matrix[x, y] == 0 || matrix[x-1, y] == 0 || matrix[x+1, y] == 0 || matrix[x, y-1] == matrix[x+1, y] == 0 || matrix[x, y-1] == 0 || 0 || matrix[x, y+1] == 0)matrix[x, y+1] == 0){ …{ …
DictionaryEntry<K, V> newEntry DictionaryEntry<K, V> newEntry = new DictionaryEntry<K, V>(oldEntry= new DictionaryEntry<K, V>(oldEntry .Key, oldEntry.Value);.Key, oldEntry.Value);
AlignmentsAlignments All types of alignments are All types of alignments are
considered harmfulconsidered harmful Alignments are hard-to-maintain!Alignments are hard-to-maintain!
Incorrect examples:Incorrect examples:
64
DateTime date = DateTime.Now.Date;DateTime date = DateTime.Now.Date;int count = 0;int count = 0;Student student = new Strudent();Student student = new Strudent();List<Student> students = new List<Student>();List<Student> students = new List<Student>();
matrix[x, y] == 0;matrix[x, y] == 0;matrix[x + 1, y + 1] == 0;matrix[x + 1, y + 1] == 0;matrix[2 * x + y, 2 * y + x] == 0;matrix[2 * x + y, 2 * y + x] == 0;matrix[x * y, x * y] == 0;matrix[x * y, x * y] == 0;
High-Quality ClassesHigh-Quality ClassesHow to Design High-Quality Classes? How to Design High-Quality Classes? Abstraction, Cohesion and CouplingAbstraction, Cohesion and Coupling
High-Quality Classes: High-Quality Classes: AbstractionAbstraction
Present a consistent level of Present a consistent level of abstractionabstraction in the class contract (publicly visible in the class contract (publicly visible members)members) What abstraction the class is What abstraction the class is
implementing?implementing?
Does it represent only one thing?Does it represent only one thing?
Does the class name well describe its Does the class name well describe its purpose?purpose?
Does the class define clear and easy to Does the class define clear and easy to understand public interface?understand public interface?
Does the class hide all its implementation Does the class hide all its implementation details?details? 66
Good Abstraction – Good Abstraction – ExampleExample
67
public class Fontpublic 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 public Font(string name, float sizeInPoints, FontStyle style)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) { ... }}}
Bad Abstraction – Bad Abstraction – ExampleExample
68
public class Programpublic 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 Does this class really represent really represent a "program"? Is a "program"? Is this name good?this name good?
Does this Does this class really class really
have a have a single single
purpose?purpose?
Establishing Good Establishing Good AbstractionAbstraction
Define operations along with their Define operations along with their oppositesopposites
Example:Example:
Open()Open() and and Close()Close()
Move unrelated methods in another classMove unrelated methods in another class
Example:Example:
In class In class EmployeeEmployee if you need to calculate if you need to calculate AgeAge
by given by given DateOfBirthDateOfBirth
Create static method Create static method CalcAgeCalcAge in a separate in a separate
class class DateUtilsDateUtils69
Establishing Good Establishing Good Abstraction (2)Abstraction (2)
Beware of breaking the interface Beware of breaking the interface abstraction due to evolutionabstraction due to evolution Don't add public members Don't add public members
inconsistent with class abstractioninconsistent with class abstraction Example: in class called Employee Example: in class called Employee
at some time we add method for at some time we add method for accessing the DB with SQLaccessing the DB with SQL
70
class Employeeclass Employee{{ public string firstName;public string firstName; public string lastName;public string lastName; … … public SqlCommand FindByPrimaryKeySqlCommand(int public SqlCommand FindByPrimaryKeySqlCommand(int id);id);}}
EncapsulationEncapsulation Minimize the visibility of classes and Minimize the visibility of classes and
membersmembers
Start from Start from privateprivate and move to and move to internalinternal, , protectedprotected and and publicpublic if required if required
Classes should hide their implementation Classes should hide their implementation detailsdetails
Anything which is not part of the class Anything which is not part of the class interface should be declared interface should be declared privateprivate
Classes with good encapsulated classes are: Classes with good encapsulated classes are: less complex, easier to maintain, more loosely less complex, easier to maintain, more loosely coupledcoupled
Never declare fields public (except constants)Never declare fields public (except constants)
Use methods or properties to access fieldsUse methods or properties to access fields 71
Encapsulation (2)Encapsulation (2) Don't violate encapsulation Don't violate encapsulation
semantically!semantically! Don't rely on non-documented internal Don't rely on non-documented internal
behavior or side effectsbehavior or side effects
Wrong example: Wrong example:
Skip calling Skip calling ConnectToDB()ConnectToDB() because you because you just called just called FindEmployeeById()FindEmployeeById() which which should open connectionshould open connection
Another wrong example:Another wrong example:
Use Use String.EmptyString.Empty instead of instead of Titles.NoTitleTitles.NoTitle because you know both because you know both values are the samevalues are the same 72
InheritanceInheritance Don't hide methods in a subclassDon't hide methods in a subclass
Example: if the class Example: if the class TimerTimer has private has private method method Start()Start(), don't define , don't define Start()Start() in in AtomTimerAtomTimer
Move common interfaces, data, and Move common interfaces, data, and behavior as high as possible in the behavior as high as possible in the inheritance treeinheritance tree This maximizes the code reuseThis maximizes the code reuse
Be suspicious of base classes of which Be suspicious of base classes of which there is only one derived classthere is only one derived class Do you really need this additional level Do you really need this additional level
of inheritance?of inheritance? 73
Inheritance (2)Inheritance (2) Be suspicious of classes that override Be suspicious of classes that override
a routine and do nothing insidea routine and do nothing inside Is the overridden routine used Is the overridden routine used
correctly?correctly? Avoid deep inheritance treesAvoid deep inheritance trees
Don't create more than 6 levels of Don't create more than 6 levels of inheritanceinheritance
Avoid using a base class’s protected Avoid using a base class’s protected data fields in a derived classdata fields in a derived class Provide protected accessor methods Provide protected accessor methods
or properties insteador properties instead 74
Inheritance (3)Inheritance (3) Prefer inheritance to extensive type Prefer inheritance to extensive type
checking:checking:
Consider inheriting Consider inheriting CircleCircle and and SquareSquare from from ShapeShape and override the abstract and override the abstract action action Draw()Draw() 75
switch (shape.Type)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;
......
}}
Class Methods and DataClass Methods and Data Keep the number of methods in a class Keep the number of methods in a class
as small as possible as small as possible reduce complexity reduce complexity Minimize direct method calls to other Minimize direct method calls to other
classesclasses Minimize indirect method calls to other Minimize indirect method calls to other
classesclasses
Less external method calls == less Less external method calls == less couplingcoupling
Minimize the extent to which a class Minimize the extent to which a class collaborates with other classescollaborates with other classes Reduce coupling between classesReduce coupling between classes
76
Class ConstructorsClass Constructors Initialize all member data in all Initialize all member data in all
constructors, if possibleconstructors, if possible Uninitialized data is error proneUninitialized data is error prone Partially initialized data is even more Partially initialized data is even more
evilevil Incorrect example: assign Incorrect example: assign FirstNameFirstName in in
class class PersonPerson but leave but leave LastNameLastName empty empty Initialize data members in the same Initialize data members in the same
order in which they are declaredorder in which they are declared Prefer deep copies to shallow copies Prefer deep copies to shallow copies
((ICloneableICloneable should make deep copy) should make deep copy)77
Use Design PatternsUse Design Patterns Use private constructor to prohibit Use private constructor to prohibit
direct class instantiationdirect class instantiation Use deign patterns for common Use deign patterns for common
design situationsdesign situations Creational patterns like singleton, Creational patterns like singleton,
factory method, abstract factoryfactory method, abstract factory
Structural patterns like adapter, Structural patterns like adapter, bridge, composite, decorator, façadebridge, composite, decorator, façade
Behavioral patterns like command, Behavioral patterns like command, iterator, observer, strategy, template iterator, observer, strategy, template methodmethod
78
Top Reasons to Create Top Reasons to Create ClassClass
Model real-world objects with OOP Model real-world objects with OOP classesclasses
Model abstract objects, processes, etc.Model abstract objects, processes, etc. Reduce complexityReduce complexity
Work at higher levelWork at higher level Isolate complexityIsolate complexity
Hide it in a classHide it in a class Hide implementation details Hide implementation details
encapsulationencapsulation Limit effects of changesLimit effects of changes
Changes affect only their classChanges affect only their class 79
Top Reasons to Create Top Reasons to Create Class (2)Class (2)
Hide global dataHide global data Work through methodsWork through methods
Group variables that are used togetherGroup variables that are used together Make central points of controlMake central points of control
Single task should be done at single Single task should be done at single placeplace
Avoid duplicating codeAvoid duplicating code Facilitate code reuseFacilitate code reuse
Use class hierarchies and virtual Use class hierarchies and virtual methodsmethods
Package related operations togetherPackage related operations together80
NamespacesNamespaces Group related classes together in Group related classes together in
namespacesnamespaces Follow consistent naming Follow consistent naming
conventionconvention
81
namespace Utilsnamespace Utils{{ class MathUtils { … }class MathUtils { … } class StringUtils { … }class StringUtils { … } class DateUtils { … }class DateUtils { … }}}
namespace DataAccessLayernamespace DataAccessLayer{{ class GenericDAO<Key, Entity> { … }class GenericDAO<Key, Entity> { … } class EmployeeDAO<int, Employee> { … }class EmployeeDAO<int, Employee> { … } class AddressDAO<int, Address> { … }class AddressDAO<int, Address> { … }}}
Code Reformatting Code Reformatting and Identifiers and Identifiers
RefactoringRefactoringLive DemoLive Demo
ResourcesResources
The bible of high-quality software construction:The bible of high-quality software construction:
83
Code Complete, 2Code Complete, 2ndnd edition, Steve McConnell, edition, Steve McConnell, Microsoft Press, 2004, Microsoft Press, 2004, ISBN ISBN 07356196700735619670, , http://www.cc2e.comhttp://www.cc2e.com
The "High-Quality Programming The "High-Quality Programming Code" course at Telerik Academy:Code" course at Telerik Academy: http://codecourse.telerik.com
QuestionsQuestions??
QuestionsQuestions??
High-Quality High-Quality Programming Code Programming Code
Construction – Part IConstruction – Part I
ExercisesExercises1.1. You are given a source code trying to solve You are given a source code trying to solve
the "Game 15" puzzle. Your task is to the "Game 15" puzzle. Your task is to improve the code quality without changing improve the code quality without changing its functionality (only bug fixes are its functionality (only bug fixes are allowed):allowed):
a)a) Reformat the code following the guidelines Reformat the code following the guidelines defined in the "Code Formatting" section.defined in the "Code Formatting" section.
b)b) Following the guidelines in the "Naming Following the guidelines in the "Naming Identifiers" section rename the identifiers in Identifiers" section rename the identifiers in the program: solution name, project name, the program: solution name, project name, class names, method names, parameter class names, method names, parameter names, variables, etc.names, variables, etc.
c)c) Split the functionality into classes with good Split the functionality into classes with good abstraction and strong cohesion.abstraction and strong cohesion.
85