Chapter 01 of the lecture Style & Design Principles taught at SAE Institute Hamburg.
Introduction to naming conventions, type and member design, exception design and common .NET interfaces.
2. About Me
“Best Bachelor“ Computer Science
Kiel University, 2009
Master Games
Hamburg University of Applied Sciences, 2011
Lead Programmer
Daedalic Entertainment, 2011-2012
Co-Founder
slash games, 2013
2 / 78
3. First Things First
• At npruehs.de/teaching you‘ll always find
• these slides
• solutions to all assignments
• Ask your questions – any time!
• Each lecture will close with
• further reading
• an optional assignment
• Contact me any time at dev@npruehs.de!
3 / 58
4. Objectives
• To get an idea of good code style and structure in
general
• To understand the importance of consistent naming
and code conventions
• To learn how to use common tools to write good
code more easily
4 / 78
5. What is “good code”?
• Straight-forward and obvious
• You’ll spend far more time reading code than writing.
• You’ll spend much time reading code you didn’t write.
• Loose coupling
• Well tested
• Reused code
• Efficient (?)
5 / 78
6. How to achieve “good code”?
Source: http://xkcd.com/844/ 6 / 78
7. How to achieve “good code”?
• Pair programming
• Code Reviews
• Client-first programming, Test-driven development
• Refactoring
• Unit Testing
• Great tools
• Static code analysis
7 / 78
8. Naming Conventions
• Greatly increase readability and usability
• Differ from language to language
• We’ll take a look at C#, but many guidelines apply to
other languages as well.
8 / 78
10. Capitalization of Acronyms
• Both characters of two-character acronyms
• Example: IO
• Only first character of three-character acronyms
• Example: Xml, Html
• Never for camelCased identifiers (such as
parameters)
10 / 78
11. Word Choice
• Easily readable:
• HorizontalAlignment instead of AlignmentHorizontal
• Favor readability over brevity:
• CanScrollHorizontally instead of ScrollableX
• No underscores
• No Hungarian notation
• No abbreviations
• Abbreviations don’t work well with IDEs.
• Semantic names
• GetLength instead of GetInt
11 / 78
13. Type Names
• Nouns for classes and structs
• Example: List, Vector
• Derived classes can end with name of base class
• Example: ArgumentException
• Adjectives for interfaces
• Prefix interface names with ‘I’
• Example: IComparable
• Use descriptive names for type-parameters
• Dictionary<TKey, TValue> instead of Dictionary<K, V>
• Singular names for non-flags enums
• Color instead of Colors
13 / 78
14. Member Names
• Verbs for methods and events
• Example: AddComponent, ComponentAdded
• Nouns or adjectives for fields
• Example: Duration, Invulnerable
• Nouns for properties
• Plurals for collections
• Items instead of ItemList
14 / 78
15. Boolean Trap #1
• Be positive!
• Enabled = true instead of Disabled = false
• CaseSensitive = true instead of CaseInsensitive = false
15 / 78
16. Tabs vs. Spaces
• Holy war between two fractions of programmers
• Some are for tabs…
• Seperation of visual representation from data
• Customizable
• Faster
• Specifically meant for indentation
• … while others are for spaces.
• Always one column
• Supported by IDEs anyway
16 / 78
17. Tabs vs. Spaces
• Most important rule:
Stay consistent.
• … or it might even blow up your version control.
17 / 78
18. Tabs vs. Spaces
„That said, only a moron would use tabs to format
their code.”
- Jeff Atwood
18 / 78
19. Tools – StyleCop
• Analyzes C# source code to enforce a set of style
and consistency rules
• Helps developers avoid common pitfalls and
mistakes
• Settings file can be checked in to version control
19 / 78
30. Type Design – Class vs. Struct
Make a type a struct instead of a class if it…
• Logically represents a single value,
• Has a valid state if all data is set to zero,
• Has an instance size < 16 bytes,
• Is Immutable, and
• Won’t have to be boxed frequently
30 / 78
31. Type Design – Class vs. Struct
Make a type a struct instead of a class if it…
• Logically represents a single value,
• Has a valid state if all data is set to zero,
• This is the case for array initialization, for example.
• Has an instance size < 16 bytes,
• Is Immutable, and
• Won’t have to be boxed frequently
31 / 78
32. Type Design – Class vs. Struct
Make a type a struct instead of a class if it…
• Logically represents a single value,
• Has a valid state if all data is set to zero,
• Has an instance size < 16 bytes,
• Value type assignments copy all values
• Is Immutable, and
• Won’t have to be boxed frequently
32 / 78
33. Type Design – Class vs. Struct
Make a type a struct instead of a class if it…
• Logically represents a single value,
• Has a valid state if all data is set to zero,
• Has an instance size < 16 bytes,
• Is Immutable, and
• Passing (and returning) by value implicitly creates a copy
• Value types that can be changed will be confusing!
• Won’t have to be boxed frequently
33 / 78
34. Type Design – Class vs. Struct
Make a type a struct instead of a class if it…
• Logically represents a single value,
• Has a valid state if all data is set to zero,
• Has an instance size < 16 bytes,
• Is Immutable, and
• Won’t have to be boxed frequently
• Happens when they’re cast to a interface
• Allocated on heap and garbage collected, then!
34 / 78
35. Type Design – Class vs. Interface
• Use interfaces for polymorphic value type
hierarchies
• Example: IComparable, IConvertible
• If an interface does more than exactly one thing,
that’s a warning sign.
35 / 78
37. Type Design – Class vs. Interface
• Favor (abstract) classes over interfaces
• Adding members to an interface is a breaking change!
• Seperating of contract from implementation with an
interface is a myth…
• … whereas doing so with an abstract class is not.
37 / 78
38. Type Design – Enums
• Favor enums over static constants
• Provide a zero value for simple enums (e.g. None)
• Don’t use enums for open sets
• Don’t use flag enums if some combinations can be
invalid
38 / 78
39. Member Design –
Property vs. Method
Make a member a method instead of a property if
it…
• Is significantly slower than a field access would be,
• Is a conversion operation (such as ToString),
• Returns a different result each time it is called,
• Has an observable side effect,
• Returns a copy of an internal state, or
• Returns an array
39 / 78
40. Member Design – Properties
• Preserve previous value if a property setter throws
an exception
• Don’t throw exceptions from property getters.
• Use a method in that case.
40 / 78
42. Member Design – Methods
• Shorter overloads should simply call longer ones
• public int IndexOf(string s)
• public int IndexOf(string s, int startIndex)
• public int IndexOf(string s, int startIndex, int count)
• Use descriptive parameter names
• Avoid varying names or inconsistent ordering
• Make only the longest overload virtual
• Allow null to be passed for optional parameters
• Default arguments are not CLS-compliant!
42 / 78
43. Member Design – Extensions
Use an extension method, if ...
• It adds functionality relevant to every
implementation of an interface, or
• An instance method would introduce unwanted
dependencies
43 / 78
44. Member Design –
Operator Overloads
• Make sense for types that feel like primitive types
• Should be defined symmetrically
• Provide methods with friendly names, as well
• Some languages don‘t support operator overloads.
44 / 78
45. Member Design –
Parameters
• Use the least derived required paramter type
• Validate all arguments
• params keyword is useful for arbitrary (but small)
numbers of parameters
• Pay attention on parameter order
• Be aware that null is a valid params array argument
45 / 78
47. Boolean Trap #2
Guess what this code means?
widget.repaint(false);
• Function argument is called immediate
• true means immediate painting
• false means deferred painting
• Better use method overloads or enums!
47 / 78
48. Boolean Trap #3
Guess what this code means?
var opacitySlider = new Slider(true);
48 / 78
49. Boolean Trap #3
Guess what this code means?
var opacitySlider = new Slider(true);
• Function argument is called horizontal
• true means horizontal slider
• false means vertical slider
• Better use subclasses!
• „Heck, who knows someday you’ll need a diagonal
slider!”
49 / 78
53. Exceptions
• Help you deal with any unexpected or exceptional
situations that occur when a program is running
• Exceptions are types that all ultimately derive from
System.Exception.
• Generated by the common language runtime (CLR),
by the .NET Framework or any third-party libraries,
or by application code.
53 / 78
54. Benefits of Exceptions
• Integrate well with object-oriented languages
• Does not require changing the method signature
• Can’t be ignored, whereas error codes can
• Exception objects contain detailed information
about the error, such as the state of the call stack
and a text description of the error.
• Possibility of defining an Unhandled Exception
Filter (UEF)
• Supported by debuggers
54 / 78
56. Exception Design
• Exceptions provide consistent error reporting
• No bool return value required
• No HRESULT
• No GetLastError
• Don’t return error codes.
• If your error code is for the developer, add additional
information to the exception message instead.
• If your error code is for the exception handler, add a
new exception type instead.
56 / 78
57. Throwing Exceptions
• Throw the most specific exception that makes
sense.
• ArgumentException
• ArgumentNullException
• Provide rich and meaningful error messages.
• Introduce a new exception type only if it should be
handled differently than existing exception types.
57 / 78
58. Handling Exceptions
• Use a try block around the statements that might
throw exceptions.
• Once an exception occurs in the try block, the flow
of control jumps to the first associated exception
handler that is present anywhere in the call stack.
• If no exception handler for a given exception is
present, the program stops executing with an error
message.
58 / 78
61. Exception Best Practice
• Do not catch an exception unless you can handle it
and leave the application in a known state.
• Do not catch non-specific exceptions, such as
System.Exception.
• Use a finally block to release resources, for example
to close any streams or files that were opened in
the try block.
61 / 78
63. Common Exceptions
• Thrown by your application or the framework
• InvalidOperationException
• ArgumentException
• ArgumentNullException
• ArgumentOutOfRangeException
• Thrown by the CLR
• NullReferenceException
• IndexOfOutRangeException
• StackOverflowException
• OutOfMemoryException
63 / 78
64. Collection Design
• Inherit from Collection<T>,
ReadOnlyCollection<T> or
KeyedCollection<TKey, TItem>
• Implement IEnumerable<T>
• Allows foreach iteration of your collection.
• Implement ICollection<T> or IList<T> where it
makes sense
• Implement an indexer where it makes sense
64 / 78
66. The interface ICloneable
• Contract doesn’t define whether cloning an object
returns a deep or shallow copy
• Define your own Clone method if required, without
implementing the interface
66 / 78
68. The interface IEquatable
• Defines a method for determining equality of
object instances
• Implement on value types to prevent boxing
• Override Object.Equals, == and != operators as
well
68 / 78
70. The interface IComparable
• Defines a type-specific comparison method for
ordering or sorting type instances.
• Override <, >, <= and >= operators as well
70 / 78
71. Equals, GetHashCode &
ToString
• If Object.Equals returns true for any two objects,
GetHashCode must return the same value for these
objects.
• Dictionaries, which are implemented as Hashtables in
.NET, will place two equal objects in different buckets
otherwise, and lookup might fail in that case.
• Override ToString wherever it makes sense.
• Provides more useful debug output.
71 / 78
73. Assignment #1
1. Field Declaration
What’s wrong with the following declaration for the
count of items in a collection?
private int m_itemcnt;
73 / 78
74. Assignment #1
2. Vector Type
Implement a type for a two-dimensional vector with
integer coordinates!
74 / 78
76. Assignment #1
4. Grid Type
1. Implement a type for a generic two-dimensional grid!
2. Add support for iteration, indexing and copying!
3. Allow comparison of grids by comparing all of their
entries!
76 / 78
77. References
• Stack Overflow. What does a good programmer's code look
like? http://stackoverflow.com/questions/366588/what-
does-a-good-programmers-code-look-like, March 2015.
• Cwalina, Abrams. Framework Design Guidelines. 2nd Edition.
Addison-Wesley, 2011.
• Hidayat. hall of api shame: boolean trap.
http://ariya.ofilabs.com/2011/08/hall-of-api-shame-
boolean-trap.html, August 24, 2011.
• Atwood. Death to the Space Infidels!
http://www.codinghorror.com/blog/2009/04/death-to-the-
space-infidels.html, April 13, 2009.
• MSDN. System Namespace. http://msdn.microsoft.com/en-
us/library/System%28v=vs.110%29.aspx, March 2015.
77 / 78
78. Thank you for your attention!
Contact
Mail
dev@npruehs.de
Blog
http://www.npruehs.de
Twitter
@npruehs
Github
https://github.com/npruehs
78 / 78