One defect that I've been finding once and again in the past doing .NET projects is a bad exception handling strategy.
Too many times I've seen code that just places a generic try { ... } catch(Exception ex) { ... } code block to capture errors. And of course any code inside throwing generic exceptions (just with different messages).
The System.Exception class it is indeed the basis of any error that happens, but it is a bad habit to reuse it. Exception represents a fatal error, something critical unexpected.
.NET provides the System.ApplicationException class for a simple reason. To catch any exception from our applications.
It inherits from Exception, so a generic catch (Exception ex) would catch it anyway, but by using it, we differenciate between those exceptions generated by our application and those generated by external factors, like for example an OutOfMemoryException.
But if we just use ApplicationException instead of Exception we only have two layers of error levels... Why not going a step further and building a full hierarchy of exceptions?
Look at that descending list... We can catch a lot of stuff from different layers:
The easy way is to stick to simple Exception throwings and catchings, but it doesn't helps your code readability. And probably, it won't help too much when the application fails and you just get a generic "Exception" in your log (it is amazing, but some people forget to at least log the full stack trace...).
And all of this can be applied to PHP too. PHP contains just two base exception classes, and a few typical derived ones.
So don't be lazy and create a hierarchy of exceptions. You, your colleages, and everyone who could use your code or the compiled components will not regret it, I promise.
Some coding guidelines and best practices advice against the use of continue and break statements.
With continue the solution is easy, placing an if (or if it existed to call continue, negate it to execute the code).
But with break, it is not always so easy. Some times, in fact the resulting code is more messed up or harder to read (usually because of too much ifs), so I use break sometimes in my code if avoiding it is going to be worse for readability.
The most common case of using the break statement is looping through an indexed array of elements searching for something:
int[] numbers = { 1, 2, 3, 4, 5 };
for (int index = 0; index < numbers.Length; index++)
{
if (numbers[index] == 3)
{
break;
}
}
How to avoid here the break? As one of my bosses taught me, remember the tools at your disposal; A for loop contains three parts: initialization expression, condition expression and loop/increment expression. Nothing forbids us to add additional checks to the condition expression, as in the following improved code:
int[] numbers = { 1, 2, 3, 4, 5 };
bool found = false;
for (int index = 0; index < numbers.Length && !found; index++)
{
if (numbers[index] == 3)
{
found = true;
}
}
We are short-circuiting the loop, but in a soft and more elegant way (and not commonly seen in the code!).
Sometimes, thinking in generic terms, instead of specific cases/problems, pays off later with greater benefits. I'm going to show you a small real world example.
When you develop a mobile website, you usually create at least two visual themes, and usually go up to three:
If your website is properly developed, all the "mobile versions" will have a common logic layer and data layer (or if it's an MVC, common Models and Controllers), so it's just a matter of detecting what version the visitor falls into and rendering the appropiate view(s).
For WML is quite easy with the HTTP Accepts header, but with the more capable devices, we usually rely on checking the HTTP User Agent header.
As an example, this is an iPhone with 3.0 OS user agent string:
Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A542a Safari/419.3
For an iPod Touch is almost the same, just changing the "iPhone" with an "iPod".
At first glance, a small regular expression to detect the words iPhone and iPod would solve the problem, no?
Well, it does, but not in a generic scope. Let's see now how an Android user agent looks:
Mozilla/5.0 (Linux; U; Android 1.5; en; HTC Magic) AppleWebKit/528+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20
Using the proposed approach we would have to add "Android" to the "nice devices" list, but until then we would be rendering on all Androids the less fancy XHTML version.
But the alternative, is to search inside the user agent for two words, "Mobile" + "Safari" (order matters!). If you look at both user agents, they both are WebKit implementations, so both are Mobile Safari browsers. Using this second approach we already support all present and future Android devices without changing our code. In fact, we will support any new browser based on Mobile Safari!
So the lesson here is to try to go for a generic approach. In this example, targeting for browser type instead of specific device id gives a lot more flexibility with the same effort and even lowers the need of modifying the code in the future.
Disclaimer: I've been only working for few months in high-scalability stuff so don't expect super-secret techniques or expert advices. It is just a newbie 5-point basic list based on what I've learned and read about this subject up to now ;)
And as an extra, talking about web, prepare to enter the hell of browser incompatibilities, limitations and hacks. Desktop development is a piece of cake compared to any medium-complex web project.
Update: Here's an interesting round-up article about an example of .NET scaling.
Almost everybody understands the burden that represents managing a project (or even a company) with multiple tools: bug tracking, version control (not full source code, just labeled/released binaries), documentation, task tracking...
There are an almost infinite spectrum of tools to aid on some of those tasks, but the problem usually is moxing (or directly integrating) them. Microsoft's Visual Studio Team System tries to integrate the most common ones (even more coding-oriented stuff, like source control and automated testing), but installing a Team Foundation Server is not an option for everyone (for example, me).
One of the things I love most of all this internet era is the concept of hyperlink: you are reading in one place, and with just a click, you can navigate to another place. No more going to the index of a document and clicking on the desired chapter/subchapter, you just click and you're there.
Hyperlinks are not only the basic pilar of internet, they are useful even "offline". If you usually read PDF books, how often have you cursed the PDF creator for not placing "bookmarks" on them? And even with them, wouldn't it be easier if you are on chapter 11 and the book mentions Web Services' session state and you want to quickly check what it meant?
As a real world example, last year I wrote a 30 pages word document with UML use cases. Apart from the all-known index listing all of them, I placed hyperlinks inside the use cases that depended on or used other use cases. That way, looking at a specific use case took a whole less time (and since hyperlinks don't work on printed paper, we saved trees too :P).
Hyperlinking in a word document is fast and easy to do. But why restricting yourself to just that? Why not having everything hyperlinked and available from one place without having to buy an expensive server and licenses?
A few weeks ago I installed a wiki * on my home server. The needs I wanted to acomplish with it where:
Few weeks later, I can't be more pleased to have taken this approach.
I now have a basic fully-working wiki structure, being able to access my stuff by project name, by category ("TODOs", "KB", ...) or by searching. I can attach a zip containing a code snippet to a post idea and later retrieve it in a second. If I think of an improvement for Kartones.Net I can annotate it in seconds. Any KB article can link to another, to internet resources, or contain a batch file to execute.
And as an added bonus, I am modifying the wiki's engine to disable all non-desired functionality so it just does what I want the fastest way it is able to.
My Google Docs. "workspace" is now empty of dozens of individual documents that were harder to link between, and as the wiki detects things like orphan pages, if I forget to setup the categories for a new page, I'm warned about it, so all is added in harmony.
This might not be the ultimate solution. For example, my source code repository can't be integrated on a wiki. A company timesheet managing application or a professional bug tracking application can't neither **. But I have spent 0 money and less than one hour to have it running and ready to configure and add contents.
* I have installed Screwturn Wiki 3.0 beta. It's made in .NET (so I can customize and extend it) and doesn't uses a DB so its fast to deploy and use, but any wiki engine will suit your needs.
If you decide to use the same engine, be aware that the binaries for the beta are compiled in debug mode. I recommend downloading the sources and rebuilding in release mode for a small speed boost.
** If it is web-based, the wiki could be extended to support some kind of iframes, but it would be more a trick than a real integration.