(From http://mikehadlow.blogspot.com/2009/05/what-i-look-for-in-code-review.html) I recently put this bullet point list together for the team I’m currently working with. Naming Conventions General Principles - The core imperative is to organise complexity.
- Clarity and readability is central. “Intention Revealing”
- Do not prematurely optimise for performance.
- Do not repeat yourself. Never copy-and-paste code.
- Decouple.
- Always try to leave the code you work on in a better state than before you started (the ‘boy scout’ principle)
Keep the source clean - Always delete unused code. Including variables and using statements
- Don’t comment out code, delete it. We have source control to manage change.
Naming things - The name should accurately describe what the thing does.
- Do not use shortenings, only use well understood abbreviations.
- If the name looks awkward, the code is probably awkward.
Namespaces - Namespaces should match the project name + path inside the project. This is what VS will give you by default.
- Classes that together provide similar functions should be grouped in a single namespace.
- Avoid namespace dependency cycles.
Variables - Use constants where possible. Avoid magic strings.
- Use readonly where possible
- Avoid many temporary variables.
- Never use a single variable for two different puposes.
- Keep scope as narrow as possible. (declaration close to use)
Methods - The name should accurately describe what the method does.
- It should only do one thing.
- It should be small (more than 10 lines of code is questionable).
- The number of parameters should be small.
- Public methods should validate all parameters.
- Assert expectations and throw an appropriate error if invalid.
- Avoid deep nesting of loops and conditionals. (Cyclomatic complexity).
Classes - The name should accurately describe what the class does.
- Classes typically represent data or services, be clear which your class is.
- Design your object oriented schema deliberately.
- A class should be small.
- A class should have one responsibility only.
- A class should have a clear contract.
- A class should be decoupled from its dependencies.
- Favour composition over inheritance.
- Avoid static classes and methods.
- Make the class immutable if possible.
Interfaces - Rely on interfaces rather than concrete classes wherever possible.
- An interface is a contract for interaction.
- An interface should have a single purpose (ISP)
Tests - All code should have unit tests if possible.
- Test code should have the same quality as production code.
- Write code test-first wherever possible.
Error Handling - Only wrap code with a try..catch statement if you are expecting it to throw a specific exception.
- Unexpected errors should only be handled at process boundaries.
- Never ‘bury’ exceptions.
http://code.msdn.microsoft.com/mef The Managed Extensibility Framework (MEF) provides developers with a tool to easily add extensibility to their applications and with minimal impact on existing code. The application developer can define extension points according to the functionality required of an extension, while the extension developer uses those points to interact with the application. MEF enables this extensibility to take place without creating a hard dependency in either direction. Applications can be extended at run time without recompilation, and extensions can be used by multiple applications sharing the same extension requirements. MEF also allows an application to delay the loading of an extension while still examining its metadata, enabling efficient traversal of large catalogs of extensions.
(Picked from book "UML Applied - A .Net Perspective")
A more important benefit of classes and objects is that they form a nice syntactic mechanism for achieving some classic aspects of well-designed code: [2]
-
Encapsulation. The goal of encapsulation is to expose only enough of a module or subsystem to allow other modules to make use of it. Object-Oriented Programming allows you to specify the degree of visibility of elements of your code, so that client code is restricted in what it can access. Thus, you can syntactically seal off implementation details, leading to more flexibility and maintainability in your system.
-
Loose coupling. Coupling refers to the ways in which and degrees to which one part of the system relies on the details of another part. The tighter the coupling, the more changes in one part of the system will ripple throughout the system. With loose coupling, the interfaces between subsystems are well defined and restricted. What lies beyond those interfaces can change without any changes needed in the client sub-systems. Object-Oriented Programming supports loose coupling by allowing you to define and publish a class's methods without publishing how those methods are carried out. This principle goes even further in OO languages that support interfaces (described later in this section).
-
Strong cohesion. Cohesion refers to the degree in which elements within a subsystem form a single, unified concept, with no excess elements. Where there is high cohesion, there is easier comprehension and thus more reliable code. Object-Oriented Programming supports strong cohesion by allowing you to design classes in which the data and the functions that operate on them are tightly bound together.
Does OO force you to have these quality attributes in your code? I wish! No matter the language, you can write shoddy code with no encapsulation, pathological coupling, and no cohesion. Furthermore, some OO languages are less rigid than others in how much they require you to design around objects. But OO languages certainly support these quality attributes if you take the time to pursue them.
The key concepts in Object-Oriented Programming are these:
-
Classes. A class is the definition of the behavior and properties of one or more objects within your system. A class binds the data (attributes) of an object to the behavior (operations) that it can perform.
-
Attributes. An attribute is a data value or state that describes an object and helps you to tell one object from another of the same class. It seems that every new OO language author feels the need to distinguish their language by coming up with new terminology. In some OO languages, these data values are called properties or member variables or member data; but in UML, the proper term is attributes.
-
Operations. An operation is a behavior or function that an object can perform. Depending on the OO language, these might be called methods or member functions or even messages. The last term, messages, comes from Smalltalk, one of the earliest OO languages, in which all objects communicated by sending messages to each other. You'll see a similar use of the term message when we study Sequence Diagrams.
-
Objects. An object is an instance or specific example of a class. If Dog is the class, then Betsy, Ladi, Patches, Jake, Radar, and Frosty are specific instances of the class found in my house. The attributes of the class have specific values within an object of that class; and the operations of a class operate on the attributes of individual objects.
-
Inheritance. This concept indicates that one class (the superclass) provides some common or general behavior inherited by one or more specific classes (the subclasses). The subclasses then provide more or different behavior beyond that defined in the superclass. For example, besides the Dogs, I have Cat objects and Horse objects that live on my property. Each class has unique behaviors: Dogs must be walked, Cats use the litter box, and Horses drop manure that must be scooped up and thrown in the manure pile. Yet all classes have some common behavior: they must be fed, and they must have vet visits. So I can define a superclass, Pet, and have my subclasses, Dog, Cat, and Horse, derive their shared behavior from the Pet class. In UML, this concept is known under the slightly different term of generalization, in which a superclass provides the generalized behavior of the subclasses. It's really the same concept, but just looking at it the other way up.
-
Components. A component is a collection of related classes that together provide a larger set of services. Components in your system might include applications, libraries, ActiveX controls, JavaBeans, daemons, and services. In the .NET environment, most of your projects will require component development.
-
Interfaces. An interface is a definition of a set of services provided by a component or by a class. This allows further encapsulation: the author of a component can publish just the interfaces to the component, completely hiding any implementation details.
|