Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Architecture, Design & Strategy

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « Scalability is Easy! (To Get Wrong)Adding User Emulation to an Application »
    comments

    At my last job we had a non-functional attribute that another team used to decorate service methods that they consumed. The other team was working on an alternative client to our WCF services, and they weren't on the same release schedule they needed to be able to target multiple versions of our services within a single version of their application. Because of this requirement, they maintained a wrapper around our services that handled some of the differences between versions. The main use for this attribute was to foster communication between the teams, so that if we changed a decorated method we would let them know. As I'm sure anyone on this other team would tell you, we weren't always that good about communicating these changes.

    In an effort to make communication between teams easier we used a CQL query like this to report changes to these methods as part of our automated builds:

    1. SELECT METHODS FROM NAMESPACES "Services"
    2. WHERE HasAttribute "OPTIONAL:Services.KnownExternalClientsAttribute"
    3. AND CodeWasChanged

    This was nice, but it only got us part of the way there. This would alert us to signature changes or changes to the content of the method, but not necessarily changes to the message contracts passed in to the method. In Pseudo-CQL the query I had in mind looks something like this:

    1. SELECT TYPES FROM NAMESPACES "Services"
    2. WHERE CodeWasChanged
    3. AND IsUsedBy (
    4.     SELECT METHODS FROM NAMESPACES "Services"
    5.     WHERE HasAttribute "OPTIONAL:Services.KnownExternalClientsAttribute"
    6. )

    This didn't work however (CQL doesn't really have support for subqueries), and I couldn't really find anything in the language that would allow us to achieve what we wanted. NDepend 4 introduces a new linq-based replacement called CQLinq that offers a lot more flexibility, so I figured I would see if I could write the query that we needed using it. It ended up being much easier than I thought - CQLinq gives us access to most (if not all) of the standard LINQ operators, and the same functions for querying code using attributes and history that we had with CQL. This is the query I came up with:

    1. // <Name>Test Query for Contract Changes</Name>
    2. warnif count > 0
    3.  
    4. let decoratedMethods = from m in JustMyCode.Methods
    5.     where m.HasAttribute("NDependSample.TestAttribute")
    6.         && m.ParentNamespace.Name == "NDependSample.Services"
    7.     select m
    8.  
    9. from t in JustMyCode.Types
    10. where  t.ParentNamespace.Name == "NDependSample.Contracts"
    11.   && t.CodeWasChanged()
    12.   && decoratedMethods.Using(t).Any()
    13. select t

    Once we have the query we can mark it as critical, so we will have a failing build after the changes are made. Only the first build after making the changes should fail, but that would be enough to trigger an investigation that would result in communicating the changes to the other team.

    CQL has always been my favorite feature of NDepend, so its no surprise that CQLinq is my favorite feature in this new release. The LINQ based syntax feels much more natural to me when writing queries against a codebase than the SQL-like syntax of CQL, and still gives us all the same visualization goodies to foster quick understanding of the query results. I'm really excited to dig in a little more and see what else I can do with it.

    About the Author

    User bio imageAlex is a .net and SQL Server developer from southeastern PA, where he lives with a lovely wife and a veritable smorgasbord of pets. He recently completed a masters degree in Software Engineering from Penn State. He loves mountain biking, open source software, home brewing, Syracuse basketball, and the mono runtime.
    Social SitingsTwitterLinkedInHomePageLTD RSS Feed
    2707 views
    InstapaperVote on HN

    2 comments

    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) How much of an impact did running NDepend have on your overall build time? I've played with it in the past, but only as manual runs.
    06/06/12 @ 08:36
    Comment from: Alex Ullrich [Member] Email
    Alex Ullrich I can't say it was trivial (though our full build was pretty involved, took ~25 minutes if we were generating an MSI) but it was *much* faster than the visual studio architecture analysis (and provided much more information). We used a separate build configuration for architecture validation that ran around 2am, mostly because we first tried using the tremendously slow visual studio tool and didn't want each build taking 45 minutes.

    The codebase in question was probably between half and three-quarters of a million lines split into 30+ projects. I never saw an ad-hoc analysis take more than 2-2 1/2 minutes and this was running on our spare machines that were *very* underpowered. I would expect it ran much faster than that on our build server, and that NDepend 4 would be at least incrementally faster than 3.
    06/06/12 @ 09:03

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)