CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

It's either puke worthy or elegant

protected static T redirectTo<T, CONTROLLER>(Expression<Func<CONTROLLER, object>> expression) where T : ViewModel, new()
{
return new T() {Override = new ControllerRedirectResult<CONTROLLER>(expression)};
}

Just a wee bit of code we're using in our MVC Controller base class.  I'm happy with what it *does,* but tell me that isn't butt ugly code.  I think the angle bracket and generic constraint noise tax is like the governor on school buses that keeps them from going over 65 miles an hour.  Anders' way of telling you that you're going too far and time to back off.  Anyway, the usage of the stuff above isn't that bad, and the unit testing is pretty easy.

Comments are welcome.  This kind of thing bothers me in the sense that later developers are gonna scream WTF! when they find it in the code.
 


 



Comments

Neil Mosafi said:

Yeah, it's C#, it's strongly typed, and that's just the way it is I guess!  A junior developer would probably not be comfy with it, but hopefully it would be hidden in the lower depths of an API and hot need to be changed EVER.

Regarding the naming, I would go with the T prefix such as:

protected static TViewModel RedirectTo<TViewModel, TController>(Expression<Func<TController, object>> expression)

           where TViewModel : ViewModel, new()

Perhaps some better aliasing support in the compiler would be nice, something like

using FuncObjectExpression<TReturn> = Expression<Func<TReturn, object>>;

Which would then make the function

RedirectTo<..>(FuncObjectExpression<TController> expression)

# June 19, 2008 6:02 PM

Mike Strobel said:

I second Bill.  WTF is up with the "CONTROLLER" generic constraint?  It should be "TController", and your method name should be "RedirectTo" rather than "redirectTo".  PascalCase is explicitly recommended in Microsoft's naming guidelines for non-private members.

# June 19, 2008 6:36 PM

Jeremy D. Miller said:

@All,

I'm not wild about the TWhatever, MS guideline or not.  We use all caps in our standard and we're consistent.  

The only really important thing about a coding standard is consistency anyway.

@Mike,

*Our* coding standard says camel casing for protected and private methods.  Pascal casing everywhere makes your code look way too much like VB.  My ideas about what a coding standard should be were formed on projects with Java guys earlier in the decade.

The awesome thing about being ALT.NET is being able to disregard MS coding standards if you don't like them;-)

# June 19, 2008 6:47 PM

Neil Mosafi said:

Not sure about that.  If you have that coding standard then it's perfectly valid for someone to do this:

public void Foo()

protected void foo()

This would of course (if you care) render your assembly non CLS compliant and would mean all those poor VB.NET developers out there would not be able to use it!

# June 19, 2008 7:38 PM

Chad Myers said:

@Bill et al

I was skeptical about the GENERICTYPE vs. TGenericType stuff at first, but as we started doing more generics it became clear that one important rule about doing generics is that you REALLY want the generic type to stand out as much as possible.

I'm sorry, but TViewModel blends in too easily with the rest of the code whereas VIEWMODEL stands out like a sore thumb (which is the desired effect.

# June 19, 2008 7:47 PM

Mike Suarez said:

yep i find myself tangled in generics syntax a lot nowadays n' i share the feeling ... it makes sense but adds some verbosity n' ugliness ... we might be evolving into something :) i hope it turns  prettier soon ..

# June 19, 2008 9:00 PM

Jeremy D. Miller said:

@Neil,

Um Neil, Pascal case or Camel casing has absolutely nothing to do with whether or not my assembly could be used by VB.Net code.

# June 19, 2008 10:47 PM

Erik said:

@Jeremy - I think Neil's point is that because VB.Net is case insensitive, 'Foo' == 'foo' for that language. Therefore, one of these methods would be inaccessible.

# June 19, 2008 10:52 PM

Colin Jack said:

Couldn't agree more. We have a few ultra useful classes deep in our domain model that use generics a lot including to multiple levels. It's a nighmare to read that code especially when the generics is on the method.

I think when we discussed our issues we decided that perhaps we were trying to do too much in the base class in a typesafe manner. Very DRY but very un-readable. We might have been better just using composition and each composed class would have had less generic arguments. Didn't take it any further though because we aren't working on that part of the code right now.

Also could you not give T a better name, it would make the line longer but might help slightly.

# June 20, 2008 3:31 AM

FransBouma said:

What I wonder about is why there's an expression tree passed in instead of a Func. The expression tree suggests that the expression is modified along the code path with more expressions being added to it, and I assume it's then compiled inside the controller to a delegate.

This IMHO is a bad thing to do, as it is a way of self modifying code. IMHO, in-memory code shouldn't use expression trees but simply Func statements which are verifyable at compile time and you can determine what's passed in in a reasonable way.

# June 20, 2008 3:44 AM

Neil Mosafi said:

@Erik - correct.  The spec states "For two identifiers to be considered distinct, they must differ by more than just their case.".  I personally use Pascal case for all methods and properties irrelvant of their access modifiers (though I initially hated doing so coming from a C++ background).  

Actually I gave it a go and both methods would actually be inaccessible - in VB you receive the build error 'Foo' is ambiguous because multiple kinds of members with this name exist in class Class1

# June 20, 2008 5:56 AM

Mike Strobel said:

@Jeremy: The problem with using camelCase for protected members is that those members are visible outside of your assembly.  You are therefore polluting the consistency that has been carefully established across the .NET platform, not just in the base class library, but also in the vast majority of third-party frameworks.  At the risk of sounding pompus, this is simply inconsiderate.  It's not just about what Microsoft says in its naming guidelines--it's about what has been clearly and widely accepted by your .NET developer peers.  This isn't Java, and appeasing migrating Java developers does not, in my opinion, justify breaking from what is a clearly established standard for the platform.  I used to be a hardcore Java programmer, but when I migrated to .NET, I completly changed my coding style, because the established Java styles were simply not appropriate.  Your argument about PascalCase resembling VB code sounds flimsy as well--.NET is not a language; it's a language-agnostic platform.  As others have already been pointed out, there are some inconsistencies regarding uniqueness of named identifiers across programming language boundaries.

@Chad: I have to disagree with your argument that generic type parameters should be named in all caps, and for much more fundamental reasons.  I cannot think of any reason why a word, no less a sequence of words, should appear in all caps.  VIEWMODEL is not an acronym.  Moreover, one must visually scan the entire identifier (with more care than usual) because there is no clear separation between the individual words (in this case "view" and "model").  At least when using PascalCase, one can quickly distinguish the individual words in the identifier, and thus quickly establish its meaning.  I see no compelling reason why generics type parameters should be made to stand out any more than they already do--between the presence of angle brackets and an appropriate prefix (e.g. the 'T' in "TViewModel"), any seasoned .NET/C++/Java developer should be able to instantly pick out a generic type parameter.  I think, however, that the most compelling argument against using all caps is a simple consideration of aesthetics.  THERE IS NO REASON WHY THIS SENTENCE NEEDS TO STICK OUT OF THIS PARAGRAPH LIKE A SORE THUMB.  If you were to tell me that the preceding sentence was loud, obnoxious, and totally unnecessary, I would agree.  If you really want your generic type parameters to stick out, consider writing a simple VS plugin to change the color, font face, or font weight of those parameters.  Better yet, put in a feature request to the VS team to make generic type parameters a distinct element type in the 'Fonts and Colors' configuration.

I do apologize if I sound like a pompus ass here.  I realize that you don't know me, and you have absolutely no reason to listen to me.  However, the sheer number of compliments that I have received about my coding style suggests that I might just be on to something :).

# June 20, 2008 10:09 AM

Jeremy D. Miller said:

@Frans,

We're not manipulating the Expression in any way.  Just using it as a way to pass a property name or method name.  It's effectively just compiler safe reflection, if you'll let me get away with saying that.  I'd call it a hacky way to do Ruby symbols.

@Erik,

There wouldn't likely be a pascalCase and a camelCase method with the same name.

# June 20, 2008 10:50 AM

Chad Myers said:

@Mike: We're writing an internal app and so we don't really care about CLS compliance and certainly not whether it's VB compatible.  We're primarily concerned with what helps us develop faster and subtle visual cues like underscore-prefixed member variables and camelCase'd protected/private members help us scan the code faster.

RE: VIEWMODEL - This isn't English, it's C#, and if it makes the C# easier to read, that's most important. We don't have editors and proofreader's scanning our code for English correctness.  

VIEWMODEL sticks out like a sore thumb, as it should. We have found it extremely disorienting to look into the middle of heavily-generic'd code and so every little visual cue that helps separate real code from generic code count.s

# June 20, 2008 10:56 AM

FransBouma said:

Jeremy: ok, though it could be done with just Func statements as well, then. The point with having Expression<Func<... >> is that someone could abuse the API without the ability to check whether it is abused (as the compiler can't verify it).

Indeed, using Funcs to access properties etc. is a neat way to write generic code without reflection. :)

# June 20, 2008 11:15 AM

Richard said:

If protected method foo() is used in 100 places, and you decide to make it public, you have to change it to Foo() in 100 places.

# June 20, 2008 12:30 PM

Jeremy D. Miller said:

@Richard,

Shift-F6 and rename "foo" to "Foo"

Not so hard.

# June 20, 2008 12:32 PM

Richard said:

I didn't say it was hard. But it is a mess in version control.

# June 20, 2008 12:44 PM

Chad Myers said:

@Frans it's the static reflection technique that Daniel Cazzulino came up with for Moq:

weblogs.asp.net/.../Linq-beyond-queries_3A00_-strong_2D00_typed-reflection_2100_.aspx)

Can you abuse it? Sure. Pass nulls into things can cause problems too, so I'm not sure why this would be any worse than anything else.

# June 20, 2008 1:20 PM

Jeremy D. Miller said:

@Richard,

Again, no it's not.  If you're using a pessimistic locking approach for your source control, I guess it would be a PITA.  With Subversion, I wouldn't hesitate.

Again, to be obnoxious.  ALT.NET means I get to use Subversion and not have some of those problems.

# June 20, 2008 1:43 PM

Roederick Sand said:

@Jeremy

Again, to be obnoxious.  ALT.NET means ...

ALT.NET means a lot of things none of them being an 'a**h****'' I don't know why, but after you (and Chad) have been kicked out of your last job, it's no more fun to watch your attitude.

# June 20, 2008 7:18 PM

Jeremy D. Miller said:

@ Roederick,

Are you seriously calling me names and using BileBlog nomenclature just because I don't care for the Microsoft coding standards, and instead, choose to use a *very* common standard (camel casing private and protected members) in .Net projects?

# June 20, 2008 8:31 PM

Roederick Sand said:

@Jeremy

I have no problems with your coding standards, I have problems with the tone of your responses to humble comments on this blog.

# June 20, 2008 10:20 PM

Mauricio said:

Funny, I've been experimenting with a similar syntax myself for some time (although for Monorail instead of asp.net mvc), like:

this.RedirectToAction(c => c.SomeAction);

implemented as extension methods.

# June 20, 2008 10:57 PM

Colin Jack said:

@Roederick

I think that any issues you have with the tone are just down to the fact that written media makes miscommunication likely.

Actually when Jeremy said he was being obnoxious he plainly wasn't, and even re-reading his comments again I don't see any reason you could possible take offense form them.

# June 21, 2008 5:07 AM

Colin Jack said:

"Shift-F6 and rename "foo" to "Foo"

Not so hard."

It can be a pain though, especially as for a large codebase you might well have multiple solutions (especially if multiple applications share some parts of the codebase).

# June 21, 2008 5:08 AM

Colin Jack said:

Sorry for 3 comments in a row but after a bit of thought my last comment was utter rubbish, ignore it! :)

# June 21, 2008 5:23 AM

Roederick Sand said:

@Colin

"written media makes miscommunication likely."

Yep. What I actually ment was - ALT.NET doesn't mean to be different for the difference sake.

And I am taking A-word back.

# June 21, 2008 8:14 AM

Chad Myers said:

@Roederick Jeremy's point was that ALT.NET means not doing things just because everyone else in the .NET/MSFT-o-sphere is doing it (i.e. VSS/TFS).  We've found Subversion takes away a lot of pain/worry/stress of source control. So wide-sweeping refactorings are encouraged if it's the right thing to do whereas, in other shops I've been in, you were afraid to make big changes for some of the reasons mentioned earlier, lack of test coverage, lots of file manipulation if not using R# to make the refactoring automatic, etc, etc, etc.

As far as my comment re: VB:  It's really a pragmatic thing:  Why should we concern ourselves with CLS compliance and VB.NET, JScript.NET, or any other .NET language other than the one(s) we're using?

If you or anyone else has a good argument, I'm all ears and I'm willing to consider it.  At this time, however, it would appear to be a waste of time with no tangible benefit.

If we were releasing a public API or an OSS project that might be used from VB.NET or some other .NET language, then absolutely, that would be an issue.

# June 21, 2008 12:58 PM

PandaWood said:

Well, my take is that if you'd used TController instead of CONTROLLER, it would have taken me a few seconds longer to way "WTF".  It's up to you to decide how much that is worth.

# June 22, 2008 11:49 PM

Brian Chiasson said:

This gives me an opportunity to take Atwood's recent advice and learn something new as I have not done anything with generics and this code is frying my brain.

www.codinghorror.com/.../001138.html

On another note, I am surprised you are using a static method here, I have found that statics are pure headaches when doing any TFD.

# June 24, 2008 1:18 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

Our Sponsors

Proudly Partnered With


This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP