Luke's profilelzcdPhotosBlogListsMore ![]() | Help |
lzcdCheaper than kittens |
|||||
|
June 01 The templating engine that no talks about… at least not in front of the childrenHere’s a little experiment for you to try in Visual Studio 2008:
Now if you save the file you should note that there’s a little “code behind” file hiding below the .tt file in much the same fashion as a WinForms or an ASP.Net control. And if we open it up we can see that it the result of the .tt file being executed as if it was a template:
So viola! We have a templating engine built right into Visual Studio and there you were just about to spend big dollars on a third party solution. Don’t you feel silly now? Well you shouldn’t feel quite so bad… yet… as the templating engine, T4 (as it’s officially known by Microsoft as) is all very nice but it’s not quite what I’m usually looking for in a templating engine. Quite often in such scenarios, what I want to do is grab some templates, grab some data and mix them all together en masse using a funky little console app to generate all sorts of weird and wonderful files for me. T4 just looks like it’s dealing with one file at a time and, even more annoyingly, I seem to need to be in Visual Studio to use it. This just won’t do. So how we do fix this? It just so happens that we can host the T4 scripting engine ourselves and do all sorts of weird and wonderful things with it. The “catch” is that if you do a search through the MSDN doco or related blogs on the T4 engine you’ll come across a boat load of API stuff that can all look rather intimidating. The good news is that we’re going to be producing a working host with little to no effort at all. (Cue fanfare) Presenting: Luke’s ultra quick starter guide to producing your own template crunching utility! In this example I’m going to be constructing a console app that takes a template file, a set of command line arguments and combines them together to produce a new file. It’s not exactly the most spectacular bit of technology around but it should hopefully get you on your way enough to produce you very own ultimate templating processing machine. Sooo…. the steps are as follows:
static void Main(string[] args) var commandLineArguments = new List<string>(args); var outputFilePath = Path.Combine(Path.GetDirectoryName(templateFilePath), Path.GetFileNameWithoutExtension(templateFilePath)); private static Host CreateHost(string templateFilePath, List<string> commandLineArguments) Most of this is quick and nasty throw away code (and not something I usually write… or at least admit to) so you can ignore most of it. The valuable bit that is worth noting is the code that creates an instance of T4’s template Engine class, feeds it a template file along with a mysterious thing called a host and magically churns out a brand new file from it. I’d suggest thinking of the Host as the middle man between your utility and the T4 templating engine… which brings us nicely to the next step which is…
[Serializable()] public bool LoadIncludeText(string requestFileName, out string content, out string location) if (!File.Exists(requestFileName)) content = File.ReadAllText(requestFileName); public object GetHostOption(string optionName) public string ResolveAssemblyReference(string assemblyReference) var candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference); return string.Empty; public List<string> CommandLineArguments { get; set; } public Type ResolveDirectiveProcessor(string processorName) public string ResolvePath(string path) if (File.Exists(path)) var candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), path); return path; public string ResolveParameterValue(string directiveId, string processorName, string parameterName) return string.Empty; public void SetFileExtension(string extension) public void LogErrors(CompilerErrorCollection errors) public AppDomain ProvideTemplatingAppDomain(string content) public void SetOutputEncoding(Encoding encoding, bool fromOutputDirective) } So now we have templates and a way to generate them. The thing that’s missing is a way to feed information from the outside world into the templates and the way we do this via Directive Processors. I’ll leave the fun of reading up about the specifics of these little beasties on MSDN as an exercise for the reader but here’s one I created earlier:
public class CustomDirectiveProcessor : DirectiveProcessor return false; public CodeDomProvider Provider { get; set; } public override void StartProcessingRun(CodeDomProvider languageProvider, string templateContents, CompilerErrorCollection errors) public static List<string> CommandLineArguments = new List<string>(); public override void ProcessDirective(string directiveName, IDictionary<string, string> arguments) if (string.Equals(directiveName, includeArgumentsKeyword, StringComparison.InvariantCultureIgnoreCase)) } private void GenerateCommandLineArgumentProperties(CodeGeneratorOptions options) property.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(CommandLineArguments[argumentIndex]))); using (StringWriter writer = new StringWriter(codeBuffer, CultureInfo.InvariantCulture)) public override void FinishProcessingRun() public override string GetClassCodeForProcessingRun() public override string[] GetImportsForProcessingRun() public override string GetPreInitializationCodeForProcessingRun() public override string GetPostInitializationCodeForProcessingRun() public override string[] GetReferencesForProcessingRun() So what does this directive processor do exactly? Well I’m glad you asked. :) It allows us to extend the templating engine with our own functionality. In this case, we’re going to make it so that when some adds the following bit of code to their templates, we’re going to magically read in the command line arguments and supply them as properties: So the only thing left to is to try it out on a template…
Hopefully you should see a brand new cs file in the folder your textfile resides in with some content (not entirely useful content I’ll admit… but template driven content none the less) If you go back and examine the mysterious entity that is the CustomDirectiveProcessor class a little more thoroughly you may notice a few odd looking things:
So now you know how to harness the inbuilt goodness that is the T4 templating engine for your evil purposes. Oh… and before I forget: One last little party piece…
..and rerun your console app. If you’ve got Visual Studio kicking around you should now be looking at one fully fledged breakpoint. Yep you can break and step through your templates just like any other Visual Studio code. It even supports variable inspections. Pretty cool, no? Now all that’s left is to go forth and template yourself silly. Enjoy. April 08 Game Writer’s Tip: The three R’s are not invited to the partyWhilst Readin’, wRitin’ and aRithmetic may have helped many people become the fine product members of society they are today, they generally don’t tend to appreciate being forced into doing such things in the course of learning how to play your game. The first reason for this is the rather boring reality of attempting to read any reasonable amount of text on a television (even one of the lovely wall sized flat panel jobbies) is rarely enjoyable. If it’s any more than about six words or any smaller than around 1/10 of the available screen space in size then a lot of your users are going to either endure horrible amounts of eye strain, skip past as quickly as possible or just plain give up before they’re more than a paragraph into your amazing narrative. Reason number two is possibly even more annoying but, none the less, just a true: People rarely read anything on a computer screen. Oh sure they may read the stuff that they’re actively seeking or writing (such as the latest celebrity gossip or the Facebook message to the distant relative some far off land) but just about everything else is either ignored or feared. And it’s not just those luddites or generationally challenged members of your office or family either. When was the last time you actually took the time to read a dialog window? Okay so if nobody is going to read anything we put up on screen, how do we inform them of all the good stuff like plot… or how play the game? If it’s something that you want to the user to do then best way to teach them is the same way as we learn in real life: by doing it. For example, if you want to teach the user that moving the left thumbstick moves their little avatar around the screen, why not show them the avatar on screen and let them experiment. Maybe provide a little short term goal to motivate them such as picking up an item or moving out of impending (but probably not real) danger? If it’s something about the plot / narrative of the story that you wish top convey then text can certainly work… but it’s best used vary sparingly (think along the lines of a twitter message or less) and usually as back up for some other means such as a voice over. Pick practically any really successful console game (from Mario through to Gears of War) and you’ll spot the signs. Very little text up on screen at any one time, Learning via experimentation and so forth. March 05 Sordid documentation revealedWe open this little story with David and Ducas having an IM conversation over Ducas' choice of "why is documentation so boring?" as an IM tag line:
Which tickled the fancy of David and prompted him to pose the question to the internal Readify Tech list:
To which I initially replied:
But after thinking about for a while over lunch, I came up with following, slightly more serious, response: Documentation for fun and profit I'm a huge fan of making documentation interesting (and hopefully fun) and have no idea what the point of producing dull documentation is. If the point of documentation is to communicate an idea then seems to make very little sense to sabotage that concept with a delivery mechanism that is actively discouraging that very act. Imagine your intended audience. If they're going to be struggling to stay awake during the discourse of your little phonebook style tome and resentful afterwards for having to loose a portion of their lives wading through it, what do you think the chances them actually retaining any of the supposedly important information is? There are two objections to producing "interesting" documentation that regularly get put forward and I'm yet to be convinced by either one of the them: The Corporate Image The classic 1950's "You're here to work, not have fun! Pull your socks up! Straighten your tie!" attitude continues to haunt a lot of us to this day. We feel guilty about anything that drifts away from the stern approval of the stereotypical "bank manager" type from our (grand) parents day. If it's fun it mustn't be work related. To that I say "Pfft!". Documentation is just like anything else your company produces. It has the chance to entice, enrapture and engage your customers and staff... or it can put them to sleep. It's the 21st century and guess what? Nobody is interested in being bored to death by reams of tedium. You wouldn't dream of spending hundreds of man-hours and squillions of dollars each year producing bad advertising and marketing would you? Well that's what a lot people do with documentation. They spend who knows how many hours and dollars describing their wonderful new creations... in a format that so tedious and boring they may as well have just locked the product and the documentation in the basement for all the good it's going to do. Bob from Accounting (Apologies for falling back on yet another bad stereotype here but I get the feeling that using geeks as a negative example would be detrimental to my cause :) ) The second objection to producing interesting documentation is that not everyone can do it. Whether it's a beautiful menagerie of Visio diagrams or a 'page turner' of a description, not everyone has it in them to produce interesting material. My argument to this is: don't make them. Just like you wouldn't attempt to force a dentist to fix a jet airliner engine, don't force people who can't write to write. There's little point. At best, you and your customers survive the trip. At worst, its a grizzly mess of morale nose dived into the ground and a whirlwind of large paper doorstops scattering across the neighbourhood. If you don't have someone in your organisation who relishes the chance to produce exciting printed material then hire someone who does. Just like those weird brightly coloured personalities that you hired to market your wares, good technical writers are a very good way to ensure your message actually gets through to your intended audience. So.... What are you waiting for? Go forth and write that epic take of love, loss and the inner working of the JRX-382! You've got nothing to lose and everything to gain. :) PS: Yes, I too recognise the irony of someone who struggles with the whole communication thing, attempting to tell others how to communicate. Don't blame me. Blame people like Infocom who had the temerity to demonstrate how to get away with such wild and whacky behaviour back in 1989: http://www.mv.com/ipusers/xlisper/zil.pdf March 01 A well versed reptileOne of the recent internal discussions kicked off by Russ Blake at Readify has been on what part to play IronPython should have in commercial software development. Is it ready for the cubicle dwelling masses? Here's my take on it: Python (Iron or otherwise):
I think the advantages of Python verses any other language is more a question of commercial environment and fashion than anything else. This isn’t good or bad. It just lumps it in with every other Turing complete language. Personally I find Python an acceptable language as: - It’s a good successor to Perl in terms of being a pragmatic scripting “glue” to bind other bits together. - The syntax, while having slightly different coloured goo than its more “commercial” peers, is readable. - It scales better than Perl in terms of being to construct medium to large sized applications. - It also has the advantage of being one of the current “cool kids” of application development (as the attendance of a recent programming comp clearly demonstrated. The only thing sexier than Google in young developers eyes at the moment seems to be Python.) My only small grumble with it, due to its Perl’esque pragmatic approach to being able to glue bits together, is that it very quickly exposes it ugly underscore ridden underbelly of working gears and levers in the pursuit of decent sized application development. So my overall response to Python in general is: Meh. Looking down from a greater altitude:
What I find more interesting is that Python tends to get used quite a lot as a hosted scripting language in other applications. Everything from games to GIMP to Chumbies seem to be ticking along with Python, LUA or some other scripting language lodged near their heart. And, hopefully without sounding too much like the crazy guy talking about how poultry controls the CIA, I think scripting languages are where is it’s at. Crazy Talk:
My dream business application, as I’ve bored many with on previous occasions, is one built in much the fashion as a modern game. Content designers (aka Business Analysts and Devs) world in their own little self contained bubble world of scripted language goodness. Framework developers work around this bubble, wiring up the ‘content’ to the graphics, storage and network bits. Content designers never attempt to write the binding code for an Infragristics grid and Framework developers never try and write the formula for calculating the rounding on the GST of a baked bread item purchased with a gift voucher. Now you there’s nothing stopping this from happening purely in the familiar world of C# or VB.NET but it presents a few issues. CLR without DLR is no fun:
The first is the nitty gritty technical pain of dealing with the shear tedium of attempting to host non-DLR languages in .Net. It’s just too much work to get a plug-in system working that doesn’t ending up stepping on the toes of memory (Yay App Domain unloading! ), exception handling (Yay App Domains!) or communication (Yay App Domains!). Secondly, there’s slightly non-intuitive ‘social’ side effects of picking of the same language for both framework and content construction. Content developers really need to focus on producing the content... not ‘peaking under the hood’ at what the Framework guys are doing and attempting to ‘patch’ into or around any random bits of framework that take their fancy. Thirdly, making a scripting language (or DSL if need be) your language of choice for how to articulate the solution to your problem is a very powerful idea indeed. In addition to being able to craft the syntax so that more elegantly describes the problem domain, executing your content via a scripting language means you gain a whole more context and control over what’s going on. Writing interfaces and APIs give you some control... but it’s practically impossible to have any sort of compile time confidence that the content developer hasn’t done something to (un)intentionally thwart the design of the underlying layers. (“So I noticed that if I used reflection and kicked off this on another thread then it all seemed to work... I hope that was okay?... Bob?... Bob?...”) Expressing the solution to a problem via scripting language or DSL is a higher level of abstraction as well. Want to add in a funky auto parallel’ising multithreaded network capable piece of code everywhere the content designer has decided to add some numbers together? No problems. The language host can specifically keep a look out for when such occasions occur and make a call your new code as required. Zero change the neat elegant highly readable content description of the business process and no need for the content developers to have to refactor their code with weird and wonderful attributes or other languages constructs that have nothing to do with the business problem at hand. So.... Crazy half-baked conclusion: My summation is: Hosting scripting languages / DSLs is cool. Python is okay as a possible scripting language choice... but may not be my first.
Random side thought: I’m thinking the long forgotten hero of scripting languages is Logo. · It’s relatively easy to implement · It has clean simple syntax · Arguments over punctuation and its placement rarely break out No joke. February 28 HR Violations in the name of Stored ProceduresPreface: As my home site of lzcd.com is going to be used for other (possibly evil) purposes, I thought I might christen my new choice of blogging locations with a random thought. Apologies in advance to any DBAs that know me... in particular those who know where I live :) It amused me when MySQL (relatively) recently introduced stored procedures. Being one of those poor saps that was "raised" in a commercial world of DB use, I had my expectations set at an early age and found the concept of a DB "surviving" for so long without stored procedures almost unimaginable. One or more DBAs would patrol the entrance to the DB. Resembling some sort of wizard from the likes of Discworld or Harry Potter, they strutted around in their tattered multicoloured robes, unkempt beards and wrinkled brows. It was only the inexperienced or dim witted that risked attempting entry without the permission of such fearsome guardians. Asking permission to see what lay behind the connection string was a double edged sword. If the DBA sensed fear above and beyond the normal levels of terror, as you lay prone upon the ground before him, he would refuse your request with a harsh quip that, if you were lucky, would only strip your self-esteem... and any gains made through that speech therapy you endured as a kid. "Be gone from my sight oh lowest of the low," he would exhale dismissively "and I shall let you live with execute access to these fine stored procedures that I have crafted from the very elements of the universe and the stars within that mere lowly mortals such as yourself could never understand." If, on the other hand, the DBA was feeling playful and you looked like you had a little too much spirit in the light of the flickering green fluorescents, he would grant you access to selected portions of the database in much the same way killer whales taunt and tease their prey in the moments before the kill. Yes, you had access to the database... but it was merely the setup for a cruel ruse. What you thought was a simple construction of a CRUD style stored procedure was in fact a noose of arcane syntax and perverted distortions to set theory slowly tightening around your neck. Experienced co-workers would look upon your feverish gaze of SQL coding in a worried pitying stare for it was only after you had constructed what you perceived as a minor miracle of well indexed Cartesian beauty (whose elegance was surely going to elicit religious ceremony from those who observed it) that the DBA would tear it all away from you in one brisk belittling put down. The exact words are lost on you almost immediately as the DBA proceeds to enumerate the many faults that infest your creation to its core. Your entire body goes numb. Your brain, unable to focus on the immediate loss, reminisces in a emotional stupor that tattered remains of the life that you used to know. The respect that other devs had given you. The small smirk of playful possibility the attractive guy / girl in marketing gave you a few hours before. The honest belief that your could in some small way live up to your parents expectations of being a respected professional. All gone. Lost forever. This was not a world of peers and mutual respect. This was a world of restricted privilege and inherited birth rights. Table schemas were never touched directly and rarely seen in person. Indexes were akin to magic incantations that only passed the lips of people whose grizzled collection of scars and matted hair could withstand the consequences. The hallowed gateway to all of this was enshrined in the sharp metallic structure of stored procedures. They dictated performance. They dictated protocol. They dictated the exact manner in which all applications would need to bow towards the all seeing and all knowing gods of data: The DBAs. Living in this reality for so long left me unable to spot the wavering edges of the illusion presented before me. The ancient curses surrounding the evils of different tiers changing at different times never seem to show up in the ways the old ones spoke of. Instead of a torrent of changing DB systems and continual refactoring of all tiers in an effort to extract the very last drip of performance, events tended to peak and trough. Long periods of calm would happen in which everyone seemed to almost hold their breath in the hope that if they didn't touch anything then it wouldn't break. And then, every once in a while, change would erupt from the business requirements and wash across all the tiers at once. Suddenly people were facing daemons that the ancients never mentioned. Panicked masses running through the streets crying out questions like "How do keep the version of the DB inline with the version of code?", "How do we test each version?" and "How do we roll out versions side by side?". I had grown up thinking that the only way that SQL could execute efficiently was via the protection and guidance provided by stored procedures. Without the stored procedure, what was there? A lawless town of missed cache hits, fumbling predicates and roaming hordes of developers feasting at the gory remains of relational theory? As it turns out, probably not: http://www.databasejournal.com/features/mysql/article.php/3525581 :) |
|
||||
|
|