Sponsors

The Lounge

Current Bloggers

HandleUnknownAction in ASP.NET MVC – Be Careful

Posted by David Hayden, Thursday, July 02, 2009 (226 views)

One of my team members was showing me some code in HandleUnknownAction based upon sample code in the online documentation. Per the documentation:

 

“The following example shows how to render views that do not have a matching ActionResult method. For example, if you have a Details.aspx view but no corresponding method exists that returns an ActionResult instance, the following example displays the Details view when a request to for the Details action is made on the controller. If there is no matching view, the error page displays a message.”

 

protected override void HandleUnknownAction(string actionName)

{

    try

    {

        View(actionName).ExecuteResult(ControllerContext);

    }

    catch (InvalidOperationException ieox)

    {

        ViewData["error"] = "Unknown Action: \"" +

            Server.HtmlEncode(actionName) + "\"";

        ViewData["exMessage"] = ieox.Message;

        this.View("Error").ExecuteResult(this.ControllerContext);

    }

}

 

The only problem with this example is that it does not take into account attributes, like the ActionMethodSelectorAttribute, that can decide based on runtime information whether an action can fulfill a request. So, it may not be that the action does not exist, but that it is not supposed to respond to the request based on the context of the request.

For example, if I use the AcceptVerbsAttribute, an example of ActionMethodSelectorAttribute, to do something as simple as this on my HomeController:

 

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult DisplayOnlyViaPost()

{

    return View();

}

 

The DisplayOnlyViaPost View will not be displayed via the DisplayOnlyViaPost Action when someone types the URL in a browser ( HTTP GET Request ) – http://…/Home/DisplayOnlyViaPost.

Unfortunately, the HandleUnknownAction code above will kick in and notice that indeed the DisplayOnlyViaPost View does exist. Therefore it goes ahead and displays the view, undermining the use of our AcceptVerbsAttribute on the original action. Not good :)

Just something I noticed that you may want to be careful of if you are using similar code in HandleUnknownAction.

 

David Hayden

 

Discuss (0)

ASP.NET MVC Extensibility at Tampa MVC Developer Group

Posted by David Hayden, Wednesday, July 01, 2009 (397 views)

The Tampa ASP.NET MVC Developer Group is starting to kick it up a notch with this month’s meeting being about ASP.NET MVC Extensibility. We have concluded our introductory topics and are now focusing on more intermediate topics. This month’s meeting will hit more advanced topics, such as:

  • Creating Custom Controller Factories for Dependency Injection
  • Using Custom View Engines
  • Creating Custom ActionFilters for DataBinding, Validation, etc.
  • Using Custom ControllerActionInvokers
  • Developing Custom ActionResults for RSS Feeds, etc.
  • Building HtmlHelpers for Productivity

 

If you are interested in building your own opinionated version of the ASP.NET MVC Framework and have it bend to your will, you don’t want to miss this meeting.

In addition, we will also be going over last month’s homework assignment, which was to use the ASP.NET MVC AjaxHelpers to “ajaxify” an ASP.NET MVC Web Application. As a hint, you can find an answer in our last screencast, ASP.NET MVC Ajax Helpers - Ajax.ActionLink and Ajax.BeginForm – Screencast :)

Those completing the homework assignment will be included in a random drawing of Steven Sanderson’s Awesome book, Pro ASP.NET MVC Framework. Absolutely love Steve’s book. Huge thanks to Apress for sending us several copies to give away to our members.

Starting in August we will be working on voluntary group projects to strengthen our team development skills using ASP.NET MVC. Again, huge thanks to two of our sponsors for making this happen: Server Intellect and Unfuddle.

 

See you on Thursday, July 9 at the Microsoft Office in Tampa!

 

David Hayden

Discuss (0)

The Videos for NDC 2009 are online

Posted by Jeremy D. Miller, Wednesday, July 01, 2009 (732 views)

The links to the videos recorded for NDC 2009 talks are online and linked in the agenda pages here.  My talks are at:

Discuss (6)

Reporting against a domain model

Posted by pvanooijen, Wednesday, July 01, 2009 (1,065 views)

I have a love it /hate it relationship with reports. In many an application the reports are the main output. They are the prints which get filed or the invoices which have to ensure the ROI of the application. A good looking output rich with information does increase customer satisfaction. The downside is that fine tuning a report is tedious and requires quite different skills than coding. Building a system with a lot of reports can be pretty boring. So the tools better be good. Switching from Crystal Reports to sql server  reporting services (RS) was quite a relief.

But  RS still has two drawbacks. First is that it accesses data using plain sql. My application is built around a domain model using nHibernate to hide all db details. The domain model includes calculated properties which are to be included in the report. The calculations are done in the domain object. It would be repetitive and prone to error to repeat them in sql or reporting expressions. It would be quite a relief to report straight from the domain model itself.

The other drawback is that RS requires an ms sql server instance with installed reporting services. The actual data is just a sqlexpress instance and I don’t want to set up a full blown reporting services server.

New in Visual Studio 2005 were client side reports (rdlc’s). They are very much like RS reports (rdl’s) but can work with any data source and don’t require a sql reporting server instance. To include these reports in an app two client side report viewers are include in the .NET framework, one for WinForms and one for asp.net. This looked like the best of both worlds so I decided to give the winforms version a try.

For a good overview on the reports check the got reportviewer site. In name it supports VS 2008, but (some of ?) the samples are based on VS 2005. Moving to 2008 there has been a change in the namespace for the classes, after fixing the reference the samples run in VS 2008. How to work with a non sql datasource is covered but not that clear. Here I will describe my minimalistic approach to work with a domain model fed by nHibernate.

The domain model

The intent of the application is to print invoices. This class diagram describes the model

Rep1

 

An invoice is for a contact, has a number of lines and an enumerated property. That is a number of values which contain a tax rate and have a clear name describing this value. Which gives the model additional value, something which would get lost when viewing the data as raw db data. An invoice has a reference to a contact and many Invoice lines. The (fluent) nHibernate mappings express this.

public class InvoiceMap : ClassMap<Invoice>

{

    public InvoiceMap()

    {

        WithTable("Factuur");

        Id(x => x.Id);

        Map(x => x.Number).ColumnName("Nummer");

        Map(x => x.OnDate).ColumnName("Dedato");

        Map(x => x.BtwPercentage).CustomTypeIs<BtwPercentage>();

        Map(x => x.Description).ColumnName("Inleiding");

        HasMany(x => x.Lines).KeyColumnNames.Add("idFactuur").Cascade.All();

        References(x => x.ForContact).ColumnName("idRelatie");

        Map(x => x.PrintIt).ColumnName("Printen");

    }

}

So we have a customtype, a hasmany and a references. Let’s see how these are used in the report.

The report

There are several ways to include a report in an application. The default when adding  a new report (Add –> New Item –> Reporting –> report) is embedded. Which is clear and easy in deployment. When you need more flexibility you can switch to rdlc file or (back to) server side report.

The report needs a datasource. It will accept any datasource including an object datasource.

Add a new object datasource to the project and pick the Invoice domain object.

Rep2

Just pick your POCO domain class. There is no need to set up any methods to get data, it is enough to have a model of the data.

This object data source is the datasource for your report. Having done so the domain invoice is available in the report designer. (To be precise the datasource has to be attached to a List, see the reportviewer docs for more information on that.)

 

Rep3

 

A report is built from VB-like expressions. A simple one looks  like this:

=Fields!Description.Value

Which displays the plain content of a property. But expressions can be more complicated. The report designer has a good expression builder which even includes intellisense. The next expression uses both the meaningful name and the value of my tax enumeration property in a string

="BTW " & Fields!BtwPercentage.Value.ToString & " "  & Fields!BtwPercentage.Value & "%"

The result is a string like “BTW Hoog 19%”.

Things get really interesting when displaying the contact information. In the domain model this expressed as

invoice.ForContact.AddressLine1

In the report the expression is quite similar

=Fields!ForContact.Value.AddressLine1

The subreport

The lines in the invoice are a one to many relation. The invoice datasource has a lines property but this property is not usable in the report. To display the lines I need a subreport. The subreport is based on invoice lines. After adding the InvoiceLine class as a datasource the subreport is drawn. It is a simple table displaying the lines.

A subreport is linked to its parent report using parameters. In my case an invoice and its lines are linked through a parameter named FactuurNummer.

Rep4

All of this works just as in “traditional” reports. In the main invoice report this parameter is assigned the value of the invoice number

Rep5

Check the gotreportviewer site for further information.

 

 

Binding the data to the report

Now the reports are ready. The next step is to get some real life data into them.

It takes code to bind real data to a report and display the result in the viewer. Also the subreport has to be fed with data. To wrap things up I have built a helper class which takes a reportviewer component and a list of invoices and wires them up.

internal class InvoiceReporter

{

    internal InvoiceReporter(ReportViewer viewer, IList<Invoice> reportData)

    {

        _reportData = reportData;

        _viewer = viewer;

    }

 

    private readonly IList<Invoice> _reportData;

    private readonly ReportViewer _viewer;

 

    internal void ShowReport()

    {

        _viewer.LocalReport.ReportEmbeddedResource = "Gekko.Administratie.FactuurPrinten.Invoice.rdlc";

        _viewer.LocalReport.DataSources.Add(new ReportDataSource("Gekko_Administratie_DomainModel_Invoice", _reportData));

        _viewer.LocalReport.SubreportProcessing += SubreportProcessing;

        _viewer.RefreshReport();

    }

 

    private void SubreportProcessing(object sender, SubreportProcessingEventArgs e)

    {

        var invoiceNumber = e.Parameters["FactuurNummer"].Values[0];

        var invoice = _reportData.First(fakt => fakt.Number == invoiceNumber);

        e.DataSources.Add(new ReportDataSource("Gekko_Administratie_DomainModel_InvoiceLine", invoice.Lines));

    }

}

The code requires some explanation. The constructor should be clear, it receives viewer and data.

The ShowReport method does the real work. The first line loads the report in the viewer. The second line loads the report data. This line is tricky. The name of the ReportDataSource has to match exactly the name of the datasource class used as model. The Invoice class name is Gekko.Administratie.DomainModel.Invoice which gets formatted as Gekko_Administratie_DomainModel_Invoice. This required magic string is not clear from any documentation, it took me quite some time to find out how essential it was.

All these datasource properties in the report definition are confusing. The model of the data is saved in the report definition. Changing the datasource  to another “dataset” will also lead to errors at run time. The report will complain about the former datasources. To get rid of the error messages you have to check the report defintion by hand. The report definition file (.rdlc) is plain xml. The last part contains dataset definitions. What helps is just deleting the unused nodes by hand.

Upon rendering a subreport an event is fired. In the third line of ShowReport a handler is attached. This SubReportProcessing method feeds the subreport with data. From the parameters the number of the invoice is read. Which is used to find the corresponding invoice. The datasource for the subreport is set just like the datasource of the main report. Again spelling the name of the reportdatasource right is essential. The data is the Lines property. Which is an IList of InvoiceLines.

Putting it all together

With all pieces in place it’s time to get some results. I have a windows form with a reportviewer on it.

var repo = new InvoiceRepository();

var reporter = new InvoiceReporter(reportViewer1, repo.ListPrintableInvoices());

reporter.ShowReport();

This reads the invoices from the repository and sends them with the reportviewer to the helper class.

There is one more thing to watch. The repository is an nHibernate repository. By default nHibernate lazy loads related objects, like the Contact and the Lines of the Invoice. The contact and the invoicelines will not be read from the database until they are actually used. This default setting has some serious drawbacks.

In the first place the reportviewer‘s datareader does not operate very well (at all ?) with nHibernate’s proxies. In the report all the contact fields will contain error messages. The subreport on the  lines will work. But still the lines are not read from the database until rendering the sub-report. So for this lazy loading to work the report has to be run against a dataset with an open dataconnection. That’s bad, I try do do as little as possible, and most likely not presenting a report, with an open connection. A far better scenario would be to fetch all data in one go, close the connection to the database and render the report after that. This can be done by eagerly loading the Contact and Lines properties and disposing of the session before returning the data.

In the nHibernate API the fetch mode can be set on a property level. The code in the repository takes care of fetching all data in one big snapshot.

public IList<Invoice> ListPrintableInvoices()

{

    using (var session = SessionFactory.GetFactory.OpenSession())

    {

        var query = session.CreateCriteria(typeof(Invoice));

        query.AddOrder(Order.Asc("Number"));

        query.Add(Restrictions.Eq("PrintIt", true));

        query.SetFetchMode("Lines", FetchMode.Eager);

        query.SetFetchMode("ForContact", FetchMode.Eager);

        return query.List<Invoice>();

    }

}

 

The repository reads all data from the database and closes the connection. After that the collected data are input to the reportviewer. Which now works completely as hoped for.

 

Rep6

 

I have my report complete with printing and export functionality and am still working with my beloved domain objects.

This way reporting can almost be pure fun.

Filed under:
Discuss (7)

Check out Virtual ALT.NET

Posted by aaronjensen, Tuesday, June 30, 2009 (588 views)

Several months ago a few people started hosting a Virtual ALT.NET meeting right here on the information super highway. I've been to a few and they're always packed with information and good conversation. It's a great way to learn new things or show off cool stuff you've been working on. If you haven't been to one, I'd recommend you check one out. There are two great looking meetings hosted by Ryan Svihla coming up soon:

Development with Castle Project with Ryan Svihla July 1 and July 8
Ryan will be doing a two part series on the Castle Project.  Mark your calendar for some Castle Project fun.
Ryan Svihla has been working as a C# developer Farm Bureau Bank in San Antonio since September 2007. Before that he worked as  a Consultant in Lincoln, NE for 3 years, where he had working experience with Php, some Perl, Python and of course C#.  Attemping Agile since early 2008 as an eager student with a focus on making programming more useful and relevant for the end user.

IoC and Dip through Castle Windsor
Ever wonder what acronyms like IoC and Dip mean? If you know what they mean do you wonder why anyone would use them in code?  This talk aims to deal primarily with those two questions through the use of Castle Windsor IoC container.  Intermediate level C# material with a couple of more advanced demos at the end for fun and pleasure.
Central Daylight Time
Start Time: Web, July 1, 2009 8:00 PM UTC/GMT -5 hours
End Time: Web, July 1, 2009 10:00 PM UTC/GMT -5 hours
Attendee URL: http://snipr.com/virtualaltnet (Live Meeting)


Web Development with Castle Monorail, Active Record and Brail view engine
Have a look at the first popular MVC .Net based web framework. Also will be covering persistance with ActiveRecord, and view templates using Brail.  Bonus, will demo a plugin framework for building CMS like applications.
Central Daylight Time
Start Time: Web, July 8, 2009 8:00 PM UTC/GMT -5 hours
End Time: Web, July 8, 2009 10:00 PM UTC/GMT -5 hours
Attendee URL: http://snipr.com/virtualaltnet (Live Meeting)

Hope to see you all there!

Filed under: ,
Discuss (2)

Making your code easier to understand context/specification style unit tests

Posted by Ian Cooper, Monday, June 29, 2009 (1,811 views)

When we started our current project we did not use context/specification style testing, instead we used testcase-per-class with a four-phase test model (also known as arrange-act-assert). Although we followed story-test driven development (STDD) we were not explicitly Behavior-Driven Development BDD when we set out. Over time I began to see the path between STDD and BDD we shifted toward a BDD approach.

That is really background for what comes next. As part of this shift we started writing more context/specification style tests. We did not re-write our existing testcase-per-class fixtures (then and still now I would see the possibility of using multiple test organisational patterns within a project; some of our tests still seem better with testcase-per-class). Recently we have had new developers join the team. One interesting, if anecdotal, observation has been that those developers find it easier to use tests as a source of documentation for what the software is doing when they are in the context/specification style. This is a useful observation, because the rest of the team is able to supply much of the context for testcase-per-class fixtures by virtue of having worked on the codebase and so do not see the lack so easily.

To build a maintainable system you have to build one where the behavior can be understood. Tests offer this promise, but often we have found that tests failed us, because the tests were no easier to comprehend than the code under test. Context/specification style tests seem to be better on this account. Of course there is no silver bullet in software. You still have to put the effort into making your context/specification tests readable, but the form seems helpful toward achieving that goal.

I'll try to post more on my experiences with BDD style approaches as they come out. I would also recommend that anyone interested in the topic look at the RSpec book from the Pragmatic Programmers which offers a great overview of the topic.

 

 

 

Discuss (6)

Fighting Fabricated Complexity

Posted by Patrick Smacchia, Sunday, June 28, 2009 (1,784 views)

Normal 0 21 false false false FR X-NONE X-NONE

During my interview on Code Metrics by Scott Hanselman’s on Software Metrics, Scott had a particularly relevant remark.

 

Basically, while I was explaining that long and complex methods are killing quality and should be split into smaller methods, Scott asked me:

looking at this big too complicated method and I break it up into smaller methods, the complexity of the business problem is still there, looking at my application I can say, this is no longer complex from the method perspective, but the software itself, the way it is coupled with other bits of code, may indicate other problem…

 

Software complexity is a subjective measure relative to the human cognition capacity. Something is complex when it requires effort to be understood by a human. The fact is that software complexity is a 2 dimensional measure. To understand a piece of code one must understand both:

  • what this piece of code is supposed to do at run-time, the behavior of the code, this is the business problem complexity 
  • how the actual implementation does achieve the business problem,  what was the developer mental state while she wrote the code, this is the implementation complexity.

Business problem complexity lies into the specification of the program and reducing it means working on the behavior of the code itself. On the other hand, we are talking of fabricated complexity when it comes to the complexity of the implementation: it is fabricated in the sense that it can be reduced without altering the behavior of the code. As an illustration here is a super/giant/complex method found inside the .Net Framework implementation System.Windows.Forms.DataGridView.GetClipboardContent():

 

 

 

GetClipboardContent() is made of around 300 Lines of Code and has a ILComplexity equals to 192. GetClipboardContent() does not have drastic performance requirement. As a consequence I don’t see any justification for not refactoring this massive method into smaller ones and maybe even a small classes hierarchy that could help in implementing the enormous switch/cases. Doing so would certainly discard a lot of fabricated complexity.

 

 

Fighting Fabricated Complexity with Simple Code Metrics

The simplest way to limit fabricated complexity is to abide by simple code metrics thresholds. This is why one of the default CQL rule proposed by NDepend is the following one:

 

// <Name>Quick summary of methods to refactor</Name>

WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE

     (  NbLinesOfCode > 30 OR             

        // http://www.ndepend.com/Metrics.aspx#NbLinesOfCode

        NbILInstructions > 200 OR         

        // http://www.ndepend.com/Metrics.aspx#NbILInstructions

        CyclomaticComplexity > 20 OR      

        // http://www.ndepend.com/Metrics.aspx#CC

        ILCyclomaticComplexity > 50 OR    

        // http://www.ndepend.com/Metrics.aspx#ILCC

        ILNestingDepth > 4 OR             

        // http://www.ndepend.com/Metrics.aspx#ILNestingDepth

        NbParameters > 5 OR               

        // http://www.ndepend.com/Metrics.aspx#NbParameters

        NbVariables > 8 OR                

        // http://www.ndepend.com/Metrics.aspx#NbVariables

        NbOverloads > 6 )                 

        // http://www.ndepend.com/Metrics.aspx#NbOverloads

 

 

Fighting Fabricated Complexity with Abstractions

Another popular way to limit fabricated complexity is to hide implementations behind some interfaces. Even though interfaces are not contracts, an interface itself often conveys enough information to make its purpose understandable. For example the IDisposable pattern is a complex topic but still, the IDisposable interface present only one method and we at least understand that it is an indication that some unmanaged resources must be released somehow. When a piece of code relies on an interface, at code review time, the interface relieves the developer from the burden of mastering every details of the implementation(s) hided by the interface. This is in essence the Liskov Subsitution Principle.

 

NDepend provides 2 ways to asses if and where your program should use more abstractions. First NDepend proposes the Robert C Martin metrics about Abstractness vs Instability. The idea is that the more a code element of a program is popular, the more it should be abstract. Or in other words, avoid depending too much directly on implementations, depend on abstractions instead. By popular code element I mean an assembly (but the idea works also for namespaces and types) that is massively used by other assemblies of the program. Abstractness of a group of types (like an assembly) is the ratio NbAbstractTypes / NbTotalTypes. There are debates about how these metrics should be computed and we plan in the future to make Robert C Martin's metrics more flexible but still, you get the point, it is not a good idea to have concrete types very popular in your code base. This provokes some Zones of Pains in your program, where changing the implementations can potentially affect a large portion of the program. And implementations are known to evolve more often than abstractions.

 

The second way to assess if more abstractions is needed is to rely on the Level metric. I won’t detail here this metric and its usage because I have already done it in the post Layering, the Level metric and the Discourse of Method. The idea here is that using more interfaces decrease the overall Level value of code elements (classes/namespaces). Thus, if many classes and namespaces have a high Level value (> 12), it means that you have a long stack of concrete layers sitting above each others. Introducing abstractions is then a good idea to split such long stack and benefit from the interface simplification describe above.

 

 

 

Fighting Fabricated Complexity with Immutability

A common source of fabricated complexity is mutable states. The human brain is not properly wired to anticipate what is really happening at run-time in a program. While reviewing a class, it is hard to imagine how many instances will simultaneously exists at runtime and how the states of each these instances will evolve over time. This is actually THE major source of problems when dealing with a multi-threaded program. If a class is immutable (meaning if the states of all its instances objects don’t change at runtime once the constructor is called) its runtime behavior immediately becomes much easier to grasp and as a bonus, one doesn’t need to synchronize access to immutable objects. For more information, I wrote about the benefits of immutable types and how NDepend can help in statically verifying immutability.

 

 

Fighting Fabricated Complexity with minimal Coupling

When trying to re-engineer/understand/refactor a large piece of code (I mean something made of dozens of classes like a big namespaces or an assembly), the difficulty is directly proportional to the coupling between considered code elements. Both these following graphs are made of dependencies between 23 classes, one with 53 edges and the other one with 175 edges: which one would you prefer to deal with?

 

 

 

 

 

 

 

While clear componentization is certainly the best way to fight against entangled/spaghetti code, keep in mind that using abstractions is also a good way to limit the over coupling-overhead. Indeed, if an interface has N implementations, then relying only on the interface is virtually like depending on the N underlying classes, except that from the static dependency point of view, you actually rely on only one type.

 

 

Could Fabricated Complexity be Measured?

There are plenty of other sources of fabricated complexity and I estimate that the 4 quoted ones are certainly the big 4 culprits. One could arguably appends also the ratio of code coverage + the number of automatic tests in the list, since a clean tests suite certainly forces the code to be better designed, simpler and more maintainable.

 

Interestingly enough, all these potential sources of problem can be controlled through NDepend. Could we find a formula that might process all these data to finally spit a number (a score) to measure the Fabricated Complexity? This approach is implemented in tools like Struture101 in the Java world that comes with a dedicated XS metric to measure fabricated complexity. Another example is the maintainability index range in VisualStudio that spits a number in the range 0-100. This number is linearly computed from potential source of fabricated complexity such as NbLinesOfCode, CyclomaticComplexity… and being lower than 20 is bad.

 

Such metrics are certainly interesting but I have a few caveats. The inventors of these formulas claim that in a certain range of value the code is crappy. The fact is that the value spitted doesn’t have any associated dimension. If a method has 120 lines of code and a Cyclomatic Complexity of 50, does it helps to add 120+50 and says that 170 something (something here is undetermined) is a bad thing? From the 2 values (120 Loc and 50 CC), isn’t it already obvious that the method should be splitted? And what about a method with 169 lines of code and no cyclomatic complexity (such as the massive Windows Form InitializeComponent() method)? I don’t think that such a method is as bad as the previous one and still they both measure 170 something.

 

Let's take for example the more and more popular CRAP metric that helps to detect crap code. The idea is that crap code is complex methods and poorly covered by tests.The proposed formula is

CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m) where comp(m) is the cyclomatic complexity of method m, and cov(m) is the test code coverage provided by automated tests.

By mixing it up, it is hard to understand the meaning of an estimation of the fabricated complexity value and worst, it makes harder to predict which refactoring will affect positively the value of the metric. This is the reason why so far in NDepend, we favored a more linearly independent/vectorial way to assess the exact causes of problems. To detect complex methods poorly covered with NDepend one just needs the following CQL rule and adjust thresholds at whim: Normal 0 21 false false false FR X-NONE X-NONE MicrosoftInternetExplorer4

 

WARN IF Count > 0 IN SELECT METHODS WHERE CyclomaticComplexity > 10 AND PercentageCoverage  < 90 ORDER BY NbLinesOfCode DESC


The CQL result panel provides all needed information to work with the crap methods detected and lets jump directly into VisualStudio to view and edit culprit methods:

 

 

Alternatively, the CQL flexibility lets correlate these metrics with other kind of relevant information, like for example detecting crap methods added recently to the code base (or also crap methods where ChangesObjectState, ChangesTypeState, CodeWasChanged, is declared inside or outside certains assemblies/nalmespaces/classes, not IsGeneratedByCompiler, is used by a certain code element, is using certain code elements, BecameObsolete...etc):

 

Normal 0 21 false false false FR X-NONE X-NONE MicrosoftInternetExplorer4

WARN IF Count > 0 IN SELECT METHODS WHERE WasAdded AND CyclomaticComplexity > 10 AND PercentageCoverage  < 90 ORDER BY NbLinesOfCode DESC

Also one can do experiments and compose metrics at whim:

 

 

Normal 0 21 false false false FR X-NONE X-NONE

This situation might evolve in the future. But so far I would prefer to avoid giving the NDepend user the feeling that fighting fabricated complexity is only a matter of reducing the value of a naked index (i.e an index without any dimension). Things must remain close to the code itself: if I have a method with 15 parameters it seems much more meaningful than having a class with a maintainability index equals to 18 or a CRAP value of 33.21.

 

Are you using these formulas? What’s your opinion on this?

 

 

 

 

Discuss (4)

MSpec... for Boo!

Posted by aaronjensen, Saturday, June 27, 2009 (1,231 views)

Jeffery Olson (a fellow Eleutian guy) has put in some good effort to create a very readable, very clean MSpec DSL for Boo. You should give it a gander.

Filed under: ,
Discuss (0)

Talking conventions with the Hanselman

Posted by Jeremy D. Miller, Saturday, June 27, 2009 (1,500 views)

Scott Hanselman posted a podcast he & I recorded at NDC last week.  We nominally talked about applying conventions and opinionated software to .Net, then we went off on every possible tangent that presented itself.

Discuss (0)

The “Anti-For” Campaign

Posted by Matthew.Podwysocki, Friday, June 26, 2009 (2,447 views)

Recently, there has been an effort launched called the “Anti-If Campaign” in which they deride the use of if statements and instead, focus on Object Oriented Principles in order to create more flexible designs.  Now certainly, I have a sympathetic ear to this cause as I’ve seen code that literally walks off the side of the screen due to nesting of if statements.  Pattern matching to me, especially at the top level of the function is actually quite beautiful in a way, such as the implementations in Haskell:

-- Haskell
lucas :: Int -> Integer
lucas 0 = 2
lucas 1 = 1
lucas n = lucas (n - 2) + lucas (n - 1)

And in Erlang, this also holds true:

% Erlang
-module(lucascalc).
-export([lucas/1]).

lucas(0) -> 2;
lucas(1) -> 1;
lucas(N) -> lucas (N - 2) + lucas (N - 1).

Simple, easy to understand and best of all, no if statements.  But, instead of focus on this debate, I’d like to propose another which strikes closer to this functional programmers heart, the “Anti-For Campaign”.  This is simply to say that we should create and use composable functions instead of explicit for loops.  This is actually an old post I had written months ago and until now had been unfinished, but now with some inspiration, it’ll finally be done.

What and Why?

Before you throw all sorts of questions asking what and why, let me instead ask a question.  When you’re writing a loop, ask yourself the question, “What am I accomplishing in this loop?”  Chances are, it might be one of the following:

  • Query (Map, Filter, etc)
  • Aggregation (Sum, Count, etc)
  • Perform some side effect

If you’re doing more than one of those in a single loop, then well, you’re probably doing too much.  In fact, Martin Fowler’s Refactoring site has a refactoring called