Three Is It

Because two isn't enough and four is just too many

Force always attracts men of low morality.
Albert Einstein
Home Blogs Genealogy Brad's Bookshelf Subscriptions Contact Sign in
 

About the author

Brad Butts is a .NET developer and architect. He is married with children and enjoys reading, working out, and genealogy is his five minutes of spare time.
E-mail me Send mail
National Debt Clock

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

CodeMash 2010: Day 2

It’s been almost a month since the CodeMash event…let’s see if I can still remember what happened on that second day.

 

Session: Oh, Crap!  I forgot (or never learned) C!

In my case, it’s kind of both: I took a single C/C++ class many, many years ago in college.

Chris Adamson led this session.  Chris is an active iPhone developer and said his primary motivation for proposing this session to CodeMash was the fact that Apple decided to create  Objective C as the development language for the iPhone.  Paraphrasing Chris, “the big-wigs at Apple must’ve gathered in a room and asked the question, ‘on what programming language can we base our development language for the iPhone?  I know!  Let’s base it on C.  Everybody knows C!’”  Unfortunately, nowadays, many people don’t know C—hence, the need for this session.

C was developed in 1972, primarily for the Unix platform.  The definitive book on the language is The C Programming Language by Kernighan and Ritchie.

LangPop.com still lists C and C++ (not to mention Java, a language inspired by C) as the most popular of development languages.  The Linux kernel and tools like SQLite and OpenGL have been written in C (according to the Free Software Directory).  Most interpreters are written in C.  Much of the iPhone is written in C.  Therefore, we should learn C!

What makes C great?  It’s portable: most OSes include a C compiler.  It’s performant and it’s minimal.

There’s no garbage collection in C, so you should be familiar with commands like malloc() and free().  The language is compiled, not interpreted, code.

C has the concept of a header file (.h extension) and the source file (.c or .cpp extension).  The header file contains functions and variable you want others to see—sounds like a contract to me.  The source file contains the actual implementation.  You use the #include syntax to include the header file in your source file.

Types in C include:

  • short, int, long, long long
  • float, double
  • char, bool
  • void

The dreaded beast of C is the pointer, but Chris addressed this pretty well in his presentation.  Overall, this was a nice refresher of concepts I learned years ago. 

 

Session: Looting Design Ideas from the World of Warcraft

Here was another instance when I was torn between two sessions: this one and one entitled RESTful Interfaces to Third-Party Websites with Python (by Kevin Dahlhausen).  There are many sites I’d like to scrape for data and the RESTful session might have been the ticket for that.  Nevertheless, I thought the Warcraft session my be informative since I have a project in mind that will probably need some good GUI design.  So, off to the Warcraft session.

I know vaguely what the WoW game is but have never played it.  Jason Follas went through several UI shots and the WoW architecture and pulled out some thoughts as to why the game is so successful—12 million subscribers at present.

The WoW interface is pretty busy with tools, meters, and other widgets; however, it appears quite customizable.  Here the key concepts Jason outlined to craft a successful interface:

  • Tool tips on the controls
  • Keyboard shortcuts
  • Customizable keyboard shortcuts
  • Add/remove widgets
  • The ability of the user to customize the UI is more important than developing the perfect layout
  • As a developer, you should deliver a simple, clean interface out-of-the-box, permit customization, and provide keybinding/shortcuts that can be customized

WoW is also extensible, with third parties offering ways to extend and alter the behavior of the game (like this one).  Extensible apps like WoW should allow the behavior of the app to be modified without requiring a recompile.  Allowing an app to be extensible give the community some “skin in the game” and can be a source of free research & development from the community.  Extensions in WoW can occur in many ways:

  • Macros – chaining multiple commands together under a single command
  • Public API – events (using the Observer pattern), methods, and UI widgets
  • Add-ons – a.k.a. “mods”
  • Scripts – via Lua, a C-based language with a small runtime

In .NET, extensibility can be achieved through the DLR (by using the ScriptRuntime class, for instance) or my using MEF.

From a data perspective, Jason talked about the importance of caching, logging (log everything), and making web services available.  Apparently, it is a popular practice for WoW players to grab the log file pertaining to a particular battle and run it through an analytics engine so that they can see which aspects of the fight they were weak in and learn to improve their play.

On the social side, Jason discussed chatting, guilds, game masters, and presence awareness.  The makers of WoW actually pay people to play the game as game masters.  As a player, you may occasionally encounter a game master who will come up to you and ask you if you need any help.

Finally, Jason talked a little about money aspects of the game.  WoW is successful, in part, because it focuses on a subscription model.  The software itself is largely free—you just have to maintain a monthly account to play the game.  Making recurring payments easy is a way to retain subscribers.

 

Lunchtime Keynote: The Mother of All Bugs

Popular author Andy Hunt gave the last keynote of the conference.  And what is the mother of all bugs?  Why our brain, of course!  We’re neither logical nor rational.  We make processing errors, we can’t predict a most outcomes (see The Black Swan), and we tend to allow contextual influences to slant our decisions.

Andy enumerated many cognitive biases that plague humanity.  These include:

  • Anchoring/arbitrary coherence
  • Fundamental attribution error
  • Need for closure
  • Confirmation bias
  • Exposure effect
  • Hawthorne effect – on average, it takes 3 weeks before a practice becomes habitual
  • Relativity
  • Free isn’t cheap

Extending upon contextual influences, Andy noted that different and competing personality traits play a factor (Myers/Briggs work has identified 32 different personalities among the masses).  Deeply held values—what you value and why—is also a strong factor.

Andy also looked at our buggy brain problems at a generational level.  He described four generational archetypes:

  • Prophet – a generation emphasizing vision and values
  • Nomad – a generation valuing liberty and survivalism
  • Hero – a generation associated with community
  • Artist – a generation focused on pluralism

Andy then overlaid these archetypes with historical generations:

I always find it interesting to see how researchers attempt to identify generational groups.  Much of the time, though, I think it’s pretty silly: everyone throughout time is unique and individualistic—shaped by the events and time in which he was born, sure, but also shaped by his geography, community, and biochemical makeup.  Or maybe that’s just the Nomad in me talking.

The final thought Andy left us with to help mitigate the bugs we create is: Trust, but verify.

 

Session: Introducing the MVVM Pattern

Again, I found myself choosing between two interesting sessions: this one and one entitled IronPython with ASP.NET (Chris Sutton).  Then I considered the fact that Microsoft appears luke-warm in their support of IronPython and thought my time would be better spent learning more about MVVM.

Brian Genisio ran this session.  So, MVVM (Model-View-ViewModel) is this variant of MVC where you have a ViewModel class sitting in between your View and your Model.  A binding relationship typically exists between the View and the ViewModel.  The View can also push actions to the ViewModel.  Data and events can be shared between the ViewModel and the Model.  You can actually have your XAML reference your ViewModel as such:

<Window.Resources>

   <ViewModels:blah x:Key=”ViewModel”>

For more details, Brian listed some of the popular opinion leaders on patterns and especially MVVM:

He also enumerated some “mini-patterns” that are relevant in this space:

  • NotifyPropertyChanged via the INotifyPropertyChanged interface
  • Command Pattern (Delegate Command)
  • Event Aggregator (Publish/Subscribe similar to the Mediator pattern)  [Brian noted that there are problems with the Observer pattern.]
  • Attached Behaviors (eg. command binding)

Brian laid out several guidelines for implementing MVVM, including:

  1. Get your code out of the code-behind
  2. Bind UI inputs/outputs to the ViewModel
  3. Implement INotifyPropertyChanged
  4. House “behavior” in the ViewModel
  5. Refrain from maintaining ViewState in the Model

Some frameworks to help you get started using MVVM include:

Testing frameworks to help you better test your MVVM components include:

 

Session: Analyze and Optimize your .NET Web Application

At last, we reach the final session of the conference: James Avery leading us down the jagged path toward ASP.NET optimization.  James geared his presentation largely around his own personal experiences optimizing web applications.  He’s found that you shouldn’t code with performance optimization on your mind but rather just code then measure afterwards: build & measure.  When you measure performance, you measure, then modify, then measure again.

In his estimation, there are three tactics for optimization:

  • Optimize the code – this is usually not the problem
  • Optimize the database and/or network
  • Cheat (by caching data)

His presentation, which was basically all coding/optimization, followed these steps:

  1. Measure the application (using Pylot)
  2. Profile the application (using ANTS Profiler)
  3. Profile the database (using SQL Profiler)
  4. Run Pylot again and look for any improvements

At one point, James dove deep into LINQ and lazy loading versus eager loading.  There are advantages to either approach, particularly concerning optimization, but I don’t remember exactly what they were.  I believe, in the demo’s case, that he wanted LINQ to do eager loading and he had to dive into the guts of it to make it work.  He also mentioned something about Plinqo.com, but don’t remember exactly what he said about that, either.

Regarding caching, James said that you basically have two options:

  1. Output caching, where you deal with caching the page
  2. Fragment caching, where you deal with caching data

For optimization purposes, fragment caching is usually the ticket.  Typically, you use HttpContext.Cache to do this.

 

That’s It

Whew.  That’s the end of my notes.  Man that was painful, but chances are, some of this might help me down the line.  As I’ve said before, CodeMash is cheap and relatively close…so it’s certainly not a bad deal, although it does place some added stress on my already tight domestic schedule.  Will I do it again next year?  Don’t really know: I’m changing roles at work which will take me almost entirely out of software development, so the conference may no longer be relevant to me this time next year.  I’ll just have to wait and see.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Wednesday, February 10, 2010 10:40 PM
Permalink | Comments (0) | Post RSSRSS comment feed

CodeMash 2010: Day 1

Well, another CodeMash is in the books and here is my write-up of the sessions I attended.

 

PreCompiler: Not to Be

Again this year I skipped the PreCompiler—it just wouldn’t have been logistically feasible.  Joe O'Brien and Jim Weirich, again, did the Ruby Koans—which, one of these days, I will step through on my own.  Jeremy Miller did a session on Advanced Presentation Patterns that would have been cool to attend.  And Jon Kruger led a session entitled Software Engineering Fundamentals Workshop: OOP, SOLID, and More that looked quite interesting.  But, alas, it was not to be.

 

Opening Keynote: Mary Poppendieck, The Five Habits of Successful Lean Development

Mary, and her husband Tom, are rockstars of the Agile/Lean community.  Agile/Lean is just something I haven’t grokked yet—I’d probably have more success understanding the process if the styles were practiced at my company (instead, we’re more of an 80s flashback to the days of RUP and Waterfall). 

Anyway, Mary’s Five Habits were: Purpose, Passion, Persistence, Pride, and Profit.  She went through several examples of companies that practiced one or more of these habits and highlighted the subsequent financial and market successes that resulted.  One funny moment was when she defined Cost Center Disease: when a company or division focuses on cost reduction to show increased profit instead delivering value.  Several heads nodded in understanding.  I also liked the quote she mentioned: “if you never fail, you’re not trying.”

Even though I don’t see Agile/Lean practices in my future, I did like what she had to say about practicing your art—whether that’s Agile/Lean mastery, vanilla software development skills, musicianship, bending nails, etc.—to the point of becoming an expert in your field.  She said that it takes 10 years or 10,000 hours of deliberate practice to gain expertise in your chosen field(s).  Deliberate practice includes the following challenges:

  • Identifying the skill that needs improving
  • Devising an exercise(s) to improve the skill
  • Practice
  • Obtaining feedback
  • Pushing your limits (like this, for instance)
  • And regular, intense practice

Elements that can facilitate your Deliberate Practice include:

  • Finding a teacher/mentor
  • Crafting new challenges
  • Getting feedback
  • And good ‘ol dedication

She talked about Improvement Katas—I always find the use of that term by technology geeks amusing because most of those folks wouldn’t survive five minutes in a real martial arts dojo.  Nevertheless, her points were right-on regarding how to become an expert in your chosen field:

  • Visualize what perfection looks like
  • Develop a first-hand grasp of your current situation
  • Define target conditions on the way to perfection (small, measurable milestones on the way to your goal)

I have a lot of goals for 2010 and I will definitely be looking back at these notes to construct an appropriate game plan to achieve each one.

 

Session: What Makes Ruby Different?

It seems like all of geekdom is buzzing—and has been buzzing for a while—about Ruby.  What gives?  Inquiring minds want to know.  So, I attended this session led by Marc Peabody, Joe O’Brien, and Leon Gersing

The format went something like this: Marc would present Java code to perform a particular operation, then Leon would present C# code to perform the same operation, and finally, Joe would step in to show how Ruby makes both technologies look stupid verbose/cumbersome since it can perform the same operations with significantly less lines of code.

The trio targeted six main areas:

  • List Iteration—you should be able to tell a list what it should do, not have to ask a list for its data and then perform operations on it.
  • File I/O—File I/O operations in Ruby are simple and to-the-point: file.open(“myFile.txt”) do …
  • Interfaces/Contracts—No interfaces or compiler-time checking in Ruby.  Duck typing is king and unit testing is critical.
  • Config Files/Annotation—Don’t remember exactly what they said about this, but since everybody now seems to hate XML config files, I’m sure it was something about the badness of that.
  • Utility Classes—Utility classes in Ruby smack of a domain specific language (DSL) which is quite cool and hip.
  • Dependency Injection—Again, my notes are scant, but I believe the three said that, while DI buys you much in our statically-type languages, it doesn’t offer much to Rubyists and most folks don’t even go there.

 

Session: Maintainable ASP.NET MVC

Chris Patterson ran this session.  I’m not exactly sure what I was hoping to get out of this one—I’ve been to a few ASP.NET MVC sessions before (including the Firestarter event back in October), so I feel like I’m at the point where it’s time to stop listening and start doing.  My notes, or lack-thereof, kind of reflect that.  One thing I could stand to learn more about are the classes and methods commonly used in the server-side script in a View.  I noted that there’s an Html class with a BeginForm method (guess that’s called a FormExtensions class/library?) and that there’s a related Ajax class with its own BeginForm method (presumably, to ajaxify the form).  The FormExtensions stuff will definitely take some getting used to.

 

Lunchtime Keynote: PHP and Other Adventures in Open Source

I am all about making the most efficient use of my time as possible.  I subscribe to over 80 different podcasts and listen to most of the shows while commuting to and from work, going for a run, mowing the lawn, or doing other sundry tasks.  I pack my lunch so I can eat at my desk and meander through Google Reader at the same time (and to save money).  So I’m quite sympathetic to why the CodeMashers would schedule key note speakers while we eat.  I just feel bad for the speakers as the rest of us clang silverware and have moderately loud table conversations.

The subject of one’s keynote also certainly has an effect on the level of attention he’ll receive.  In this one, Hank Janssen discussed PHP, Linux, Open Source, and Microsoft.  Mostly, it was about Hank and his work at Microsoft to get the company to be more open source-friendly.  Sorry, but a little bit of a yawner for me.  I do appreciate the effort, though: for instance, I am a big fan of WiX, Microsoft’s first open source project.

 

Session: PowerShell—Ten Things You Need to Know

I was quite torn between attending this session and the session Photoshop for Engineers: Going from PSD to HTML (by Joe Nuxoll).  I’m pretty bad at the UI side of development and need all the help I can get.  Photoshop is Greek to me, so I thought that the Photoshop session might be pretty enlightening.  Nevertheless, my inner voice of reason (one of them, anyway) got the better of me, saying: “you do framework development, not UI.  Whaddya gonna do with a session on laying out cool graphics on web pages?”  So, I went to the PowerShell talk.

Matt Hester and Aaron Lerch tag-teamed on this one.  I didn’t make a list of their Top 10, but here’s a list they had on why PowerShell’s important:

  • Rich scripting
  • Bulk operations
  • Interactive
  • Task Automation
  • Object-Oriented

When should one resort to PowerShell?  When you need to perform consistent, repeatable tasks.  Additionally, when you need to interact with Active Directory (just AD or any LDAP-compliant container?), the Registry, WMI, and other such repositories.

One of the attractive features of PowerShell is its consistency.  PowerShell commands are structured all in the same way: command (verb-noun) then parameters (name and argument).  For instance:

get-service –name “*net*”

The get-service portion is the command, structured in verb-noun format.  The –name “*net*” portion represents the parameters of the command, in a name/argument format.  Nice.

Let’s see…what else?  Matt and Aaron made heavy use of piping command outputs get-member.  This is a basic PowerShell technique to familiarize yourself with the members of the object(s) produced by your initiating command, but I seem to always forget that command.  Also, I must remember format-table and format-list, used to manipulate the console output produced by PowerShell commands.

They didn’t differentiate much between version 1.0 and 2.0, but a feature they noted that’s new in 2.0 is get-module and import-module.  A great many Microsoft products—BizTalk, SharePoint, Exchange Server, etc,—are beginning to ship with PowerShell modules filled with cmdlets designed to let you easily administrate the particular product through PowerShell.  In order to use these new cmdlets, you have to import their modules into your PowerShell session.

One feature they talked about which might help me with some of the work I do in the security space is the PowerShell Providers: get-psprovider.  PowerShell ships with several providers that are designed to help you navigate certain data repositories like your file system, the Registry, etc.  There’s one provider that will let you navigate the certificate store (simply by typing cd cert:).  I must investigate that further.

One of the last things they talked about was writing your own cmdlets in C#—inheriting from either PSCmdLet or CmdLet—and adding user interfaces in front of your PS script.  There’s a new feature in PS 2.0 where you can output data to a sortable grid in a dialog—very similar to LogParser.  I wonder if they’ll borrow any other features from LogParser.

Probably the biggest reason I attended this session over the Photoshop session was that Matt and Aaron promised to talk about Psake.  I had been messing with builds recently, was getting frustrated with something (don’t remember what), and wanted to explore other options besides the conventional MSBuild and Nant options.  I remembered hearing about Psake, so I downloaded it and started to play with it, but got nowhere fast—couldn’t find much help online, either, so I was looking forward to hearing Matt and Aaron talk about it.  Well, it was quite a let-down: Psake appears to be nothing more than a skeleton script where you fill in all the details about how to build your app.  I guess that makes the approach more technology-agnostic, but the lazy side of me was hoping for a turn-key solution.  Anyway, at least I have a better understanding of how to use the project going forward.

 

Session: Refactoring the Programmer

I could have sworn this was a Jeremy Miller session.  I wanted to attend at least one of his presentations.  Thought this was the one.  Guess I can’t read.  Anyway, Joe O’Brien did this one.

I usually try to avoid the touchy-feely type presentations.  The ones that target the softer skills.  I tend to think I’m pretty good at the interpersonal and communicative-type skills: if not, I’m probably not going to learn those skills from geeks, anyway.  Nevertheless, here are some of the take-aways I jotted down from this session:

Joe said, “you are responsible for your own growth: invest in yourself.”  Makes sense.  Who else would be looking out for me?  He then went into ways that he has invested in himself over the years.  He talked about his leading technical indicators.  One of his indicators is attending conferences (the realm of the alpha-geeks).  This helps him answer the question: “do I need to spend more time with [enter technology of the moment]?”  If he hears of a technology discussed more than four times, he should look it up (the Rule of 4).  If he hears of a technology discussed more that eight times, he should start playing with it (the Rule of 8).  He also tries to pay attention to the speakers at the conferences he attends.  He’ll make a judgment as to whether he should follow a given speaker via blog or twitter.  Of the folks in the industry he follows, Joe has developed an inner circle and an outer circle.  His inner circle is small—four to five individuals.  These are folks (like Neal Ford) he trusts to lead him through the technology mine field.  His outer circle is a collection of many others who sometimes give great advice but must also be viewed with a degree of skepticism.

Joe also suggested that developers should endear themselves to their communities.  They can do this in many ways: participate in an open source project, attend and participate in the local user groups, attend conferences, and even get into things like podcasting or webcasting.  [note to self: Joe also mentioned a great way to learn Ruby was to take the quiz at RubyQuiz.com]  Finally, Joe suggested three books for helping you kick your programming career into gear:

 

Session: Testing ASP.NET Applications Using Ruby

At work, one of my current pain points is testing around my component’s frequent use of HttpContext.  Were I building on .NET 3.5 SP1, I would just refactor the component to make use of HttpContextBase, an abstraction of HttpContext that can be easily mocked.  Unfortunately, other requirements prevent me from moving up to that version, so I now have to think of other ways I can isolate these web components so that I can better test my code.  Is there any way Ruby can help me? 

Ben Hall presented this session.  What was funny was that I had just gotten through listening to a .NET Rocks interview of Ben on the drive up to CodeMash.  Now, here he was, to talk more about testing in person.  Now that’s pretty cool!  [note to self: Ben did write a book called Testing ASP.NET Web Applications that I may want to check out at some point.  He also put up an accompanying website.]

Well, the short answer is, no, Ruby (or, rather, IronRuby.NET) can’t help my particular situation.  Nevertheless, it is pretty fascinating what you can do with the platform and how you can use it to unit test your .NET binaries.

At some point, Ben went into various tools he uses or had used for testing.  Here’s the list I wrote down:

Ruby is still Greek to me, but here is some code I wrote down that I found interesting:

  • Setting a reference path?  $:  << ‘../someDir/bin’
  • Setting another reference path?  $:  << ‘../lib’
  • Bringing in a .NET assembly into your IronRuby code: require ‘myAssembly.dll’
  • Instantiating a class of a .NET assembly in IronRuby:  describe MyNamespace::MyClass.new

 

Evening Entertainment: Enter the Haggis

Normally, the evening entertainment at CodeMash consists of a bunch of relatively-drunk geeks standing around talking about technology until 2am.  Personally, I don’t find that very entertaining; however, I normally mill around for a few hours before retiring for the evening.  BTW: I wish I would have made this suggestion on the CodeMash suggestion board—we need an alternative to the raffle ticket thing.  When you register, you’re given a beer ticket (ticket for one free beer at the nighttime party).  Throughout the conference, you might receive other tickets from various vendors for prize drawings at the end of the conference.  I happened to have lost all these tickets over the course of the day.  Kind of a bummer.

Anyway, this year, the guys at EdgeCase actually hired a band, Enter the Haggis, for the evening.  Although from Canada, they’re all about the Irish rock, combining bagpipes and fiddle with guitar and drums.  The music was fantastic.  I would have bought one of their CDs had I not left my money in my room.  Regardless, they did a great job and it was a nice way to close out the evening.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Monday, January 25, 2010 10:21 PM
Permalink | Comments (0) | Post RSSRSS comment feed

PowerShell vs. the GAC

Some time ago, I had a need to look up an assembly in the GAC or some such operation—can’t remember exactly what I needed to do—but was surprised to find no easy way to use a Visual Studio command line utility or even PowerShell to do the work I needed.  Well, a few days ago, I come across this post on how to produce a list of all assemblies in the GAC.  Sweet.  However, let’s do a little more tinkering. 

First, let’s use the windir environment variable so I can make my script a little more portable across OSes.  Second, let’s go ahead and pipe the output to System.Reflection and go ahead and get something nice—like, say, the fully-qualified name of each assembly.  Now we’re talking!

Get-ChildItem $env:windir\assembly\GAC_MSIL -filter *.dll -recurse | %{[System.Reflection.Assembly]::LoadFile($_.FullName).FullName}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Monday, January 11, 2010 9:53 PM
Permalink | Comments (4) | Post RSSRSS comment feed

CodeMash 2010

Yep.  I’ll be attending yet again for another fun-filled few days of codemasherie.CodeMash2010

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Monday, January 11, 2010 9:12 PM
Permalink | Comments (6) | Post RSSRSS comment feed

Key/Value Pair Configuration Section

Here’s another suggestion for Microsoft: give me a nice key/value pair configuration section.

Now, you might say, don’t you already have appSettings?  The appSettings configuration section is certainly handy, but occasionally, I’ll have to store sensitive data in my configuration file—data required to be encrypted.  I’ve made a few attempts to encrypt the appSettings section to no avail, although I’m not sure why it won’t encrypt—the new System.Configuration.AppSettingsSection v2.0 implements System.Configuration.ConfigurationSection, which tends to play nicely with the configuration encryption infrastructure…so either I’m not doing something right or I’m missing something.

You might say, fooey on appSettings, why don’t you put your secret in the connectionStrings section and encrypt that?  I could do that (and I know it does play nicely with configuration encryption), but what if I have sensitive data I need to store that’s not a connection string—like a plain old password?  That would look kind of silly in a connectionStrings section:

<connectionStrings>
  <add name="myPassword" connectionString="bob sent me"/>
</connectionStrings>

In code:

string myPassword = ConfigurationManager.
                ConnectionStrings["myPassword"].ConnectionString;

 

I just don’t think that reads very well.

No, what I really want is a third option: a good ‘ol Key/Value pair configuration section that will encrypt/decrypt consistently.  Well, interestingly, two-thirds of the work to make such a section available is already done in the .NET framework. 

Most custom configuration sections require that you implement three abstract classes: ConfigurationSection, ConfigurationElementCollection, and ConfigurationElement.  As it turns out, the .NET framework already contains a public System.Configuration.KeyValueConfigurationCollection which manages a collection of System.Configuration.KeyValueConfigurationElement objects.  The only thing left to do is to expose this collection to configuration via an implementation of ConfigurationSection.  It’s as simple as this:

using System.Configuration;

namespace Brad.Configuration
{
    public class KeyValueSection : ConfigurationSection
    {
        [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
        public KeyValueConfigurationCollection Settings
        {
            get
            {
                return (KeyValueConfigurationCollection)this[""];
            }
            set
            {
                this[""] = value;
            }
        }
    }
}
It’d be nice if such a class were already available in the framework instead of me having to code the last piece.  Maybe some nice Microsoft employee can add this class in a future release.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Tuesday, September 15, 2009 11:38 PM
Permalink | Comments (1) | Post RSSRSS comment feed

Powershell vs. Lotus Notes

I’m writing this post for the same reasons that I write most of my posts:

  1. Because once I solve a problem, the solution tends to decay quickly from my mind.  If I don’t get it down on paper in some coherent form, it will be gone—and a month from now, I’ll likely need it again. 
  2. And because I’m sure there are many better ways to solve this problem.  My horrible googling skills came up empty, so this is the best I could do.  It works, but I’m sure there are more elegant ways to do this.  Perhaps a more savvy script writer could educate me.

Overview

At work, we develop components, gadgets, and gizmos that others use to do their work.  When we have a new release of said gizmo or some other relevant event, we send out an email to our internal customers with the announcement.  Recently, we learned that there are many other employees in the company that are not on our email distribution list—folks who may also benefit from our products and services—so we wanted to contact these other people to see if they’d like to be added to our mailing list. 

Later, I may post on how I compared our current mailing list to this other list of people to find out who we were actually missing.  For now, assume that I have already sent out my solicitation email and have begun receiving replies.  In my solicitation, I said something to the effect, “if you would like to be added to our list, please reply to this email with the phrase, ‘add me to the list.’”  I wasn’t specific about where to place the phrase, so some respondents put the phrase in the body of their reply while others put it in the subject line of their reply.  Still others replied back with “no, thanks” and a few even replied that they wanted to be added, but didn’t use my phrase: eg. “sounds great!  Sign me up!”

I knew I didn’t want to go through all the replies by hand and add the affirmative replies, one-by-one, to my email list.  Rather, I wanted to find a way to programmatically process the replies and build a single list of affirmatives that I could add, in bulk, to my distribution list.  Here’s what I did:

Step 1: Export to the replies from Lotus Notes into a form I could process

Lotus Notes is not my email client of choice—that’s simply what I’m forced to use.  The SMTP infrastructure at my company is dark and mysterious; while I’m sure there are APIs I could program to, I decided that the quickest approach to extract the emails I wished to process was to simply do it the manual way.  I found that I could checkmark all the email I was interested in, then select the menu File > Export… and produce a single text file I could work with.  The file looked something like this:

email1

Step 2: Transform the replies into some delimited-type format that I could better process

Now, I had to get this dump of email into some form I could work with.  The first thing that came to mind was to see if I could use Powershell to transform the email dump into a delimited file.  If I could get the fields I needed to process into a delimited file, I could write a LogParser query to identify the individuals wishing to be added to my list.  Here’s the Powershell script I came up with:

$delim = "|"
$allResponses = Get-Content d:\Docs\email_dump

$principals = $allResponses | Select-String "^Principal:"
$abstracts =  $allResponses | Select-String "Abstract:"
$subjects = $allResponses | Select-String "Subject: [^My]"
$inetfroms =  $allResponses | Select-String "INetFrom:"

$newFile = ""

for($count = 0; $count -lt $principals.Count; $count++)
{
    $newFile += ($inetfroms[$count] -replace "INetFrom:  ", "") + $delim + `
        ($abstracts[$count] -replace "Abstract:  ", "") + $delim + `
        ($subjects[$count] -replace "Subject:  ", "") + $delim + `
        ($principals[$count] -replace "Principal:  ", "") + "`n"
}

$newFile > D:\Docs\delimResponses.txt

So, let me explain some of this….  I found that there were probably four relevant fields for my objective:

  • Principal—the English name (distinguished name) of the respondents
  • Abstract—the first line or first X number of characters of the reply
  • Subject—the subject line of the reply
  • INetFrom—the email address of the respondent

Most respondents placed the “add me to your list” phrase either at the beginning of their response (Abstract field) or in the subject line (Subject field).  Of course, I needed the respondent’s email address (INetFrom) to add to my distribution list, and the respondent’s full name (Prinicipal) was just nice to have in case the email address was too cryptic and I wanted to know the actual respondent’s name.

Anyway, I used the Select-String cmdlet to find all the instances of each field.  For the most part, the pattern match (a Regular Expression) was easy; however, initially, my Select-String pattern for the Subject field was just “Subject:”.  Unfortunately, this pattern not only picked up the respondents’ subject lines, but also the subject line from my original email, which was tacked onto the bottom of every email I received.  I had to figure out how to make sure not to capture that subject line.  So, I came up with the pattern “Subject:  [^My]”.  In Regular Expression-eze, this means, “match on all lines where the line begins with “Subject:  [and any characters that don’t begin with ‘My’]”.  After all, my original subject line was “Subject:  My team’s distribution list”.

[Side note: Regular Expressions drive me batty.  Fortunately, my buddy Rob is especially gifted at them and I tend to contact him when I get in a bind.  This tool was also helpful.  Recently, Jeff Atwood recommended this book as a helpful tool in crafting your regular expressions—think I’ll pick that one up.]

So, my script built arrays for these four fields from each email; then, I wrote a loop to iterate through the arrays, building a delimited line item for each index of the array.  I assumed a couple of things: 1) that each array was built starting at the top of the email dump file and working toward the bottom (such that, say, index 23 of each array contained values from the same email) and 2) that each email actually had all four fields.  My first assumption appeared to be true, as I spot-checked the results against the raw data and the values seemed to line up; however, it turned out that there were a few emails actually missing the INetFrom field, which threw off all the line items processed after the errant email.  Perhaps I could have written more script to catch such problems, but instead, I just identified the errant emails, added the missing fields in the raw email dump, then ran the script again and all was successful.  The resulting file looked something like this:

email2

Notice the dollar sign at the beginning of the second field.  This is the Abstract field.  In the raw email dump, the Abstract field name is actually “$Abstract:”.  In regular expressions, the dollar sign is a special character and to treat it as a literal, you have to escape it.  In my replace operation, I tried “\$Abstract:  “, “\\\$Abstract:  “, and “\\\\$Abstract:  “, but nothing seemed to work.  Frustrating, but I can live with it.

 

Step 3: Query against my delimited representation of the replies to produce a report of the affirmative replies

With the raw email dump processed into a delimited format, I can now query for the affirmative responses with LogParser.  Here’s the query I came up with:

SELECT
    Field1
FROM delimResponses.txt
WHERE Field2 LIKE '%add me to%' OR Field3 LIKE '%add me to%'

I saved this query in a file called process_email_responses.sql, then, from the command line, executed this:

LogParser file:process_email_responses.sql -i:TSV -iSeparator:"|" -headerRow:OFF -rtp:-1 > AddToList.txt

This query created a list of email addresses that I could just paste into my distribution list (manually, of course, using the Lotus Notes client).  The query yielded about 95% of the affirmative responses; to get the remainder (those that didn’t explicitly include the phrase “add me to your list” in either the body or subject line of the reply), I ran the reverse query and manually reviewed the results:

SELECT
    Field1
FROM delimResponses.txt
WHERE Field2 NOT LIKE '%add me to%' AND Field3 NOT LIKE '%add me to%'

 

Step 4: Add the affirmative emails to my distribution list

As I said, I took the results of my first query (about 95% of the affirmative responses), manually added the remaining affirmative responses from the second query, and then manually pasted the resulting email addresses into the Lotus Notes Edit Group window of my distribution list.bonehead

Over all, this stuff took me a couple of hours to come up with—mainly because I’m a bonehead.  I probably would have spent about the same amount of time processing the list manually—of course, I probably would have made mistakes, too, and ended up adding someone to the list who didn’t want to be added or vice-versa.  At least now that I’ve documented my efforts here, when I send out more solicitation emails in the future (we do anticipate doing this a few more times, at least), I should be able to significantly reduce the processing time of the results. 

The biggest question I have, though, is: is there a smarter way to use Powershell to process a list like my raw email dump?  A list where the fields are listed vertically with some funky character delimiting records?  I couldn’t find examples of anyone processing such files, but I’m glad I found at least one clunky way to do it.  I guess the other question is: did I really need to use LogParser or could I also get Powershell to do my query?  I probably could have gotten Powershell to do my query—with Regular Expressions, no less—but I guess I just felt more confident with LogParser, at least for now.  Anyway, if you have answers or suggestions to these deep and troubling questions of mine, please feel free to comment.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Sunday, June 14, 2009 12:34 PM
Permalink | Comments (5) | Post RSSRSS comment feed

Setting Enums from the Config

This has been one of several nagging curiosities in the back of my mind for quite some time, but until recently, I never had much motivation to explore the question…

Recently, I was given the assignment to deploy some .NET code that would activate an auditing feature with a variety of enumerated flags.  I wanted to make sure I provided enough flexibility in my component such that any combination of the flags could be set from outside the component without the need to recompile the component—the easy answer was to provide a means to set these flags from configuration.

I know I’ve seen other components do this—particularly different logging components—so there ought to be an easy way to set an enumeration from XML, but what is it?  Well, here’s the short-and-dirty solution:

Imagine this kind of configuration file:

<configuration>
  <appSettings>
    <add key="MyEnumSettings" value="OptionOne,OptionTwo"/>
  </appSettings>
</configuration>

Here’s code you can use to parse and convert string representations of an enumerator into the actual enumerator type:

public enum SomeEnumFlag
{
    None,
    OptionOne,
    OptionTwo,
    OptionThree,
    MoreOptions
}

class Program
{
    static void Main(string[] args)
    {
        string enumSettings = ConfigurationManager.AppSettings["MyEnumSettings"];
        string[] settingsArray = enumSettings.Split(new[] { ',' });

        SomeEnumFlag myEnumSettings = new SomeEnumFlag();

        foreach (string setting in settingsArray)
        {
            try
            {
                SomeEnumFlag settingFromConfig =
                    (SomeEnumFlag)Enum.Parse(typeof(SomeEnumFlag), setting.Trim(), true);
                //use the bitwise operator to concatenate enum values together
                myEnumSettings |= settingFromConfig;
            }
            catch (ArgumentException ex)
            {
                //if my config feeds a bad enum value, ArgumentException will be thrown
            }
        }

        if (myEnumSettings == SomeEnumFlag.None)
        {
            //my enum defaults to None and will remain so if no values were
            //found in the config
        } 
    }
}

 

Side note: my real-life problem dealt with a SharePoint enumerator, but, since I have yet to set up a SharePoint development environment at home, I decided to create my own enumerator for this example.  The concept is still the same, though.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Sunday, March 15, 2009 8:51 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Unit Testing in ASP.NET

I’m all for unit testing and even Test Driven Development (although I can do without some of the TDD zealotry out there).  Recently, I began writing some libraries for ASP.NET applications and really struggled with how I was going to write my unit tests to test my work.  Certainly, we have the MVP and MVC patterns and lots of great examples, frameworks, and miscellaneous tools to help you implement these patterns and greatly simplify the unit tests you need to write—but I’m writing an ASP.NET-based library, not an end-to-end application.

Here’s what I’m doing:

I have to write components around a commercial security device that injects certain identity information into the request header of http requests (via an ISAPI filter).  Specifically, I am writing an HttpModule (a few, actually, for different scenarios) to build out a custom Identity object and insert it into the Current.User object.  Additionally, I’m writing a couple of RoleProviders to manage the roles returned by the device.

These components obviously have a tight reliance on HttpContext, so how do you unit test under such a scenario?  Incidentally, these components have to work with a pure ASP.NET 2.0 solution, which means I don’t have access to the new System.Web.Abstractions assembly which is supposed to make testing in this space much easier—I’d still like to see what the Abstractions assembly could do for me, though.

Phil Haack offered up this effort at mocking HttpContext, but I simply couldn’t get that to work for my scenario.  I then looked at TypeMock.  Here’s some code I wrote against TypeMock that still doesn’t work:

[Test]
[VerifyMocks]
public void TestOnAuthenticateRequest2()
{
string fname = "John";
string lname = "Smith";
string fullName = fname + " " + lname;
string roles = "cn=Role1,ou=APPS,o=SomeCompany:cn=Role2,ou=APPS,o=SomeCompany";
string login = "jxsmith";
string commonName = "Smith";
//TestedImplementation is an alias for my custom HttpModule
TestedImplementation target = new TestedImplementation();
MockObject<HttpApplication> applicationMock = MockManager.MockObject<HttpApplication>();
MockedEvent authRequestEvent = applicationMock.ExpectAddEvent("AuthenticateRequest");
target.Init(applicationMock.Object);
MockObject<HttpRequest> httpRequestMock = MockManager.MockObject<HttpRequest>();
applicationMock.ExpectGetAlways("Request", httpRequestMock.Object);
MockObject<HttpResponse> httpResponseMock = MockManager.MockObject<HttpResponse>();
applicationMock.ExpectGetAlways("Response", httpResponseMock.Object);
httpRequestMock.ExpectGetAlways("HttpMethod", "POST");
httpRequestMock.ExpectGetAlways("AppRelativeCurrentExecutionFilePath", "foobar.aspx");
httpRequestMock.Object.Headers.Add("LOGIN", login);
httpRequestMock.Object.Headers.Add("FIRSTNAME", fname);
httpRequestMock.Object.Headers.Add("LASTNAME", lname);
httpRequestMock.Object.Headers.Add("ROLE", roles);
httpRequestMock.Object.Headers.Add("COMMONNAME", commonName);
authRequestEvent.Fire(applicationMock.Object, EventArgs.Empty);
//once I can actually mock the context, I'll write some asserts
}

As I recall, I could never figure out how to stub in data to the request header of the mocked request.  Doing this is pretty important as my components behave differently based on the data present (or not present) in the header.  A sister project to TypeMock called Ivonna (no pun intended) actually might let me do this, though.  Of course, both these products cost money—so, I’d still like to find a free answer to my problem.

Some folks have suggested refactoring my IHttpModule and RoleProvider implementations such that I move as much code as possible out of the direct implementations and into separate classes that can be more easily tested.  I assume they mean separate private classes that aren’t exposed to clients using my components.  To that end, here’s what I tried in my implementation:

public class MyHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.AuthenticateRequest += OnAuthenticateRequest;
}
private void OnAuthenticateRequest(object sender, EventArgs e)
{
HttpApplication httpApp = sender as HttpApplication;
MyHttpModuleHelper helper = new MyHttpModuleHelper();
helper.DoStuff(httpApp.Request.Headers);
}
public void Dispose()
{
//dispose stuff here
}
}
//the private class that can be tested
class MyHttpModuleHelper
{
public string[] DoStuff(NameValueCollection headers)
{
//process the headers in some way
return new[]{"hello world"};
}
}

And in my unit test class:

private MethodInfo DoStuffMethod;
private object MyHttpModuleHelper;
[SetUp]
public void Init()
{
Assembly testAssembly = Assembly.GetAssembly(typeof (MyHttpModule));
MyHttpModuleHelper =
testAssembly.CreateInstance("MyNamespace.HttpModules.MyHttpModuleHelper");
Type helperType = MyHttpModuleHelper.GetType();
BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
DoStuffMethod = helperType.GetMethod("DoStuff", bf);
}
[Test]
public void DoStuffTest()
{
NameValueCollection stubHeaders = new NameValueCollection();
//stubHeaders.Add();  //add some fake data
object returnValue = DoStuffMethod.Invoke(MyHttpModuleHelper, new object[] { stubHeaders });
Assert.IsTrue(returnValue.GetType().IsArray, "Expected the type to be a string array");
string[] roleArray = returnValue as string[];
Assert.IsTrue(roleArray.Length == 1, "Expected the array length to be 1");
StringAssert.IsMatch(roleArray[0], "hello world", "Expected the first value to be hello world");
}

This works, but it’s such a pain.  One frustration I’ve had is that I tend to refactor my helper methods a lot—the parameters I pass, the return values I return, even the names of the methods themselves.  Every time I refactor, I have to go back to my unit tests and refactor them accordingly—even Resharper isn’t smart enough to cascade through such refactoring when I’m using Reflection to invoke those methods.  Do I have any other options?

Virtually at the end of my rope, I even contemplated the mildly insane notion of writing a test ASP.NET app to Response.Write out values from my Identity and Principal objects rendered by my HttpModules and RoleProviders…then use a product like Selenium or WatiN to perform assertions on those values in the pages.

Just when I thought all hope was lost, a friend of mine reminded me of the ASP.NET host adapter.  The ASP.NET host adapter allows you to run a unit test that smells a lot more like an integration test—like integration testing, you have to develop a web app within which your test will run.  The big difference, though, is that you can perform assertions on server-side objects. 

You invoke the ASP.NET host adapter by decorating your MSTTest test method with the attribute, [HostType(“ASP.NET”)].  You also have to include the attribute [UrlToTest(“someUrl”)]—where you specify the ASPX page that establishes the server-side context you’d like to test.  You can add one more attribute, AspNetDevelopmentServerHost, to have you test web app run under the Development Server (a.k.a. Cassini) as opposed to IIS.

It’s lame that I need a web app to run a unit test, but I’m desperate, so I’ll play along.  As I started all this work, one obstacle I kept running into was the UrlToTest attribute: it seemed to only understand the “localhost” domain name.  As I mentioned earlier, I’m writing components that have to play nicely under this third party ISAPI filter.  The ISAPI filter will only be invoked when it detects certain domain names it’s configured to listen for.  Localhost is not one of these—if it were, every time anyone would run an app under localhost, the ISAPI filter would invoke a particular set of policies that may or may not have anything to do with your work—frankly, it would just be bad.

Instead, in Development, until we can get a real IP assigned to our app, we create fictitious domain names by mapping 127.0.0.1 to that fictitious name in our local hosts file.  We configure the ISAPI filter to apply our particular policy when it detects this fictitious host name being requested and all is right in the world.  That is, until you try to invoke the ASP.NET host adapter using your fictitious domain name: it seems that the ASP.NET host adapter could care less about what mappings I have in my hosts file.  I even tried my own IP address and it didn’t like that, either.  Finally, I tried my machine name and, ta-da, the ASP.NET host adapter worked and my test ran.  It just so happens that I can use my machine name as one of these fictitious domain names, but I consider that bad form—it tightly associates my machine to the development environment.  Now, even my tests are tightly associated to my machine.  That really stinks—so much for running my tests on a separate build server…they just won’t work.

Here’s an example of one of my test methods:

[TestMethod]
[HostType("ASP.NET")]
[UrlToTest("http://MyMachineName/SomeVirDir/Default.aspx")]
public void IdentityType()
{
Assert.IsNotNull(HttpContext.Current.User, "Current.User object is null");
Assert.IsNotNull(HttpContext.Current.User.Identity, "Current.User.Identity object is null");
Assert.IsInstanceOfType(HttpContext.Current.User.Identity, typeof(MyCustomIdentity),
"Current identity is not of type MyCustomIdentity");
}

Another thing I noted regarding the UrlToTest attribute is that it only likes my “short” machine name—I had to truncate off my DNS suffix in order to get my test to run properly.

So, this is a terrible way to test—my tests are tightly bound to my machine and require a web app of all things to run a simple unit test—but, at least it works on my machine.  The alternatives would be scraping together a few hundred bucks to buy TypeMock/Ivonna (which would come out of my pocket, not my company’s—see here on why that’s the case) or upgrade to .NET 3.5 SP1 with hopes that the new Abstractions assembly can help me out.

For the moment, I’ll stick with this approach.  My next challenge is to figure out how to dynamically change my web configuration between tests to swap out HttpModules and RoleProviders, as I need to test a few of these.  Any ideas?

Currently rated 2.5 by 4 people

  • Currently 2.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Brad on Saturday, February 21, 2009 7:14 PM
Permalink | Comments (7) | Post RSSRSS comment feed

Thinking about Logging

I think about logging pretty often as I code solutions.  To me, logging is an important part of a quality software product.  In the middle of the night, when your software goes haywire, being able to explore a well-detailed application log file (not just the event logs or IIS logs, for example) can be critical in remediating the problem and reducing the number of lost hours of sleep.

I think a good logging solution should include:

  1. The ability to be turned off or on from outside the compiled solution (eg. from the configuration file).
  2. Persistence ignorance—maybe today I want to log to a flat file, but tomorrow I want to log to a database.  I should be able to easily swap persistence providers without recompilation.  With regard to flat file logging, I’d like the option to be able to specify a relative path or absolute path for the log file (although, for web apps, that could serve as a security vulnerability).  Also, a rolling log file provider is a must.
  3. The ability to crank up or crank down the verbosity of the logging solution. 
  4. Some control over the look of the log file.  Although I might, on occasion, crack open a log file in notepad and manually walk through it, most log files I deal with are quite large—I’d rather use tools like LogParser to produce human-readable reports from the generally-not-human-readable log file.  By having some control over the data that’s added to my log files and how that data is delimited, it can be easier for me to write scripts that render powerful reports (some day, I do hope to put up a post on how I’ve used LogParser to produce meaningful reports based on my application logs).

I could also add to the list that the solution must be hidden behind an interface for easy injection via Dependency Injection.  The easy winner here, in my opinion, is log4net.  If you’re not familiar with log4net, it is a light, open-source API that meets all of these needs and more.  Here are my quick notes on implementing the library:

Step 1: Configure it

…in your application configuration file

<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<!-- A1 is set to be a ConsoleAppender -->
<appender name="A1" type="log4net.Appender.RollingFileAppender">
<file value="logs\log4net.log"/>
<appendToFile value="true"/>
<datePattern value="yyyyMMdd"/>
<rollingStyle value="Date"/>
<!-- A1 uses PatternLayout -->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-4timestamp|%thread|%-5level|%logger|%ndc|%message%newline"/>
</layout>
</appender>
<!-- Set root logger level to DEBUG and its only appender to A1 -->
<root>
<level value="ALL"/>
<appender-ref ref="A1"/>
</root>
</log4net>

…and in your AssemblyInfo.cs file

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

Step 2: Add a reference to log4net.dll

Step 3: Code Away

using System;
using System.Reflection;
using log4net;
namespace WebApplication1
{
public partial class log4net : System.Web.UI.Page
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected void logButton_Click(object sender, EventArgs e)
{
log.Debug("some Debug msg");
log.Error("some Error msg");
log.Fatal("some Fatal msg");
log.Info("some Info msg");
log.Warn("some Warn msg");
}
}
}

 

So, log4net’s great for your everyday application needs, but I have a new requirement: most of what I do anymore is write libraries and frameworks for others to use.  I want to litter my APIs with lots of log messages so that, should a developer want to know what my API is doing, he should just be able to flip a configuration switch and get a log of the activities of my API.  It seems a little presumptuous of me to introduce yet one more dependency on my customer—the log4net dependency—just to be able to use my API.  In this situation, I’d prefer to be able to leverage any kind of logging opportunities in the base class library itself.  The System.Diagnostics namespace gives me some of this opportunity, but none of the native options are as rich or powerful as log4net.

System.Diagnostics.TraceSource

I find the newer System.Diagnostics.TraceSource not even a viable option for me.  TraceSource seems nothing more than the older System.Diagnostics.Trace with less options (eg. no throttling).  So, let’s skip TraceSource and talk about Trace.

 

System.Diagnostics.Trace

It used to be that I would configure a TraceListener like this:

    <system.diagnostics>
<switches>
<add name="MagicTraceSwitch" value="Verbose"/>
</switches>
        <trace autoflush="true" indentsize="4">
<listeners>
<clear/>
<add name="fileListener" 
type="System.Diagnostics.TextWriterTraceListener" 
initializeData="logs\SysDiag.log" 
traceOutputOptions="DateTime"/>
            </listeners>
</trace>
    </system.diagnostics>

Then I’d start coding against the namespace as such:

public partial class _Default : System.Web.UI.Page
{
private TraceSwitch MyTraceSwitch = new TraceSwitch("MagicTraceSwitch", "switch from config file");
protected void Button1_Click(object sender, EventArgs e)
{
Trace.WriteLineIf(MyTraceSwitch.TraceInfo, "log some informational message.");
Trace.WriteLineIf(MyTraceSwitch.TraceVerbose, "log some verbose message.");
}
}

Since System.Diagnostics is part of the BCL, no extra dependencies are required and I can ship just my APIs with no other third party assemblies.  I have at least two problems with this approach, though: 1) the TextWriterTraceListener has no rolling log file capabilities and 2) the way I’m pushing messages out to the listener, via the Trace.WriteLineIf statement, means that only the exact string message in my argument gets inserted into my log—no nicely delimited line with timestamp, thread id, etc.

To address my second problem, I could use a different set of methods in the Trace class:

Trace.TraceError("an error happened.");
Trace.TraceInformation("this is an information trace {0} {1}", "parm1", "parm2");
Trace.TraceWarning("this is a warning trace {0} {1}", "parm1", "parm2");

Interestingly, though, these methods don’t throttle—they pay no attention to my TraceSwitch setting.  All these messages will get logged regardless of the verbosity setting.  The log entries will, however, include the values “Error”, “Warning”, and “Information” if that’s any consolation.  To format the log entry, the listener configuration includes a “Delimiter” attribute and a traceOutputOptions attribute.

To address the first problem, I’ve recently discovered the Microsoft.VisualBasic.Logging.FileLogTraceListener, thanks to this post on StackOverflow.  Here’s a configuration I’ve used for this listener:

    <system.diagnostics>
<switches>
<add name="MagicTraceSwitch" value="Warning"/>
</switches>
        <trace autoflush="true" indentsize="4">
<listeners>
<clear/>
<!--<add name="fileListener" 
type="System.Diagnostics.TextWriterTraceListener" 
initializeData="logs\SysDiag.log" 
traceOutputOptions="DateTime"/>-->
<add 
name="fileListener2" 
type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" 
CustomLocation="C:\data_files\app_development\LoggingTest\WebApplication1\logs"  
Location="Custom" 
BaseFileName="MyApp" 
LogFileCreationSchedule="Daily" 
Delimiter="|" 
traceOutputOptions="ProcessId, DateTime"/>
</listeners>
</trace>
    </system.diagnostics>

One thing to note about this listener is that, unlike the TextWriterTraceListener, the FileLogTraceListener seems to only accept an absolute file path, not a relative one—if you can deal with that, this listener seems to be a viable option—although if I were writing an end-to-end application, not just a framework, I’d definitely go with log4net for my logging solution.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Technology Blog
Posted by Brad on Saturday, February 21, 2009 3:15 PM
Permalink | Comments (1) | Post RSSRSS comment feed

CodeMash 2009: Day 2

Key Note Speaker: Eric Meyer

Eric Meyer headlined the morning keynote for CodeMash 2009, day 2.  I think the title of his talk was something like, “How Javascript will Save the World.”  He talked about innovations using Javascript to play flash movies and to standardize fonts on the web and he talked about how Microsoft browsers tend to screw up the standardization effort.  He also mentioned other cool Javascript efforts like Nifty Corners and Bluff.  A problem he sees in this space, though, is that all these efforts invariably produce new Javascript libraries: why not have these libraries parse and process CSS instead?

Like the other keynoters, Eric was quite entertaining and obviously a thought leader in web UI.  I must confess that I am far out-of-the-loop on such things.  He briefly covered microformats mentioning some Yahoo group that seems to be involved in the movement.  Finally, my notes mention ObjectiveJ, 280slides.com, and Capuccino.  I suppose these are more innovative web UI platforms.  Moving on…

 

Session: IronRuby In The Real World

Michael Letterle led the talk on IronRuby in the real world; however, based on his presentation, I don’t see how it could be ready for the real world—or at least the real business world.  His demo began with a C# desktop application.  We were to pretend that the original developer left and no source code could be found (and, I guess, .NET Reflector didn’t exist either…or maybe the code was just obfuscated).  At any rate, Michael showed how you could just overlay the desktop app with an IronRuby executable to change the behavior of the desktop app and implement new business requirements.  That is pretty cool, but I just don’t see how that would be a practical approach to solving the business problem. 

Some online resources for IronRuby include Jimmy Schementi’s blog, the grand wizard himself John Lam, and Ruby itself.

 

Session: Language Oriented DDD

It seems that everywhere I turn, someone is talking about Domain Driven Design (DDD).  I guess, much like Eric Meyer’s Javascript, DDD will save the universe.  David Laribee led the only talk with DDD in the title, so I thought I’d better attend.

David kicked things off with a reference to the book The Design of Everyday Things—a book that points out examples of good and not-so-good constructions.  Later on, he launched into a discussion of various patterns:

  • Layered Architecture; eg. MVC
  • Application Services, which should not be “transactional” (as in database transaction?), vs. Domain Services, which should be small and focused
  • Model Controller; eg. that which connects a model to a queue
  • Published Language
  • Aggregate Root
  • Routing Method
  • The Repository
  • Collocated Specifications, used for entity matching requirements
  • Anti-Corruption Layer – the use of explicit interfaces

He also enumerated a few anti-patterns:

  • Anemic Model
  • Ambiguous Command – opposing the use of explicit interfaces
  • Reflective Mappers

I’m sure DDD is much more than several five dollar words, but I’ll let you know for sure when I’m done reading the book.

 

Session: A Programmers Guide to User Experience

My UI skills stink.  I know this.  However, I am desperate to eliminate my UI handicaps.  If any of you know of a good class, book, webcast, or some other medium that could help me in this effort, please let me know.  So, in my continuing quest to become a better UI guy, I attended Josh Walsh’s presentation. 

Josh is a professional UI designer-type guy for Design Interactive.  He walked through how he meets with clients to develop user interfaces that meet their needs.  For one thing, he conducts interviews: what does the project mean to you, Mr. Customer?  He defines scenarios and processes.  He builds a specification document of these scenarios and he writes out tasks and groups them accordingly.  He does a lot of hand sketching, too, on graph paper (with a Sharpie).

Next, he performs some tests with the users—without even writing code yet.  He’ll walk his documents (and sketches) in to the client and use them as they walk through different scenarios.

That’s all well and good, but can you give me any nuggets of advice that I can use immediately?

  • Use standard HTML controls…hmm.  Don’t ASP.NET and third party controls ultimately render to HTML controls, anyway?
  • Use Arial or Helvetica for body text.  These fonts are known as sans serif fonts.
  • Use Georgia for header text.  Georgia is known as a serif font.  What?  No Comic Sans?
  • Josh recommends a dark grey as a good back color.
  • Line height should be 1.5em.
  • A page should have space on either side and the middle part (with the content) should be only 40-60 characters wide.  There goes my idea of using as much real estate as possible.
  • Try blurring the page to see where your eyes focus.  This can help you determine the focal point of the page.

Books Josh would recommend: Don’t Make Me Think, Getting Real (a free ebook from 37signals.com), and, possibly, Prioritizing Web Usability

 

Session: Reverse Engineering Applications

My original plan was to attend Drew Robbins’ Modern Web Applications with .NET presentation, but Drew was sick in bed (or maybe he just stayed out a little too late the night before at the CodeMash after-hours party…hmm).  So, I went to Joe Kuemerle’s Reverse Engineering session.  The notion of reverse engineering software to see its source code is not new to me, but Joe did tackle the topic in a pretty comprehensive manner.

Popular reverse engineering tools include:

The primary way to combat disassembly of your compiled code is to obfuscate your code—Joe, as an employee of PreEmptive solutions, certainly knows this!  [Although, to his credit, Joe in no way pimped Dotfuscator.  Someone in the audience asked how you combat such reverse engineering tactics and it was only then that Joe mentioned part of what his company does.  He even went so far as to mention the Phoenix Project—a free obfuscator for .NET.  I wonder if he really meant the Babel obfuscator, built on Microsoft’s new Phoenix framework?]

Joe mentioned strong name signing of your assemblies, not to combat reverse engineering per se, but to at least offer some form of integrity or validation.  The last thing Joe mentioned was authenticode signing of .NET binaries.  I had never heard of this technique before until several months ago when someone in my company told me about problems he was having with Enterprise Library.  He was running a web app using Enterprise Library (version 4.0, I believe) on an internal web server.  The first time his app made a call to EntLib, EntLib would try to call out to Microsoft.com.  My company’s firewall rightfully blocked the call, but the process would sit for about 10 seconds until timing out and continuing with the rest of the operation.  The developer determined that this was due to the fact that EntLib was authenticode signed and was trying to do some validation of the certificate.  Don’t know how the story turned out—hopefully he found that hotfix—but this authenticode business sounds dicey…and kind of expensive.

 

Wrap Up

Well, that’s another CodeMash.  For the price and locale, you can’t really beat it.  Conferences are always a double-edged sword to me: they’re a great way to learn about new and existing technologies/methodologies and an opportunity to ask questions of the experts that normally would be tough to do otherwise.  However, they also tend to depress me more than usual.  I go away thinking that I’ve fallen so behind in knowledge and experience—I’m barely cognizant of DDD, barely practicing TDD…not to mention Agile, WPF, SilverLight 2.0, Ruby, blah, blah, blah.  Either most of these people are exaggerating their experiences, have no life and code all the time, or have great jobs that let them gain deep experience in lots of technologies and methodologies.

Well, I’m going to stop whining and do something this year to keep up.  Not sure what, but something.  Maybe I should put up one of those trite New Year’s Resolution posts.  Hmm.  Gotta think about that one. 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Categories: Technology Blog
Posted by Brad on Saturday, January 24, 2009 11:28 PM
Permalink | Comments (0) | Post RSSRSS comment feed