Suggestion: Class library refactoring

Apr 20, 2012 at 1:08 PM

T4MVC has become an essential part of my MVC toolkit, however, is not really open for customization or extension.

I'm assuming that the current single-file template-and-code mish-mash is simply the result of evolution over time. However, given the current file size it's fairly obvious that it must have become less than trivial to maintain, let alone modify or extend with new features. Also, T4 templates are not as easy to debug as regular code and I'm not aware of any unit-test like facilities for them.

I'd therefore like to propose a refactoring of T4MVC into a class library that a reduced template could make use of. I'm not a T4 expert so am assuming this is possible in the first place.

This would provide a number of potential benefits:

  • Greater ease of maintenance (debugging, refactoring, etc.)
  • Unit tests to ensure that the core parts produce the expected results
  • Easier code accessibility for potential contributors
  • Reduced template file size (I'm guessing that this could potentially speed up output generation as there is less dynamic compilation going on)
  • It'd be easy to enable a MEF-based plugin model for extending the code generation process

Motivational background:

I was inspired to make this suggestion as I was in need of the path to a partial view folder. I had an action that takes an enum parameter (specifying which partial to render), but then needed to combine the specific view folder path with the partial view name. To achieve this I had to go figure out how to obtain the path, find out where in to emit it and test the changes. Without code navigation and similar features this was all needlessly complicated for what was essentially a minor feature addition.

Thoughts? :)

Apr 22, 2012 at 12:53 AM

You are certainly right that the template is a result of evolution over time, with various contributions from a lot of people. It started out a lot smaller than it is now, and I agree that maintenance/extension is on the painful side. It could use a good round of clean up!

To address a couple of your points:

  • Debugging is actually pretty easy once you know the trick: just attach another instance of VS to it and open the .tt file in there. Then debugging just works.
  • Speed up of the generation: I don't think that's actually a factor, as once the .tt file is compiled, the same compiled bits keep getting reused. i.e. if you keep choosing 'Run Custom Tool' on it, you are just running it, and not recompiling anything.

The rest of the points I agree with.

Whether a rewrite as a class library is the right answer is an interesting question. In term of ease of development, it would come with some pros and cons. Some cons:

  • I think you'd need to restart VS each time you make a change to the library, while with the .tt file you can just resave it in the same instance
  • .tt files are good at generating templated output compared to straight C# code. Though that could be mitigated by using preprocessed T4 templates inside the library.
  • That might mean turning it into a VSIX extension instead of a plain file that comes with the project. Maybe there is a way to avoid that. But we also want to avoid making people commit the binary library into their project. Nuget might help there.

Anyway, we need to think about all this. One fairly big factor is that I have limited time to work on T4MVC, so hopefully any such effort would come with good community contribution :)

Apr 23, 2012 at 12:49 PM

Sadly, I have little experience creating either VSIX extensions or T4 templates, so am not aware of the pros and cons of either solution. I'd think the VSIX solution would be much more flexible - you could create an options panel for the code generation settings and probably forego having a .TT file altogether. On the other hand, it'd likely be more work.

I personally wouldn't mind having to restart VS to enable changes - except when changes are frequent. VS seems to be pretty slow at checking for updates to installed extensions, so I always end up having just loaded a solution when it notifies me. T4MVC seems to have reached a feature set that would make updates less frequent but you're probably a better judge of that.

I think the best chance of any progress with this is if you chart the direction :o) Someone with knowledge of the pros and cons of the possible solutions needs to define a list of tasks that need to be completed in order to get to vNext, whatever that ends up being. Having a list of fairly specific tasks makes it much easier for potential contributors to find something appropriate to their skill set and available time, which thus increases the chance of actually getting any.

Apr 23, 2012 at 11:01 PM

My comment about having to restart VS was actually from the point of view of developing the template rather than consuming it. But anyway, that's not a major issue, as all VSIX authors have to deal with it.

It my very well be that moving to a VSIX is the right long term direction to this project, though that would definitely be a good chunk of work. I'd be interested to see how many folks would prefer that model over the current model. Maybe the time will come for such transition.

Any the name T4MVC would no longer make much sense! :)

Apr 24, 2012 at 9:49 AM

Restarting VS to test changes would actually be a major pain, but I suspect that most things could be unit tested in advance.

I think the current solution works fairly well, so perhaps it'd all just be too much work for too little gain - especially considering that neither of us seems to be jumping up and down at the thought of all the work involved :o)

It might make sense with a poll or some such - I suspect T4MVC has a fairly large user base (happy, but silent).

You're probably also best equipped to identify the problem points with the current solution. If you wish for people to become more engaged in the development the suggestion about creating tasks/issues to represent stuff that needs to be done still applies.

Apr 25, 2012 at 2:57 PM

I don't feel a full VSIX is the best way to go. The biggest issue I see is you loose the current portability of the template. It would require every developer to have the same version of the plugin and would make source control more difficult.

I propose a best of both worlds solution. Refactor the non-user maintainable code into an assembly provided in the nuget package, leaving the codegen template in the project. Then move the settings into a versioned xml file so it can be future proofed. With these two changes you gain better code control and can handle upgrades better. Finally, a VSIX can be built to provide a settings manager and other functions. The addon would not be necessary for build, but an added bonus.

Apr 26, 2012 at 12:16 PM

Yes, something like that might be conceivable,

Apr 26, 2012 at 1:21 PM

Good suggestions, and also more akin to what I had in mind with the original proposal. Extracting the non-user maintainable parts into a class library makes the code easier to unit test and extend with the only downside being the assembly dependency for the template.