We need to first define the problem. If I had an hour to save the world, I would spend 59 minutes defining the problem and 1 minute finding solutions.
Viewing entries tagged
Every time I come across a procedure or code file with a 1000 lines of code I just want to sentence the creator to permanent programming abstinence. To write elegant and maintainable code there are a couple of things you'll want to consider (and learn, if not known). This article will cover some of them, with a focus on Object Oriented Programming. First we shall find a good motive to do this. Why would we want to write elegant code? What is our motivation for code metrics?
- Improve software quality: Well-known practices on your code will (with high probability) make software more stable and usable.
- Software Readability: Most software applications are not the sole creation of an individual. Working with teams is always a challenge; code metrics allows teams to standardize the way they work together and read more easily each other’s code.
- Code flexibility: Applications with a good balance of cyclomatic complexity and design patterns are more malleable and adaptable to small and big changes in requirements and business rules.
- Reduce future maintenance needs: Most applications need some sort of review or improvement on their lifetime. Coming back to code written a year ago will be easier if the code have good metrics.
To have a good maintainability index in your code you should have a couple of metrics measured up. Ultimately the maintainability index is what works for your specific case. This is not a fixed industry set of rules, but rather a combination of them that works for the requirement of your organization application and team. Let’s take a look at what I PERSONALLY CONSIDER good metrics for the ultimate maintainability index of software applications:
Cyclomatic Complexity (CC)
- Cyclomatic Complexity (CC)
- Very popular code metric in software engineering.
- Measures the structural complexity of a function.
- It is created by calculating the number of decision statements and different code paths in the flow of a function.
- Often correlated to code size.
- A function with no decisions has a CC = 1, being the best case scenario.
- A function with CC >= 8 should raise red flags and you should certainly review that code with a critical eye. Always remember, the closest to 1 the better.
Lines of Code (LOC)
- LOC is the oldest and easier to measure metric.
- Measures the size of a program by counting the lines of code.
- Some recommended values by entities (for .NET Languages):
- Code Files: LOC <=600
- Classes: LOC <=1000 (after excluding auto-generated code and combining all partial classes)
- Procedures/Methods/Functions: LOC<=100
- Properties/Attributes: LOC <=30
- If the numbers on your application show larger number than the previous values, you should check your code again. A very high count indicates that a type or a procedure it trying to do too much work and you should try to split it up.
- The higher the LOC numbers the harder the code will be to maintain.
Depth of Nesting
- Measures the nesting levels in a procedure.
- The deeper the nesting, the more complex the procedure is. Deep nesting levels often leads to errors and oversights in the program logic.
- Avoid having too many nested logic cases, look for alternate solutions to deep if then else for foreach switch statements; they loose logic sense in the context of a method when they run too deep.
- Reading: Vern A. French on Software Quality
Depth of Inheritance (DIT)
- Measures the number of classes that extend to the root of the class hierarchy at each level.
- Classes that are located too deep in the inheritance tree are relatively complex to develop and maintain. The more of those you have the more complex and hard to maintain your code will be.
- Avoid too many classes at deeper levels of inheritance. Avoid deep inheritance trees in general.
- Maintain your DIT <= 4. A value greater than 4 will compromise encapsulation and increase code density.
Coupling and Cohesion Index (Corey Ladas on Coupling)
- To keep it short, you always should: MINIMIZE COUPLING, MAXIMIZE COHESION
- Coupling: aka “dependency” is the degree of reliance a functional unit of software has on another of the same category (Types to Types and DLLs to DLLs).
- The 2 most important types of coupling are Class Coupling (between object types) and Library Coupling (between DLLs).
- High coupling (BAD) indicates a design that is difficult to reuse and maintain because of its many interdependencies on other modules.
- Cohesion: Expresses how coherent a functional unit of software is. Cohesion measures the SEMANTIC strength between components within a functional unit. (Classes and Types within a DLL; properties and methods within a Class)
- If the members of your class (properties and methods) are strongly-related, then the class is said to have HIGH COHESION.
- Cohesion has a strong influence on coupling. Systems with poor (low) cohesion usually have poor (high) coupling.
- Design Patterns play an extremely important role in the architecture of complex software systems. Patterns are proven solutions to problems that repeat over and over again in software engineering. They provide the general arrangement of elements and communication to solve such problems without doing the same twice.
- I can only recommend one of the greatest books in this subject called: “Design Patterns: Elements of Reusable Object-Oriented Software” by the Gang of Four. Look it up online, buy it, read it and I’ll guarantee you’ll never look at software architecture and design the same way after.
- Depending on the needs of the problem, applying proven design patterns like Observer, Command and Singleton patterns will greatly improve the quality, readability, scalability and maintainability of your code.
Triex Index (TI - Performance Execution)
- Triex Index (TI) measures the algorithmic time complexity (Big O) of object types.
- TI is more important to be considered for object types that carry a large load of analysis, like collections and workers objects.
- This metric receives a strong influence from Cohesion and should only be applied to classes and types and not to individual members. The coherence is also very influential on the time complexity coherence between its members.
- This is a personal metric. I haven't found this type of metrics elsewhere, but I think it's singular and significant to the overall elegance and performance of your code.
- The Triex Index is calculated by dividing the infinite product of the execution order (Big O) for all members of a class, by n to the power of c-1; where c is the number of members in the class/type.
- TI > n2 - Bad. Needs algorithm revision
- n<TI<n2 - Regular.
- TI<=n - Good
- If a member of a class is hurting the overall TI of the class, try splitting its logic into one or more methods with less costly execution orders. Be careful not to harm the coupling and cohesion metrics of the type while doing this step.
The same way I have my preferences, I have my disagreements with some colleagues when it comes to other known code metrics. I consider some of this code metrics a waste of time when measuring code elegance and maintainability:
- Law of Demeter (for Functions and Methods)
- The Principle of Least Knowledge is a design guideline I’ll always encourage to use. What I consider unnecessary is the “use only one dot” rule enforcement for functions and methods.
- “a.b.Method()” breaks the law, where “a.Method()” does not. That's just ridiculous.
- Weighted Methods Per Class (WMC)
- Counts the total number of methods in a type.
- Number of Children
- Counts the number of immediate children in a hierarchy.
- Constructors defined by class
- Counts the number of constructor a class have.
- Kolmogorov complexity
- Measures the computation resources needed to represent an object
- Number of interfaces implemented by class
- Counts the number of interfaces a class implements.
There are 2 main reasons I do not like to consider these metrics when looking at maintainability and code elegance:
- Many of them are obsolete metrics when we look at modern software engineering techniques and languages like C# and LINQ. Things like methods per class or number of children do not apply very well to the core concepts of these modern techniques. Just imagine measuring the “Weighted Methods Per Class” in a world full of extension methods that ultimately do not depend on the original creator of the object type.
- The second reason is that the complexity of the problem never changes. If we have to solve a problem that by nature is a complex one, it doesn’t matter how many constructors of methods we have, or whether the functions do not abide by the Law of Demeter. That is irrelevant if the solution does not solve the problem. The complexity of any given problem is a constant; the only way out is to change the perspective to the problem and abstract as much complexity as possible. When you abstract a complex problem, you end up with a large number of abstractions. Counting them is meaningless, BECAUSE THE PROBLEM IS A COMPLEX ONE and ITS COMPLEXITY WILL NOT CHANGE.
It’ll be extremely hard to come up with good numbers for all of these metrics. Yet, you should know about them and the reason for their existence. Then, when you are having a developer saying “Holy cow, I don’t understand the logic of this method, it has too many if then else, I’m lost.” you’ll say “Aha! that method may have a high CC” and go straight to the problem and solve it. Applying metrics to your source code is not magic, you still own what you write, and ultimately you have to know your business well to have elegant code. But hopefully with the help of these metrics and a couple of tools you'll make your code work like a charm and look neat as a pin.
This article is supporting the article “Definition of DONE” with regards of code analysis and best practices. FxCop is an application that analyzes managed code assemblies (code that targets the .NET Framework CLR) and reports information about whether the assemblies are abiding by good design guidelines and best practices. Things like architectural design, localization, performance, and security improvements are among the many things the tool will check automatically for you and give you a nice detailed report about its findings. Many of the issues are related to violations of the programming and Microsoft guidelines for writing robust and easily maintainable code using the .NET Framework.
On the home page of the tool says that "FxCop is intended for class library developers". Wait what? Class Library Developers? WTF, whatever...the fact is that the tool is good for any type of managed library, including service libraries, winForms and WPF projects. If it looks like a DLL, smells like a DLL, and it has extension "*.dll" or "*.exe" => FxCop will screen the hell out of it.
I also find FxCop a very useful learning tool for developers who are new to the .NET Framework or who are unfamiliar with the .NET Framework Design Guidelines. There is plenty of documentation online (MSDN) about the Design Guidelines and the different rule sets of best practices Microsoft recommends.
Think of FxCop as a bunch of Unit Tests that examine how your libraries conform to a bunch of best practices
FxCop is one of the tools I use to follow my Scrum definition of "Done" when writing code in .NET. But I also mentioned(wrote) about ReSharper Code Analysis features and how great they are and how we use them too. So the singular question becomes: WHAT IS THE DIFFERENCE BETWEEN FxCop and ReSharper Code Analysis?
The answer is simple:
- ReSharper Code Analysis analyses your .NET language (C#, VB.NET) source code.
- FxCop analyses the binaries produced by your source code. FxCop will look for the Common Intermediate Language (CIL) generated by the compiler of your .NET language.
In a sense, FxCop analysis should be done after ReSharper analysis, and will trap everything R# missed. FxCop was initially developed as an internal Microsoft Solution for optimization of new software being produced in house, and ultimately it made is way to the public.
Installing FX Cop
- Verify whether or not you already have the Windows SDK 7.1. If you already have the folder "C:Program FilesMicrosoft SDKsWindowsv7.1" on your FS, that means you have it; otherwise you need to install it. If you have it, skip the next steps.
- Download the Microsoft Windows SDK for Windows 7 and .NET Framework 4. You can download the web installer from HERE or search in Google for "windows sdk windows 7 web installer .net 4.0". Make sure you are downloading the one for .NET 4.0 and no other one.
- Install the SDK with the following settings
- Install FX Cop 10 by going to "C:ProgramFilesMicrosoftSDKsWindowsv7.1BinFxCop" and running the setup file.
Using FX Cop
There are 2 ways of using FxCop: standalone or within Visual Studio.
Using FxCop in standalone could not be simpler. It works similar to VS in the sense that you create projects where each project is nothing else than a collection of DLLs that are analyzed together (called targets in FxCop... why not, Microsoft).
To use FxCop as a Visual Studio tool:
- Open VS and go to Tools->External Tools
- Add a new tool and call it FxCop with the command line tool pointing to "C:Program Files (x86)Microsoft Fxcop 10.0FxCopCmd.exe"
Now without leaving VS you can either run it as a CMD line tool by going to Tools->FxCop OR you can configure your projects to enable code analysis when you build your project. Doing it the second way will allow you to get the errors and warnings on the same build output window you get compilation errors.
FxCop is a very solid tool to enforce good practices on your projects and assemblies, and it offers a wide array of configurable features not on the scope of this article. Ultimately you can write your custom rules for FxCop and enforce them as part of your project code analysis. Visual Studio integration is also a great way to maintain your code as you write it.
For more resources on FxCop, check out the FxCop Official Blog.
This article is supporting the article "Definition of DONE" with regards of code cleanup.
Having your code CLEAN is not only elegant, but also a good practice and habit to have specially if you work in a team environment. Every developer have their own styles, likes and dislikes when it comes to code formatting, ordering, grouping regions, etc; precisely because of this, is always good to get the team together, crack-open some Red Bulls and come up with your code standards and practices (and while you are at it, put them up on the Wiki). You can then use automation tools for your IDE to speed up the process and make sure everybody is generating and organizing their code files using the same rules. In my case, at work, we are living in the .NET world and ReSharper 4 or later in Visual Studio does the trick perfectly for us.
ReSharper has a feature called "Code Cleanup" that accomplishes exactly that: it automates the suggestions from the "Code Analysis" and applies them to code files. You can remove code redundancies, reorder type members and remove redundant using directives among many other things. This is not the only one of the many useful things ReSharper offers to .NET developers, but is certainly one I use the quite often. Let's see how it works.
At the time of this article I'm using VS 2010 and ReSharper 5.0, so all images are representative only of such software and version.
Make it perfect in one machine
The first thing is to configure all the settings in ReSharper on one machine and then share your settings. There is plenty to go through and each team may have different requirements. For example, by default ReSharper has the inspection severity on the unit "Redundant 'this.' qualifier" to "Show as warning" and in my team WE DO LIKE to use the 'this.' qualifier regularly, so we changed the R# setting to make "Show as hint". Things of this magnitude does not impact performance in code execution, the compiler simply ignores it; and they are more of a "style" type of inspection you can always tailor to your specific needs.
Once you have your Dev Box all configured, simply export your settings so the rest of the team can use them.
You can download the style we are currently using HERE.
That is the official way of sharing things using ReSharper, BUT... there is a small problem: that only shares the code inspection rules of the ReSharper settings and not other[important] things like the "Code Cleanup" settings. Breathe with ease ninja, there are solutions.
- If you have ReSharper 5.1 => you can use Resharper Setting Manager. This is an open source tool (CodePlex hosted) that allows you share ALL of your R# settings very easily. Officially you need R# 5.1 for this tool; I've tried it with R# 5.0 and have had a success rate of 0.5 (there is some black magic going on there that makes it work only half of the time with R# 5.0).
- Go old school and just copy the settings straight from the application data on your installation folder. Just navigate to %appdata%JetBrainsReSharperv5.0vs10.0 and copy the files UserSettings.xml and Workspace.xml to your repository (or a share folder, or email, or... ). You can then get those settings from other dev machines and put them in their respective places (close VS first).
Now when you open VS on the other dev machines you'll find the same configuration and code cleanup settings as the original box. Sweet!
Using Code Cleanup
When using VS with a source code file open, the code inspection engine will always notify you of how well (clean) your code is doing with regards to your R# settings. The keyboard shortcut to run the code clean up is Ctrl+E+C or Ctrl+K+C depending on the shortcut schema layout you are using. After you run it, things will be looking better for you ;)
- Red light means there is a BREAKING change on the code, and will probably not compile.
- Orange light means the code doesn't have any breaking changes, but it can be improved. You'll get some warnings and some suggestions.
- Green means you are good to go buddy. Ready for commit.
Part of our Definition of DONE is to get a green light on your source files. No exceptions.
You can find some more useful features of ReSharper like solution-wide analysis HERE.
I've been using SCRUM to manage my team for sometime now. When a new member joins the team one of the first things to get him/her up to speed is to get them aquainted with the team definition of "DONE". So here we go. When thinking whether or not a work item is "Done", ask yourself "Is this feature ready to be shipped?" if the answer is not a STRONG yes, then it is very likely the work is not "Done".
One basic principle we can follow when developing features and trying to complete work is:
-> IT IS OK TO BE BASIC, BUT NOT OK TO BE FAULTY
-> "Done" != "Done Enough"
-> "Done" = Shippable
A developer can say a work item is "Done" when:
- The case have specification and an entry with the specification in FogBugz (we use FogBugz for issue and bug tracking)
- The item was planned, designed and had an estimate (in time).
- Coding completed
- Code clean-up:
- Code was commented and checked-in
- Peer-to-Peer review happened
- Coding standards and code quality
- Code security review
- Hallway usability tested
- Unit tested (when there is a unit test sub-case)
- Wiki: Always have a wiki page documenting your feature and the components involved in it, like what tables, folders, configuration elements, etc.
- Release Notes: When configuration or deployment instructions change, it must be documented.
- Item was signed off by appropriate personnel and the FogBugz case was closed.
Some rules that apply to the definition of "Done":
- "Done" only applies to all user stories & sub-cases that also have children (in FogBugz)
- Only "Done" cases can be closed
- Only create Unit Test for items with a "Unit Test" sub-case.
- If the user stories has a "Unit Test" sub-case, then the unit test must be created prior to the actual implementation of the case.