Posts tagged with 'c'
Welcome to another "Weekly Concerns". This is a post-a-week series of interesting links, relevant to programming and programmers. You can check out previous Weekly Concerns posts in the archive.
- Why Your Previous Developer was Terrible - I tend to lash out emotionally when I see bad code, but I always feel uncomfortable blaming the previous developer, since I have no idea what kind of constraints (personally and professionally) they were working under. It's not always possible, but I try my best to seperate the art from the artist (and the code from the coder).
- Learn CSS Layout is an interesting CSS tutorial, that kinda reminds me of the various koans and git immersion types of tutorial sites.
- Did you see that "Everything from a 1991 Radio Shack ad is now done on your phone" thing making the rounds recently? Here's another analysis of technology costs then and now. Very roughly, the equivalent technology is not the $3000 nominal price in the Radio Shack ad, but at least $3.56 million.
- In MySQL, there's a sometimes handy GROUP_CONCAT function built in. Pete Shearer shows a way to accomplish something similar using FOR XML PATH and Microsoft SQL.
If you have an interesting link that you'd like to see in Weekly Concerns, leave a comment or contact me.
In the last post, I added some compile time validation to make sure that the aspect is being used in the correct places. Today, we're going to look at actually logging the exception.
Remember early on when I said that this aspect is not generally applicable? For this part, it's especially true, since I'll be using a specific logging library + service: Exceptionless.
The application that I'm working on is meant to be deployed to an Azure web site. Because of this, I have to think a little differently about logging. You can still log to the file system, of course, but on a cloud service that may not be the best idea. You could log to table storage on Azure Storage. You could also log to a normal database. However, I wanted to use something that: a) requires very little work, b) provides some useful monitoring tools that I don't have to build, c) is very low cost or free. So, based on my research and an endorsement from Mark Greenway, I decided to explore Exceptionless.
Using Exceptionless is as simple as installing a NuGet package, pasting in your API key, and then using an extension method.
Here's how I could use Exceptionless in my aspect:
This is very similar to what I did initially, but since this project is in development, I made a few adjustments along the way to make my life easier.
SQL exceptions. Especially during development, it's very likely that I'll screw up a SQL query, forget to run a migration script, etc. Additionally, since I'm using constraints in my database, I want to handle the case where a user is trying to delete an entity and a constraint is preventing them. So I modified the aspect some more:
The way I'm checking for "constraint" exceptions feels very hacky to me, but I haven't found a better way yet.
NotImplementedException. Again, since I'm still in active development, often times a NotImplementedException will pop up. For these exceptions, I want them to crash right away, and I also don't need to worry about logging.
Now that SQL exceptions and not-implemented exceptions are handled on their own, any other exception is one that I still want to log and output to the UI in a friendly, non-yellow screen way. During development, I definitely want to see the full exception message, but that's something that will definitely need to be revisited before going into production. Back to the list:
- This only works for ITerritoryService
- Swallowing exceptions: we should at least be logging the exception, not just ignoring it. <- We are now logging exceptions!
- If the method has a return type, then it's returning null. If it's meant to return a reference type, that's probably fine, but what if it's returning a value type?
- What if it's returning a collection, and the UI assumes that it will get an empty collection instead of a null reference?
- Do we really want to return the exception message to the user? <- We'll revisit this later.
- What if I forget to use ServiceBase as a base class on a new service?
Welcome back to another "Weekly Concerns" (after skipping a week). This is a post-a-week series of interesting links, relevant to programming and programmers. You can check out previous Weekly Concerns posts in the archive.
- If you haven't seen Seth Petry-Johnson's Patterns of Effective Test Setup presentation yet, you should at least check out his slides.
- Source code for MS-DOS and Word for Windows is now available.
- You can play Missile Command with a YouTube video. Just go to any YouTube video, like this one, and type "1980".
- Mark Greenway and myself did an introductory presentation on WordPress with Azure through the MVP Mentor program. A recording of WordPress with Azure is now available.
If you have an interesting link that you'd like to see in Weekly Concerns, leave a comment or contact me.
In the last post, we started using ServiceBase as a way to more generally address the services and use the callback to report errors to the UI.
What happens if I put the aspect on a method in a class that doesn't inherit from ServiceBase (because either I forgot, or I put an aspect on a class outside of the service layer by mistake)? Exceptions will be swallowed, not reported, and probably cause issues elsewhere in the project.
One approach would be to change the case from "args.Instance as ServiceBase" to "(ServiceBase)args.Instance". At least then, I'll get a runtime error about casting (but only if there's an exception). With PostSharp, we can do better than that.
In fact, remember when I said that PostSharp aspects have to be marked as [Serializable]? This is because, as compile time, PostSharp instantiates those aspect objects and serializes them to be used later at runtime. BUT, since the aspect is being instantiated anyway, PostSharp also does a couple of other optional steps: it can do some compile-time initialization (to avoid runtime reflection, for instance), and it can do some compile-time validation.
That's right, we can put some code in the aspect that can check to make sure that we're applying the aspect correctly. If we aren't, it will give us a compile-time error. We could check, for instance, that the aspect is being applied to a method in a class that inherits ServiceBase.
This code will only be executed at compile-time. If the declaring type (the class that the method is in) does not inherit from ServiceBase, then PostSharp will write out an error at compile time:
So now if I ever forget to use ServiceBase, or I use this aspect in the wrong place, I'll know right when I'm compiling. And because of this validation, I can also confidently change the cast from "args.Instance as ServiceBase" to "(ServiceBase)args.Instance", knowing that if the project compiles, that cast will never fail.
How are we doing:
- This only works for ITerritoryService--what about the other services?
- Swallowing exceptions: we should at least be logging the exception, not just ignoring it.
- If the method has a return type, then it's returning null. If it's meant to return a reference type, that's probably fine, but what if it's returning a value type?
- What if it's returning a collection, and the UI assumes that it will get an empty collection instead of a null reference?
- Do we really want to return the exception message to the user?
- What if I forget to use ServiceBase as a base class on a new service? <- We just took care of this
Next time we'll look at actually logging the exception.
In the previous post, we got the aspect to communicate with the service object by using args.Instance. But it only really works for one service: TerritoryService.
How can we get it to work with other services?
One approach would be to add a bunch of casts and if-statements:
I don't like that approach much. Another approach would be to create a base class that all our service classes would inherit from. I generally try to avoid this approach as much as possible, but I think it makes sense in this case. We could create an interface, like IHasValidationCallback, but let's take it one step further and create an abstract base class that already contains the implementation.
Now that the TerritorySerivce (and our other services) have a ServiceBase base class, we can update the aspect to use ServiceBase.
And there you have it: as long as all the services in the namespace inherit from ServiceBase, this will work.
So I think we're making progress, but let's review the issues from last time:
- This only works for ITerritoryService--what about the other services? We just addressed this one.
- Swallowing exceptions: we should at least be logging the exception, not just ignoring it.
- If the method has a return type, then it's returning null. If it's meant to return a reference type, that's probably fine, but what if it's returning a value type?
- What if it's returning a collection, and the UI assumes that it will get an empty collection instead of a null reference?
- Do we really want to return the exception message to the user?
- NEW ISSUE: What if I forget to use ServiceBase as a base class on a new service?
Yep, we fixed one issue, but we really just shifted the problem to a base class that could easily be overlooked. Next time, let's see if we can get PostSharp to help us with that.