Jekyll2022-01-18T20:05:44-06:00https://luddites.me/atom.xmlпоходы на моем столеHiking My Desknibbling at my own words2022-01-18T00:00:00-06:002022-01-18T00:00:00-06:00https://luddites.me/nibbling-at-my-own-words<h2 id="and-thus-as-i-repeat-the-refrain">and thus as i repeat the refrain</h2>
<p>A little over a year ago, I had a burst of energy and a vision to <a href="https://luddites.me/2020-10-04-blogging-to-the-oldies/">rewrite my blog</a>. In my mind, I envisioned having a website that I could easily change. I would have complete control over the code behind the site, and it would be effortless to author new content.</p>
<p>As you can see from the dearth of content between then and now, that plan did not so much work as wither. I obsessed over the template and the build system, spending countless hours writing and rewriting the code behind the site. I was caught in a recursive loop of refactoring from which no greater refactoring could be conceived. I like tools like Gatsby, and I enjoy the exercise of writing code as I write other things; but I found myself in an inextricably knotted mat of dead ends and loose threads. The site never looked exactly the way I wanted it to look, so it became impossible to simply write for the sake of writing. I would lose time and energy, leaving the project for weeks or months only to return and find that the whole toolset and ecosystem had changed beneath my feet. I would spend long nights simply building and rebuilding the site just to get it to work the same way today that it worked the last time I had touched it.</p>
<p>A few months ago, I needed to write some content for work, and it occurred to me that a <a href="https://jupyter.org">Juptyer notebook</a> would be a nice, neat and uncomplicated way to write a bit of code and tad of content, then see the result rendered as a website that anyone could view. What if I could use a Jupyter notebook for my entire blog? A few minutes of searching revealed the solution: <a href="https://fastpages.fast.ai">Fastpages</a>.</p>
<p>I abandoned my <a href="https://github.com/crfroehlich/blog">old codebase</a> and moved everything into the <a href="https://github.com/crfroehlich/cellar">cellar</a>. Fastpages relies on Jekyll, which was the one technology I had explicitly declared would not be part of my solution. Yet, here we are.</p>
<p>This site does not look exactly the way I want it to look (yet or perhaps never); the tools that build the site are essentially a black box that I rely on with little or no desire to understand the inner workings at any level of depth. Nothing about this setup is perfect, but it’s better than that because it does what I need it to do reliably and quickly.</p>
<p>Almost and precisely zero of the requirements I set for myself a year ago materialized into actual parts of <a href="https://luddites.me">my blog</a>. You might even go so far to say that everything I wrote about the future of my blogging was wrong. You might be right. I might be wrong.</p>
<p>Finishing the race is its own satisfaction–no matter that I started a triathlon and finished a biathlon. This to me is one of the persistent joys of writing (be it code or poetry), that we can stumble through the darkness and yet still find our way through the darkness. While I may throw away most of what I write, I lose little. I can look at my past naivete and be comfortable in my wrongness. After all, it’s a place where I spend a lot of time, so it’s nice to be comfortable while there.</p>
<p>Here’s hoping I continue past my own obstacles and. just. write.</p>CFand thus as i repeat the refrainYou’re Not a Dick, and So Can I2022-01-15T00:00:00-06:002022-01-15T00:00:00-06:00https://luddites.me/you're-not-a-dick-and-so-can-i<p>Already half way (or more) through my brief consciousness of this earth, and I still cannot quite wrap my head around what I must now conclude to be normative or perhaps even inevitable behavior. I see this exchange (or one very much like it) played out almost every day of my life. Imagine two people introducing themselves. Social context does not matter, neither does the medium–this could be in person or on a video call or by email.</p>
<blockquote>
<p>“Hi, my name is Richard.”<br />
“Nice to meet you, Dick. My name is…”</p>
</blockquote>
<p>Were <code class="language-plaintext highlighter-rouge">dick</code> red and <code class="language-plaintext highlighter-rouge">richard</code> black, I could make a tidy fortune at roulette. It’s the near mathematical certainy of this outcome that is perhaps so perplexing to me. If you have followed the gentle ebb and flow of my musings and so far not apprehended the conundrum, that is no doubt further evidence in support of the argument for socio-normative behavior. Yet, still.</p>
<p>The simplicity of it confounds me. Richard presents their name, “Richard”. Person B, without any hesitation, immediately begins speaking back to Richard using a name that is not “Richard”. To me, it seems intuitively obvious that when I present some other person with a name and an assignment for that name, e.g. “Hello, here is this name ‘Richard’, and I assign this name to myself by way of saying ‘My name is Richard’. So you now have a covenient label by which to refer to me, specifically, and distinguish that reference from all the other things in this room or the universe at large about which we might want to speak.” I posit that many (if not most) people would find an exchange like this somewhat untennable:</p>
<blockquote>
<p>“This wall needs to be painted viridian.”<br />
“Great, I’ll go get some green paint.”</p>
</blockquote>
<p>Generally, labels are not loosely interchangeable with each other and in the course of normal human interactions, we assume that we can rely on the shared vocabulary and grammar of our peers to converse. We might disgree about whether or not this particular color is viridian, but we generally agree that having colors named things like viridian and vermilion can be useful when it comes to talking about what to paint walls or cars or houses. I think it then follows that if I were to ask for a wall to be painted viridian and that if that wall were painted some other not-viridian color, that I would be in the right to say the job has not been completed.</p>
<p>There is, of course, the very nuanced issue of nicknames and diminutives. For example, a common familiar name for “Alexander”, “Alexandra” is the gender neutral “Sasha”; however, it is reserved for use by close family and friends, and not a name that would be used in any professional context without explicit permission. Permission in the form of, “Hi, my name is Alexander; but you may call me Sasha.” Similarly, in many languages the second person pronoun “you” is biforcated into formal and informal words (think “thee” and “thou” of old english), never the two streams to be crossed. In my opinion, english suffers greatly from the convergance of all second person (singular, plural, informal and formal) into the single obsequious “you”, but that is a rant for another time and place.</p>
<p>So it is. While I have more or less resigned myself to a fate of forever being called “Chris”; that no matter how many times I present my actual name “Christopher”, the echos always whisper “Chris”; I still do not like it. I often wonder what it is (if anything) that passes through someone’s mind when they hear me say my name, “Christopher” and then immediately switch to a diminutive.</p>
<ul>
<li>Did they mishear me pronounce my name?</li>
<li>Are they mispronouncing my name accidentally?</li>
<li>Have they confused me with someone else?</li>
<li>Were they explicitly taught to truncate names?</li>
<li>Are they trying to assert some kind of dominance by butchering my name?</li>
<li>Is it a power play to see if they will be corrected?</li>
<li>Are they just being intentionally rude?</li>
<li>Do they somehow not realize what they are doing?</li>
</ul>
<p>It just boggles. I don’t know if I subscribe to any generalizations about the nature of humanity, but I do think that most people will not go out of their way to hurt other people. I suspect that most of the day to day injuries we experience are a result of lethargy. When trash and recycling containers are ubiqutous, most people do not litter most of the time. I know of myself that I will sometimes (perhaps even frequently) succumb to the morally dubious paths–on those cold or rainy days, sometimes the tempation to leave the shopping cart behind the car instead of putting it back correctly overwhelms me.</p>
<p>As someone who has difficulty remembering names, I spend a lot of time thinking about introductions. Repeating someone’s name aloud helps it stick a little, so I find myself repeating this pattern:</p>
<blockquote>
<p>“I’m Javier.”<br />
“Javier? Did you say, Javier? Nice to meet you Javier.”</p>
</blockquote>
<p>So, it is perhaps my hyper-attention to these little moments that raises my awareness of and sensitivity to these abberations in patterns that may be imperciptible to others. I do not know.</p>
<p>All I can say with any certainty is that I pay close attention to how people introduce themselves and how we name each other. How a person sees themself, identifies and names themself, opens the doorway ever so slightly into a view of their world, from their perspective. I think it valuable to be thoughtful and delibrate about the words we use. Flowers with beautiful petals will always be beautiful in themselves, but it’s not nothing to know that they’re roses either.</p>CFAlready half way (or more) through my brief consciousness of this earth, and I still cannot quite wrap my head around what I must now conclude to be normative or perhaps even inevitable behavior. I see this exchange (or one very much like it) played out almost every day of my life. Imagine two people introducing themselves. Social context does not matter, neither does the medium–this could be in person or on a video call or by email.Blogging to the Oldies2020-10-04T00:00:00-05:002020-10-04T00:00:00-05:00https://luddites.me/blogging-to-the-oldies<h2 id="reality-meet-opportunity">Reality, Meet Opportunity</h2>
<p>For quite a while now, I have wanted to update my blog, do some more writing (both personally and professionally) and generally flex some unused muscles a bit. Fortuna often has sadistic tendencies as some can attest. Consider the recent toppling of the <a href="https://www.sec.gov/litigation/litreleases/2020/lr24905.htm">NS8 empire</a> <a href="https://www.wsj.com/articles/former-head-of-cyber-fraud-detection-startup-ns8-arrested-on-fraud-charges-11600469207">1</a>, <a href="https://www.pacermonitor.com/public/case/36301258/United_States_Securities_and_Exchange_Commission_v_Rogas_et_al">2</a>, <a href="https://www.forbes.com/sites/davidjeans/2020/09/18/how-a-cyber-fraud-company-ceo-raised-123-million-in-months---and-got-arrested-for-fraud/amp">3</a>, <a href="https://www.reviewjournal.com/business/sec-charges-former-ceo-of-tech-company-with-fraud-2123503/">4</a>, <a href="https://www.justice.gov/usao-sdny/press-release/file/1317641/download">5</a>, <a href="https://www.linkedin.com/pulse/ns8-demonstrates-how-employment-data-can-valuable-richard-stiennon">6</a> and a <a href="https://www.formds.com/issuers/ns8-inc">great fall of nepotism</a> with <a href="https://www.justice.gov/usao/justice-101/preliminary-hearing">recent developments</a> and <a href="https://www.reviewjournal.com/business/laid-off-workers-sue-tech-company-citing-lack-of-advance-notice-2124501/">former employee actions</a>. So many links to criminal conspiracy to defraud and so little daylight; regardless, I have had more than a little time to navel gaze in recent weeks.</p>
<p>I’ve long been frustrated by the available tools for blogging. Some of these goals compete with each other and some are onerous due to costs–I want as much of my platform to be free (both as in beer and as in speech) as possible <em>and</em> I want as much control over my platform as possible <em>and</em> I want to have features like commenting and search and analytics <em>and</em> there can be no ads and the word <em>Jekyll</em> may not be invoked. I have an old <a href="https://hiking.luddites.me">Blogger site</a>, which I desperately want to retire; and I have a <a href="https://medium.com/@christopher.r.froehlich">Medium site</a> which I am increasingly frustrated with: from the inability to post articles in the past to Mediums idiotic approach to monetization–what was initially cool about medium is no longer interesting to me.</p>
<p>So I set out to figure out how to create the blog platform you, dear reader, are currently (hopefully) enjoying.</p>
<h3 id="goals">Goals</h3>
<p>Broadly speaking, I want to be able to meet these objectives:</p>
<ul>
<li>Easy to add new posts</li>
<li>Easy to update existing posts</li>
<li>Keep revision history of edits</li>
<li>Blog is searchable</li>
<li>Commenting in some form is possible, and comments are stored in my control</li>
<li>No ads (at least for now)</li>
<li>Service is free for me to host my content and free for consumers</li>
<li>I can more or less change anything about the blog at whim</li>
<li>Fast to manage</li>
</ul>
<h3 id="non-starters">Non-starters</h3>
<p>I considered a number of options, and I won’t go too deep into the pros and cons so much as leave breadcrumbs for others to follow (in no particular order):</p>
<ol>
<li><a href="https://medium.com">Medium</a>: it looks nice, but I have to surrender too much control. It’s not free as in speech or free as in lattes.</li>
<li><a href="https://blogger.com">Blogger</a>: it looks dated. It does most of what I need, but it’s slow to manage and cumbersome to maintain.</li>
<li><a href="https://ghost.org">Ghost</a>: it used to be a nice competitor to Medium, but the target audience for users no longer includes me. It’s free to self-host, but non-trivial to manage.</li>
<li>All other self-hosted solutions (Ghost included): while I <em>can</em> run anything on my local systems, I don’t want to depend on my personal equipment to run my site and I don’t want to have to deal with security (although services like <a href="https://ngrok.com">Ngrok</a> and <a href="https://pagekite.net/">Pagekite</a> are awesome and definitely worth your time).</li>
<li>Cloud hosting options are a mixed bag when looking for free. You can get lots of usage out of <a href="https://azure.com">Azure</a> on the initial free options, but eventually you have to pay.</li>
<li>WordPress/Drupal/etc. Will never use; will not investigate.</li>
</ol>
<h2 id="solution">Solution</h2>
<p>One “blog” concept that I’ve always liked is by <a href="https://twitter.com/raganwald">@raganwald</a> is his use of <a href="https://github.com/raganwald/raganwald.github.com/tree/master/_posts">Github</a> for organizing content. I have long considered this approach as it checks off a lot of boxes:</p>
<ul class="task-list">
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Complete control</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Free as in latkes and free as in peaceful protests</li>
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />It’s git, so it’s all under control</li>
</ul>
<p>The perceived negatives I have had in the past seem to be less of an issue these days with the emergence of a few factors (some relatively new, some a bit older):</p>
<ul>
<li><a href="https://pages.github.com/">Github Pages</a>: a free static content website based on the content of a branch of your repository. Commonly the <code class="language-plaintext highlighter-rouge">gh-pages</code> branch, which is how this blog is served.</li>
<li><a href="https://github.com/features/actions">Github Actions</a>: Manage your updates to Github Pages automatically</li>
<li><a href="https://github.com/features/codespaces">Github Codespaces</a>: Everything you need to manage your site, in your browser. This is a very nice to have–you can do this anywhere/anytime already with other tools.</li>
<li><a href="https://www.gatsbyjs.com/">GatsbyJs</a>: A pretty slick static site generator based on React. Lots of extensions and pluggability.</li>
<li><a href="https://github.com/utterance/utterances">Comments</a>: Using a tool called Utterances, which is just a convenient wrapper around Github Issues–commenting is free and easy and completely under my control.</li>
<li><a href="https://www.algolia.com/">Search</a>: This is the only 3rd party piece that I cannot take and move just anywhere, but it’s free as in pancakes for my purposes, so I’ll content with it for now and/or until I need something better.</li>
</ul>
<h3 id="getting-there">Getting There</h3>
<p>I did some basic soul googling for <code class="language-plaintext highlighter-rouge">blog github pages -jekyll</code> and quickly found <a href="https://codesandtags.github.io/blog/creating-my-blog-with-gatsby-and-github-pages">Creating my blog with Gatsby and Github Pages</a>, which was more than enough to get me going. I explored a variety of <a href="https://www.gatsbyjs.com/starters/?v=2">Gatsby Templates</a> (once I had decided that Gatsby would meet all my needs) and I picked the <a href="https://www.gatsbyjs.com/starters/hasura/gatsby-gitbook-starter/">Gitbook Starter</a> template as a base. There were a variety of things I needed to change–most notably the logic for generating the sidebar tree, which required comparing the <a href="https://github.com/hasura/gatsby-gitbook-starter">template repo</a> with the <a href="https://github.com/hasura/learn-graphql/tree/master/tutorials/graphql/intro-graphql/tutorial-site">demo repo</a>.</p>
<p>Most of my time was occupied fixing annoyances–I spent more than a few hours wrestling with the <a href="https://github.com/tschaub/gh-pages">gh-pages</a> module that I use for automating deploys to, you guessed it, Github Pages. The production build process for Gatsby is much slower than I would like, which is especially annoying in the early phases of development when you’re making lots of minor tweaks and changes. Combine that with trying to guarantee that I cache bust my site with new deploys, the general speed of build+deploy, local caching issues, remote caching issues–and I easily spent most of a day refreshing my browser in a state of uncertainty as to whether I was testing the right version of my code. Once I generally worked through my self-inflicted CI/CD pipeline issues, I am very satisfied with what I was able to throw together over a day and a half.</p>
<h2 id="outstanding-concerns">Outstanding Concerns</h2>
<p>One of the fun bits of doing all this work is that it’s a beautiful combination of development work, writing and designing–all of which I love. I get to keep polishing my dev chops as I work through my backlog of blog posts to migrate as well as explore new technologies and solutions to my own little set of concerns. I’ve historically struggled to find a development problem that aligns with my personal interests, and for the first time I feel like I have the beginnings of a solution here.</p>
<p>Still, much remains todo if I want to consider this feature complete:</p>
<ul>
<li>Add analytics so I can measure traffic.</li>
<li>Some form of management for comments.</li>
<li>Find alternate ways to authenticate for comments so not everyone needs to have a Github account to comment.</li>
<li>Fix some rendering issues on page load.</li>
<li>Tagging and other basic “bloggy” features.</li>
<li>Migrate all my old content over.</li>
<li>Refactor the whole thing to TypeScript, because {reasons}.</li>
<li>Refactor the whole thing from TypeScript to Rust, because…why not?</li>
</ul>
<p>If any of this has been interesting, please let me know in the comments or in <a href="https://github.com/crfroehlich/blog">the code, which is the blog, which is the code, which…</a>!</p>CFReality, Meet Opportunity For quite a while now, I have wanted to update my blog, do some more writing (both personally and professionally) and generally flex some unused muscles a bit. Fortuna often has sadistic tendencies as some can attest. Consider the recent toppling of the NS8 empire 1, 2, 3, 4, 5, 6 and a great fall of nepotism with recent developments and former employee actions. So many links to criminal conspiracy to defraud and so little daylight; regardless, I have had more than a little time to navel gaze in recent weeks. I’ve long been frustrated by the available tools for blogging. Some of these goals compete with each other and some are onerous due to costs–I want as much of my platform to be free (both as in beer and as in speech) as possible and I want as much control over my platform as possible and I want to have features like commenting and search and analytics and there can be no ads and the word Jekyll may not be invoked. I have an old Blogger site, which I desperately want to retire; and I have a Medium site which I am increasingly frustrated with: from the inability to post articles in the past to Mediums idiotic approach to monetization–what was initially cool about medium is no longer interesting to me. So I set out to figure out how to create the blog platform you, dear reader, are currently (hopefully) enjoying. Goals Broadly speaking, I want to be able to meet these objectives: Easy to add new posts Easy to update existing posts Keep revision history of edits Blog is searchable Commenting in some form is possible, and comments are stored in my control No ads (at least for now) Service is free for me to host my content and free for consumers I can more or less change anything about the blog at whim Fast to manage Non-starters I considered a number of options, and I won’t go too deep into the pros and cons so much as leave breadcrumbs for others to follow (in no particular order): Medium: it looks nice, but I have to surrender too much control. It’s not free as in speech or free as in lattes. Blogger: it looks dated. It does most of what I need, but it’s slow to manage and cumbersome to maintain. Ghost: it used to be a nice competitor to Medium, but the target audience for users no longer includes me. It’s free to self-host, but non-trivial to manage. All other self-hosted solutions (Ghost included): while I can run anything on my local systems, I don’t want to depend on my personal equipment to run my site and I don’t want to have to deal with security (although services like Ngrok and Pagekite are awesome and definitely worth your time). Cloud hosting options are a mixed bag when looking for free. You can get lots of usage out of Azure on the initial free options, but eventually you have to pay. WordPress/Drupal/etc. Will never use; will not investigate. Solution One “blog” concept that I’ve always liked is by @raganwald is his use of Github for organizing content. I have long considered this approach as it checks off a lot of boxes: Complete control Free as in latkes and free as in peaceful protests It’s git, so it’s all under control The perceived negatives I have had in the past seem to be less of an issue these days with the emergence of a few factors (some relatively new, some a bit older): Github Pages: a free static content website based on the content of a branch of your repository. Commonly the gh-pages branch, which is how this blog is served. Github Actions: Manage your updates to Github Pages automatically Github Codespaces: Everything you need to manage your site, in your browser. This is a very nice to have–you can do this anywhere/anytime already with other tools. GatsbyJs: A pretty slick static site generator based on React. Lots of extensions and pluggability. Comments: Using a tool called Utterances, which is just a convenient wrapper around Github Issues–commenting is free and easy and completely under my control. Search: This is the only 3rd party piece that I cannot take and move just anywhere, but it’s free as in pancakes for my purposes, so I’ll content with it for now and/or until I need something better. Getting There I did some basic soul googling for blog github pages -jekyll and quickly found Creating my blog with Gatsby and Github Pages, which was more than enough to get me going. I explored a variety of Gatsby Templates (once I had decided that Gatsby would meet all my needs) and I picked the Gitbook Starter template as a base. There were a variety of things I needed to change–most notably the logic for generating the sidebar tree, which required comparing the template repo with the demo repo. Most of my time was occupied fixing annoyances–I spent more than a few hours wrestling with the gh-pages module that I use for automating deploys to, you guessed it, Github Pages. The production build process for Gatsby is much slower than I would like, which is especially annoying in the early phases of development when you’re making lots of minor tweaks and changes. Combine that with trying to guarantee that I cache bust my site with new deploys, the general speed of build+deploy, local caching issues, remote caching issues–and I easily spent most of a day refreshing my browser in a state of uncertainty as to whether I was testing the right version of my code. Once I generally worked through my self-inflicted CI/CD pipeline issues, I am very satisfied with what I was able to throw together over a day and a half. Outstanding Concerns One of the fun bits of doing all this work is that it’s a beautiful combination of development work, writing and designing–all of which I love. I get to keep polishing my dev chops as I work through my backlog of blog posts to migrate as well as explore new technologies and solutions to my own little set of concerns. I’ve historically struggled to find a development problem that aligns with my personal interests, and for the first time I feel like I have the beginnings of a solution here. Still, much remains todo if I want to consider this feature complete: Add analytics so I can measure traffic. Some form of management for comments. Find alternate ways to authenticate for comments so not everyone needs to have a Github account to comment. Fix some rendering issues on page load. Tagging and other basic “bloggy” features. Migrate all my old content over. Refactor the whole thing to TypeScript, because {reasons}. Refactor the whole thing from TypeScript to Rust, because…why not? If any of this has been interesting, please let me know in the comments or in the code, which is the blog, which is the code, which…!Oscar2020-09-30T00:00:00-05:002020-09-30T00:00:00-05:00https://luddites.me/oscar<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Words have been changed and characters rearranged to limit liability to the not guilty.
</code></pre></div></div>
<p>Every sixty minutes at seven minutes past the hour exactly, Oscar would run naked through the house. He always entered through the front door, streaked through the living room, raced down the hallway, dashed in and out of each room (bathrooms and closets included), ran a quick circle around the island in the kitchen and exited through the mudroom and out the garage. If the garage door were closed, Oscar would mash the button and jog in place until the door raised high enough to dart under.</p>
<p>While Oscar’s hourly run was in and of itself perplexing, what confused us even more was that not one of us had the faintest idea who was Oscar or whence he came. Did he visit other houses on our street? The pure oddity of our visitor left us in an unusual position. Customarily, it is not appropriate to approach a stranger’s house (be it or not a neighbor’s), knock upon the door and inquire about nude persons that may or may not be running through said person’s home.</p>
<blockquote>
<p>“Good afternoon, ma’am. I’m your neighbor from down the street, and…” <br />
“Oh, yes, ma’am. Number 312, yes.”<br />
“I’m sure you have seen me riding down the street. Yes, ma’am.” <br />
“Oh, no, ma’am — we don’t even play baseball. I don’t…” <br />
“Yes, ma’am, I see. I am very sorry about the window, but it really wasn’t…” <br />
“If I may, I will ask my mother to inquire around.” <br />
“Yes ma’am, integrity and responsibility are very important virtues for our young people, yes. As a matter of fact, I…” <br />
“Of course, ma’am. I could not agree more.” <br />
“Ma’am, the reason I came by is to ask if you have ever seen Oscar.” <br />
“Well, you see, ma’am, I really do not know. I only know that he runs naked through our house every day.” <br />
“Heaven forbid, ma’am. This is no prank…” <br />
“Please, I assure you, I had no such intention…” <br />
“Accept my apologies; I am sorry to have disturbed you.” <br />
“Yes, I will have my mother…” <br />
“Good day ma’am.”</p>
</blockquote>
<p>So you see, the question of asking about the neighborhood was itself quite out of the question. The next, most obvious approach was to try to follow Oscar and see where he went. Now, I do not know if you have ever tried to chase a naked, fully grown man with a seven foot long beard as he runs down the street in broad daylight, but the folks around here do not take kindly to it. Frankly, we didn’t much relish the idea either. It is one thing to blissfully, obliviously ignore a naked person streaking past and quite another thing entirely to try to unsee a couple of children chasing a naked, fully grown man with a seven foot beard.</p>
<p>If we were not going to interview the neighbors and if we were not going to chase a naked, four and a half foot tall, fully grown man with a seven foot beard, then the next best thing had to be to setup a stakeout. I would watch the front door and keep a clear view up and down the street. Isaac would set up base at the top of the street and Jordan would keep watch from the bottom of the street. You will now be forgiven if you thought this a perfectly good and reasonable plan, for none of us expected to see Oscar floating gently down toward the ground, a parachute the color of the setting sun holding him aloft as his freely dangling loins taunted us with the ineffable and inscrutable ceremony of Oscar’s visit. No one expects a naked, four and a half foot tall, fully grown man with flowing red hair and a seven foot beard to parachute into their driveway, release and then run through every nook and cranny of their house. Indeed, faced with the blur of that buck naked, birthday suit clad, man coursing through our house, we were still caught by the shock of the parachute entrance to react in any significant way before Oscar was already tearing out the garage toward the end of the street. Curiously, as we watched him slowly fade into the horizon, the wind picked up and before I had a chance to snap my fingers the parachute caught the breeze and carried itself after Oscar down the street.</p>
<p>As you might imagine, my brothers and I were most puzzled. Did Oscar always parachute down? That seemed highly improbable — surely it would take more than an hour to get back into a plane, take off, circle overhead and parachute back down again. There was only one thing for it: stay in position and wait sixty minutes. We decided to take turns at the front of the house for the next round. I drew the short straw, so the first watch was mine. At five minutes past the hour, I would blow a whistle to call my brothers out and we would all fall into position. So it was that at 7:05 in the evening, the three of us resumed our triangular formation to await Oscar. The seconds dripped off our foreheads like icicles sweating. I was focused with such intensity on my watch that the explosion in the middle of the street nearly snatched the life right out of me. At 7:06:30 the sewer lid in the middle of the street shot straight up into the air and Oscar tumbled forward in a pop-off suit. Quick as a jackrabbit, he discarded the suit into the sewer just as the cover landed perfectly back in place. Thus we were left staring at the massive, yellow smiley face tattooed on Oscar’s posterior as that naked, four and a half foot, fully grown man with flowing red hair and a seven foot beard flashed in and out of our house toward the setting sun.</p>
<p>We had time for one more watch before darkness fell. We briefly discussed positioning a camera through the night to capture Oscar’s various entrances but just as quickly decided we had already seen enough of naked Oscar and did not need to further stain our memories with yet more images of Oscar’s pride. As before, we waited until the appointed time, and at 8:05 that evening resumed our watch in anticipation of Oscar’s return. We stood facing the street, no longer attempting to hide, standing in plain view in the middle of the driveway. Were it not for Isaac’s excellent hearing and quick wit, we might have missed Oscar’s entrance entirely. At Isaac’s signal, we swiftly turned around to face the house just in time to see Oscar release his grip on a hang glider and land nimbly on the roof, from which he performed a flawless backflip, his neatly braided armpit hair swinging like dreadlocks, landing before the front door and streaking inside.</p>
<p>There comes a point in the day when one can take no more of a naked, four and a half foot tall, full grown man with flowing red hair, a seven foot beard, a giant smiley face butt tattoo and armpit hair dreadlocks. After all, he would be lapping through our house every hour, all night long. We had given up closing bedroom doors long ago. Oscar could pick a lock in less than a second. Deadbolts didn’t stop him. Barricading the door slowed him down not in the least. In the beginning, once it had become clear that Oscar was an unstoppable force, my parents had begun trying to solicit advice from friends and family — but try as they might, they could not find a way to broach the subject of the naked man. My parents tried hosting dinner parties in a more casual effort to allow the subject of Oscar to occur organically in conversation, but Oscar’s hourly runs would prove as frictionless as my mother’s desserts find their way from table to tummy — Oscar could loop through the house, setting foot in every room, unseen and unheard by all except we privileged few with tickets to the never ending show. Gradually, we would come to accept that Oscar’s loins were intended for an audience of us and us alone.</p>
<p>My parents tried all the usual sorts of things that simple, hardworking, market fearing adults should try. They called the police.</p>
<blockquote>
<p>“Yes, officer, fourteen inch toenails painted neon green with glitter.” <br />
“No, officer, I assure you — this is not a joke.”</p>
</blockquote>
<p>They called the city newspapers.</p>
<blockquote>
<p>“Yes, tugboat earrings in both ears — quite large. The tugboats make a horn sound as he runs.” <br />
“Well, no, we don’t have any pictures…the man is stark naked. If you could just come by the house…” <br />
“What time? Any hour of the day; just be here at seven past the hour.” <br />
“What? Yes, of course I am serious!”</p>
</blockquote>
<p>They called animal control.</p>
<blockquote>
<p>“Well, no, he is not technically an animal himself, but he does run with a gerbil in each hand.” <br />
“Well the gerbils look quite distressed!” <br />
“Their squeaks sound most concerned.” <br />
“I assure you that being swung about in the hands of a naked man is not among the things Mother Nature provisioned for a gerbil’s recreational activities.”</p>
</blockquote>
<p>They called the fire department.</p>
<blockquote>
<p>“No sir, nothing is burning. Yet. Not at this exact moment.” <br />
“Well, you see, the back of his neck, you see. Erm. His neck hairs to be precise. Well, the back of his neck is always smoking and the hairs are singed you see.” <br />
“Something is burning them.” <br />
“Well, as I said, not at this exact moment, but if you come by in just thirty minutes, I am sure you will see the smoke.” <br />
“No, I am not threatening to start a fire!”</p>
</blockquote>
<p>They called the FBI.</p>
<blockquote>
<p>“I see. You’ve already heard about us, eh?” <br />
“Nothing you can do? Nothing at all? Can’t even take a message, eh? Would just get thrown away as soon as I hang up, you say?” <br />
“Would it make any difference to know that he has tiny tattoos of the Russian flag above his nipples?” <br />
“None whatsoever, eh…”</p>
</blockquote>
<p>At that my father gave up hope. For a time, my mother carried on. She called the local churches, the banks, the grocery stores. She called plumbers and electricians and contractors. She called the Red Cross, Amnesty International, the UN and the WHO. I do believe she called every non-residential entity with a phone number before finally collapsing against the cold, hard, unrelenting truth: Oscar’s naughty bits were inextricably intertwined with our lives.</p>
<p>My parents were nothing if not rational creatures, disposed to dispensing healthy portions of the scientific method at every opportunity (and to them, moments do not exist that are not opportune). Logically, if we could not rely upon anyone else, then from beneath our own bootstraps we must emerge prepared to do battle. Gods bless them, they did try so many things. If I recall correctly, my mother had the first idea: equip each of us with solar eclipse glasses and turn out the lights before Oscar’s next run. Mother handed out the glasses and we sat wrapped in the comforting embrace of darkness, eyes closed behind thick, dark lenses with the quiet evening holding vigil around us. Darkness, sweet and absolute, suddenly abandoned us without warning as the light of a thousand flares roared to raging life around the house, bringing Oscar’s frank and beans into perfect clarity and focus as he flitted gracefully, rapidly through the house. In the dark of the evenings, my father tried cutting the power to the house. Naturally, Oscar persisted, his whole body wrapped in a complex web of glow sticks. At that, my brothers and I did begin a short lived philosophical discussion on whether or no the glow sticks constituted a form of clothing; but we quickly tired of the question and are happy to defer it to consideration by future generations.</p>
<p>Among all the curiosities that surround Oscar: his arrival, appearance and routine, the simplest to explain (and not without coincidence the first question often asked of this simple narrative) is how we came to know his name; and for this we have but Oscar to thank, for every time Oscar opened the front door, he proclaimed in a sing-song voice “Oscar’s back” with the “ack” extended in a lilting sort of way, extended but not entirely detached from the “b” of its birth — the way a mother might soothe a infant on her return: all is well, worry not, sanity and security are restored. The answers to most other questions remain shrink wrapped in enigmas: how and where does he sleep? Does he have a family? What does he do each hour for the 58½ minutes not spent inside our house? How does he keep this up, every single hour of every single day for months if not years on end? What happens when he gets sick? Has he ever been late? Where did he come from? And why? Why? Why — by the unwritten, sacred names of all the unspoken holiness around us — why?</p>
<p>As it does, time passed. Like a sudden burst of sunlight severing the grip of an icicle from the roof, an idea smashed into my consciousness with the same abruptness as Oscar bursting through the doorway: why not ask him? For reasons that will soon clarify as they crystalize: attempting to start a conversation with Oscar proved slightly more difficult than my confidence in the idea suggested. One Saturday morning, as Oscar entered the living room, I braced myself for the unthinkable and managed to release a whispery “Are you hungry?”, which only barely managed to escape my lips before Oscar reached the garage. Each conversation felt as a stained glass window being assembled from its shattered fragments. Our first dialog differed little from the rest except insofar as it was the end of the evitable.</p>
<blockquote>
<p>06:07 — Are you hungry?</p>
</blockquote>
<blockquote>
<p>07:07- Yep.</p>
</blockquote>
<blockquote>
<p>08:07 — Would you like a sandwich?</p>
</blockquote>
<blockquote>
<p>09:07 - Please.</p>
</blockquote>
<blockquote>
<p>10:07 — What kind of sandwich?</p>
</blockquote>
<blockquote>
<p>11:07 — Tuna… <br />
12:07 — …fish… <br />
13:07 — …no… <br />
14:07 — …pickles.</p>
</blockquote>
<p>At 3:07 in the afternoon, a tuna fish sandwich, on toasted rye bread, lounged upon the kitchen counter, waiting with a diagonal come hither slice down the middle for Oscar to return. Oscar took the sandwich and at 4:07 said “Thanks” as he passed. From that day forward, I left a tuna sandwich on the kitchen counter in the afternoons. Our conversations continued, Oscar replying a word or two per hour.</p>
<p>I asked:</p>
<blockquote>
<p>“Do you enjoy this?”</p>
</blockquote>
<blockquote>
<p>“This is…” <br />
“…the job…” <br />
“…I was…” <br />
“…born…” <br />
“…to do.”</p>
</blockquote>
<blockquote>
<p>“Is the pay good?”</p>
</blockquote>
<blockquote>
<p>“Decent…” <br />
“…Has per diem…” <br />
“…Benefits…” <br />
“…Travel.”</p>
</blockquote>
<blockquote>
<p>“When did you start?”</p>
</blockquote>
<blockquote>
<p>“A few…” <br />
“…years ago.”</p>
</blockquote>
<blockquote>
<p>“What made you get into this line of work?”</p>
</blockquote>
<blockquote>
<p>“Great…” <br />
“…exercise…” <br />
“…Meet new…” <br />
“…people…” <br />
“…See new…” <br />
“…places.”</p>
</blockquote>
<p>So the conversations went for days or weeks, until (quite unexpectedly) I stumbled upon the question I should have asked at the very beginning. “So. Um. Oscar? So, why our house?” I paused, “I mean, this is great and all — don’t get me wrong — the gerbils really close the deal…but why choose to do this in our home?”</p>
<p>Oscar skidded to a halt in mid stride. He turned to face me and walked slowly into the living room. “Eh,” he said, “Sorry. Say that one more time?” “Well,” I started, “I mean, of all the houses in all the world, why ours?” Oscar scratched his head for a moment, his red hair somehow still flowing, “Why. Hrm. Yes, why, indeed.” From where I cannot imagine, Oscar produced a thick stack of papers. “Let’s see,” he started, thumbing through the papers, “Kilpatricks. 312 Maple. Full service package. Ordered on February 2nd. Full year, paid in advance.” He looked up at me, “This is 312 Maple. You are the Kilpatricks, right?” “Oh, no” I said, “You want 313, just across the street.”</p>
<p>Inside a blur of motion, Oscar had a phone in his hand and he was furiously tapping away at the screen. He lifted the phone to his ear.</p>
<blockquote>
<p>“Jimmy, Oscar here. Looks like corporate screwed up again.” <br />
“Yeah, the DF-10.75 package with full service add-on. Yeah, it’s 313 Maple.” <br />
“Right, send the usual cleanup crew.” <br />
“Ok. I’ll update the protocol.” <br />
“Sounds good. I’ll start on them first thing tomorrow.”</p>
</blockquote>
<p>At that, Oscar hung up and the phone vanished as quickly as it had appeared. He flipped through the paperwork, located a page and held that with one hand while the other produced a tongue depressor in a sterile package, “Lick that and swab here please,” he said to me. Dazed, I unwrapped the small wooden device from the plastic, gave it a lick and spread the ooze on the form where he indicated. “I’m very sorry about all of this,” Oscar said as the paperwork and tongue depressor vanished. “You know how corporate gets sometimes. Mistakes happen. Big wigs don’t think like the little wigs, and so on.” Oscar looked around, almost with a hint of sadness — though it was difficult to interpret his emotions behind the layers of clown makeup on his face. “Again, so terribly sorry about all of this. Corporate will be in touch to tidy things up here, hog tie any loose ends, wrangle any problems, etcetera.” Oscar walked toward the front door and said without looking back, “Well, good luck with…well, whatever it is you people do here.” He was gone, and I have never seen him since.</p>
<p>My mother walked into the living room later that evening and observed me — I must have looked glazed over, sitting on the couch and staring at the wall. “What happened dear?” she asked. “I have no idea. I mean, Oscar’s gone. Seems he won’t be back. Something about a wrong address. I had to lick some paperwork. I guess he wanted the Kilpatricks from across the street.” The color fell off my mother’s face like a mortar dropping toward the earth, “The Kilpatricks moved away months ago, dear. A new family just moved in last week.”</p>
<p>“Oh. Oh, dear my. Oh dear,” I said. “Should we…? Should we, you know, say something?”</p>
<p>My mother mused for a moment before slowly composing herself and turning toward the kitchen, “No…No, I think it’s best they figure this out for themselves.”</p>CFWords have been changed and characters rearranged to limit liability to the not guilty. Every sixty minutes at seven minutes past the hour exactly, Oscar would run naked through the house. He always entered through the front door, streaked through the living room, raced down the hallway, dashed in and out of each room (bathrooms and closets included), ran a quick circle around the island in the kitchen and exited through the mudroom and out the garage. If the garage door were closed, Oscar would mash the button and jog in place until the door raised high enough to dart under. While Oscar’s hourly run was in and of itself perplexing, what confused us even more was that not one of us had the faintest idea who was Oscar or whence he came. Did he visit other houses on our street? The pure oddity of our visitor left us in an unusual position. Customarily, it is not appropriate to approach a stranger’s house (be it or not a neighbor’s), knock upon the door and inquire about nude persons that may or may not be running through said person’s home. “Good afternoon, ma’am. I’m your neighbor from down the street, and…” “Oh, yes, ma’am. Number 312, yes.” “I’m sure you have seen me riding down the street. Yes, ma’am.” “Oh, no, ma’am — we don’t even play baseball. I don’t…” “Yes, ma’am, I see. I am very sorry about the window, but it really wasn’t…” “If I may, I will ask my mother to inquire around.” “Yes ma’am, integrity and responsibility are very important virtues for our young people, yes. As a matter of fact, I…” “Of course, ma’am. I could not agree more.” “Ma’am, the reason I came by is to ask if you have ever seen Oscar.” “Well, you see, ma’am, I really do not know. I only know that he runs naked through our house every day.” “Heaven forbid, ma’am. This is no prank…” “Please, I assure you, I had no such intention…” “Accept my apologies; I am sorry to have disturbed you.” “Yes, I will have my mother…” “Good day ma’am.” So you see, the question of asking about the neighborhood was itself quite out of the question. The next, most obvious approach was to try to follow Oscar and see where he went. Now, I do not know if you have ever tried to chase a naked, fully grown man with a seven foot long beard as he runs down the street in broad daylight, but the folks around here do not take kindly to it. Frankly, we didn’t much relish the idea either. It is one thing to blissfully, obliviously ignore a naked person streaking past and quite another thing entirely to try to unsee a couple of children chasing a naked, fully grown man with a seven foot beard. If we were not going to interview the neighbors and if we were not going to chase a naked, four and a half foot tall, fully grown man with a seven foot beard, then the next best thing had to be to setup a stakeout. I would watch the front door and keep a clear view up and down the street. Isaac would set up base at the top of the street and Jordan would keep watch from the bottom of the street. You will now be forgiven if you thought this a perfectly good and reasonable plan, for none of us expected to see Oscar floating gently down toward the ground, a parachute the color of the setting sun holding him aloft as his freely dangling loins taunted us with the ineffable and inscrutable ceremony of Oscar’s visit. No one expects a naked, four and a half foot tall, fully grown man with flowing red hair and a seven foot beard to parachute into their driveway, release and then run through every nook and cranny of their house. Indeed, faced with the blur of that buck naked, birthday suit clad, man coursing through our house, we were still caught by the shock of the parachute entrance to react in any significant way before Oscar was already tearing out the garage toward the end of the street. Curiously, as we watched him slowly fade into the horizon, the wind picked up and before I had a chance to snap my fingers the parachute caught the breeze and carried itself after Oscar down the street. As you might imagine, my brothers and I were most puzzled. Did Oscar always parachute down? That seemed highly improbable — surely it would take more than an hour to get back into a plane, take off, circle overhead and parachute back down again. There was only one thing for it: stay in position and wait sixty minutes. We decided to take turns at the front of the house for the next round. I drew the short straw, so the first watch was mine. At five minutes past the hour, I would blow a whistle to call my brothers out and we would all fall into position. So it was that at 7:05 in the evening, the three of us resumed our triangular formation to await Oscar. The seconds dripped off our foreheads like icicles sweating. I was focused with such intensity on my watch that the explosion in the middle of the street nearly snatched the life right out of me. At 7:06:30 the sewer lid in the middle of the street shot straight up into the air and Oscar tumbled forward in a pop-off suit. Quick as a jackrabbit, he discarded the suit into the sewer just as the cover landed perfectly back in place. Thus we were left staring at the massive, yellow smiley face tattooed on Oscar’s posterior as that naked, four and a half foot, fully grown man with flowing red hair and a seven foot beard flashed in and out of our house toward the setting sun. We had time for one more watch before darkness fell. We briefly discussed positioning a camera through the night to capture Oscar’s various entrances but just as quickly decided we had already seen enough of naked Oscar and did not need to further stain our memories with yet more images of Oscar’s pride. As before, we waited until the appointed time, and at 8:05 that evening resumed our watch in anticipation of Oscar’s return. We stood facing the street, no longer attempting to hide, standing in plain view in the middle of the driveway. Were it not for Isaac’s excellent hearing and quick wit, we might have missed Oscar’s entrance entirely. At Isaac’s signal, we swiftly turned around to face the house just in time to see Oscar release his grip on a hang glider and land nimbly on the roof, from which he performed a flawless backflip, his neatly braided armpit hair swinging like dreadlocks, landing before the front door and streaking inside. There comes a point in the day when one can take no more of a naked, four and a half foot tall, full grown man with flowing red hair, a seven foot beard, a giant smiley face butt tattoo and armpit hair dreadlocks. After all, he would be lapping through our house every hour, all night long. We had given up closing bedroom doors long ago. Oscar could pick a lock in less than a second. Deadbolts didn’t stop him. Barricading the door slowed him down not in the least. In the beginning, once it had become clear that Oscar was an unstoppable force, my parents had begun trying to solicit advice from friends and family — but try as they might, they could not find a way to broach the subject of the naked man. My parents tried hosting dinner parties in a more casual effort to allow the subject of Oscar to occur organically in conversation, but Oscar’s hourly runs would prove as frictionless as my mother’s desserts find their way from table to tummy — Oscar could loop through the house, setting foot in every room, unseen and unheard by all except we privileged few with tickets to the never ending show. Gradually, we would come to accept that Oscar’s loins were intended for an audience of us and us alone. My parents tried all the usual sorts of things that simple, hardworking, market fearing adults should try. They called the police. “Yes, officer, fourteen inch toenails painted neon green with glitter.” “No, officer, I assure you — this is not a joke.” They called the city newspapers. “Yes, tugboat earrings in both ears — quite large. The tugboats make a horn sound as he runs.” “Well, no, we don’t have any pictures…the man is stark naked. If you could just come by the house…” “What time? Any hour of the day; just be here at seven past the hour.” “What? Yes, of course I am serious!” They called animal control. “Well, no, he is not technically an animal himself, but he does run with a gerbil in each hand.” “Well the gerbils look quite distressed!” “Their squeaks sound most concerned.” “I assure you that being swung about in the hands of a naked man is not among the things Mother Nature provisioned for a gerbil’s recreational activities.” They called the fire department. “No sir, nothing is burning. Yet. Not at this exact moment.” “Well, you see, the back of his neck, you see. Erm. His neck hairs to be precise. Well, the back of his neck is always smoking and the hairs are singed you see.” “Something is burning them.” “Well, as I said, not at this exact moment, but if you come by in just thirty minutes, I am sure you will see the smoke.” “No, I am not threatening to start a fire!” They called the FBI. “I see. You’ve already heard about us, eh?” “Nothing you can do? Nothing at all? Can’t even take a message, eh? Would just get thrown away as soon as I hang up, you say?” “Would it make any difference to know that he has tiny tattoos of the Russian flag above his nipples?” “None whatsoever, eh…” At that my father gave up hope. For a time, my mother carried on. She called the local churches, the banks, the grocery stores. She called plumbers and electricians and contractors. She called the Red Cross, Amnesty International, the UN and the WHO. I do believe she called every non-residential entity with a phone number before finally collapsing against the cold, hard, unrelenting truth: Oscar’s naughty bits were inextricably intertwined with our lives. My parents were nothing if not rational creatures, disposed to dispensing healthy portions of the scientific method at every opportunity (and to them, moments do not exist that are not opportune). Logically, if we could not rely upon anyone else, then from beneath our own bootstraps we must emerge prepared to do battle. Gods bless them, they did try so many things. If I recall correctly, my mother had the first idea: equip each of us with solar eclipse glasses and turn out the lights before Oscar’s next run. Mother handed out the glasses and we sat wrapped in the comforting embrace of darkness, eyes closed behind thick, dark lenses with the quiet evening holding vigil around us. Darkness, sweet and absolute, suddenly abandoned us without warning as the light of a thousand flares roared to raging life around the house, bringing Oscar’s frank and beans into perfect clarity and focus as he flitted gracefully, rapidly through the house. In the dark of the evenings, my father tried cutting the power to the house. Naturally, Oscar persisted, his whole body wrapped in a complex web of glow sticks. At that, my brothers and I did begin a short lived philosophical discussion on whether or no the glow sticks constituted a form of clothing; but we quickly tired of the question and are happy to defer it to consideration by future generations. Among all the curiosities that surround Oscar: his arrival, appearance and routine, the simplest to explain (and not without coincidence the first question often asked of this simple narrative) is how we came to know his name; and for this we have but Oscar to thank, for every time Oscar opened the front door, he proclaimed in a sing-song voice “Oscar’s back” with the “ack” extended in a lilting sort of way, extended but not entirely detached from the “b” of its birth — the way a mother might soothe a infant on her return: all is well, worry not, sanity and security are restored. The answers to most other questions remain shrink wrapped in enigmas: how and where does he sleep? Does he have a family? What does he do each hour for the 58½ minutes not spent inside our house? How does he keep this up, every single hour of every single day for months if not years on end? What happens when he gets sick? Has he ever been late? Where did he come from? And why? Why? Why — by the unwritten, sacred names of all the unspoken holiness around us — why? As it does, time passed. Like a sudden burst of sunlight severing the grip of an icicle from the roof, an idea smashed into my consciousness with the same abruptness as Oscar bursting through the doorway: why not ask him? For reasons that will soon clarify as they crystalize: attempting to start a conversation with Oscar proved slightly more difficult than my confidence in the idea suggested. One Saturday morning, as Oscar entered the living room, I braced myself for the unthinkable and managed to release a whispery “Are you hungry?”, which only barely managed to escape my lips before Oscar reached the garage. Each conversation felt as a stained glass window being assembled from its shattered fragments. Our first dialog differed little from the rest except insofar as it was the end of the evitable. 06:07 — Are you hungry?Code Generation Fail: An all the king’s horses tragedy2019-07-10T00:00:00-05:002019-07-10T00:00:00-05:00https://luddites.me/code-generation-fail-an-all-the-kings-horses-tragedy<p>Sometimes best intentions and good ole fashioned elbow grease are no match against the tyrannical fist of Reality. In my <a href="https://blog.luddites.me/2019/Code-Generation--Connecting-T4-to-Entity-Framework-Core">previous post</a>, I discussed some of the initial ambitions and achievements in my attempt to convert the Entity Framework Core + MVC project into a dynamically generated template using T4. The good news? T4 is a perfectly adequate way to generate code from templates. The bad news? There is no way to make this completely integrated in a pure .NET Core project. What does this mean, and why is this a problem?</p>
<h3 id="the-story">The Story</h3>
<p>Full disclosure: if you want something approximating a tldr; just skip to the next section.</p>
<p>For starters, the beauty of .NET Core is that I can compile and run a .NET Core app as easily on my Pixelbook as I can on my Windows devices. Getting a Core app up and running is just a <code class="language-plaintext highlighter-rouge">git clone</code> and <code class="language-plaintext highlighter-rouge">dotnet build</code> away! This simplicity is bruised, battered and beaten when we can’t run the transforms required to generate that code. In an ideal world, when I run <code class="language-plaintext highlighter-rouge">dotnet build</code> on the <a href="https://github.com/crfroehlich/autoEcMvc">AutoEcMvc</a> solution, the CodeGeneration project would compile and output the generated code into the AutoEcMvc project, which would then compile.</p>
<p>If this worked, the project could then drop seamlessly into Azure Pipelines which would automatically compile, test and deploy the project to my Azure app container! (It should be noted, I can still make this work, but it’s extra work that should be unnecessary).</p>
<p>Before I dive into the full autopsy of the deceased dream, I’ll explain my temporary solution and a few alternatives that I considered. For reasons that I’ll explain momentarily, the only way for even <code class="language-plaintext highlighter-rouge">msbuild</code> to work with a T4 project is to base the project on .NET Framework. In order to keep the T4 free from compilation issues (because Text Transformation happens <em>before</em> build, you can find yourself in a situation where the solution cannot compile without some minor hacking), I find it useful to keep the C# backing code for the templates in its own project. Unfortunately, the minimum project type that will work is .NET Standard (.NET Framework will also work, but the goal is to get as close to .NET Core as possible). For these reasons, my current solution’s solution has three projects, in build order: CodeGeneration (.NET Standard) > T4 (.NET Framework) > AutoEcMvc (.NET Core). CodeGeneration has only the utility functions required for the T4 project, which has only the metadata JSON and TT files, and AutoEcMvc has the user defined and generated content together. In another chapter, we’ll remove generated code from source control entirely, but for now I’m leaving it in place as a way to easily review and compare changes with the original project.</p>
<p>With this configuration, msbuild works seamlessly and I’ll update my Azure Pipeline to use msbuild and get my CI/CD plans back on track. I’m less than thrilled with having to throw <code class="language-plaintext highlighter-rouge">dotnet build</code> under the bus, but I’ve also spent more hours trying to crack this nut than I want — and I have whales need fryin’.</p>
<p>Before I completely abandoned the dream of a pure .NET Core solution, I explored a few options. There is <a href="https://github.com/daveaglick/Scripty">Scripty</a>, which “lets you use Roslyn-powered C# scripts for code generation. You can think of it as a scripted alternative to T4 templates.” While it sounds promising, the project hasn’t been updated in a while and seems to have outstanding issues with .NET Core. There is also the issue of documentation — any <a href="https://github.com/daveaglick/Scripty/issues/104">examples</a> of converting a T4 template to Scripty would be enormously helpful. Another promising option was <a href="https://github.com/atifaziz/t5">T5</a>, but no amount of tinkering prevailed against the ineffable and inscrutable refusal from Core to comply. Finally, there is <a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/page?view=aspnetcore-2.2&tabs=visual-studio">scaffolding</a> built into ASP.NET Core, but this is specific to Razor pages and not really a way to keep generated code in sync with metadata in the way I want to use it.</p>
<p>Absent other ideas, T4 still seems like the best approach without a major rewrite. I should note, my specific use of T4 is not terribly complicated, and it would be easy to ditch the templates altogether and simply write the code entirely in C#, but then it would cease to be generic and defeat the purpose of this little exercise. I may emerge from this experiment with a different opinion, but for now I’ll assume that T4 will remain the backbone of the project (until proven differently).</p>
<p>As always, this has been a long winded series of asides, a slow and drifting detour from the main point: T4 and .NET Core do not mix. The latter does not abide the former. There is hostility, vitriol and threats of malice aforethought between the two. How do I know this?</p>
<h3 id="my-current-solution">My Current “Solution”</h3>
<p>To understand the problems with trying to migrate T4 into .NET Core, I think it useful to explain the challenges presented in .NET Framework. There are two paths to text transformation.</p>
<p>The first is a developer convenience baked directly into Visual Studio since at least 2015. When you add a new <code class="language-plaintext highlighter-rouge">.tt</code> file into a project, VS immediately recognizes the template and offers a few convenience options for you as a developer: (1) whenever you save changes to the template, VS immediately runs text transform and the output is regenerated, (2) VS gives context menu options to manually transform (aka Run Custom Tool) and to debug the template, which will launch the debugger and allow you to set breakpoints anywhere, and (3) VS offers the option to run all transforms at the project/solution level. All of these features are hugely beneficial to the development of templates. But. And this is a big “but”.</p>
<p>The second is through <code class="language-plaintext highlighter-rouge">msbuild</code> which is what I would normally use in my CI pipeline. Msbuild launches text transform in a different context than VS, which means that the relative paths (e.g. <code class="language-plaintext highlighter-rouge">$(SolutionDir)</code> )that work in VS no longer work from msbuild.</p>
<p>In order to reconcile the two different behaviors, we need to make some changes to the <code class="language-plaintext highlighter-rouge">.csproj</code> file. Unfortunately, a project using .NET Framework has to be unloaded to be edited, then reloaded. Personally, I edit the project file directly in VS Code and let VS trigger the reload warning after I save changes. This is tedious, but it eliminates a few right-clicks.</p>
<p>If we start with a <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/T4/templates/imports.ttinclude">T4 import</a> that looks like this:</p>
<pre><code class="language-t4">#><#@ assembly name="$(SolutionDir)CodeGeneration\\bin\\netstandard2.0\\CodeGeneration.Dll"
#><#@ assembly name="$(SolutionDir)CodeGeneration\\bin\\netstandard2.0\\Newtonsoft.Json.Dll"
#><#@ import namespace="Newtonsoft.Json"
#><#@ import namespace="Newtonsoft.Json.Linq"
#><#@ import namespace="CodeGeneration" #>
</code></pre>
<p>we have two immediate problems. <code class="language-plaintext highlighter-rouge">$(SolutionDir)</code> cannot resolve outside of VS, and our 3rd party dependency on Newtonsoft will not be available from the <code class="language-plaintext highlighter-rouge">bin</code> directory. Starting with the latter, you can add this into a property group in the project file:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><PropertyGroup></span>
<span class="nt"><CopyLocalLockFileAssemblies></span>true<span class="nt"></CopyLocalLockFileAssemblies></span>
<span class="nt"></PropertyGroup></span>
</code></pre></div></div>
<p>Now, all reference binaries will be copied into the build output directory.</p>
<p>Next, the challenge of resolving the path to that output directory can be solved as well. A custom mapping is required, which is also possible with a little XML markup:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><PropertyGroup></span>
<span class="nt"><targetFolder></span>$(MSBuildProjectDirectory)\\..\\CodeGeneration\\bin\\netstandard2.0<span class="nt"></targetFolder></span>
<span class="nt"></PropertyGroup></span>
<span class="nt"><ItemGroup></span>
<span class="nt"><T4ParameterValues</span> <span class="na">Include=</span><span class="s">"targetFolder"</span><span class="nt">></span>
<span class="nt"><Value></span>$(targetFolder)<span class="nt"></Value></span>
<span class="nt"></T4ParameterValues></span>
<span class="nt"></ItemGroup></span>
</code></pre></div></div>
<p>Now, I can update the T4 imports to:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#><span class="err"><</span>#@ assembly name="$(targetFolder)\\CodeGeneration.Dll"
#><span class="err"><</span>#@ assembly name="$(targetFolder)\\Newtonsoft.Json.Dll"
</code></pre></div></div>
<p>And this will work seamlessly between VS and msbuild. There are a few other changes to make, but these are much more clearly documented elsewhere. For reference here, you also need:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><Import</span> <span class="na">Project=</span><span class="s">"$(MSBuildToolsPath)\\Microsoft.CSharp.targets"</span> <span class="nt">/></span>
<span class="nt"><PropertyGroup></span>
<span class="c"><!-- Get the Visual Studio version: --></span>
<span class="nt"><VisualStudioVersion</span> <span class="na">Condition=</span><span class="s">"'$(VisualStudioVersion)' == ''"</span><span class="nt">></span>16.0<span class="nt"></VisualStudioVersion></span>
<span class="c"><!-- Keep the next element all on one line: --></span>
<span class="nt"><VSToolsPath</span> <span class="na">Condition=</span><span class="s">"'$(VSToolsPath)' == ''"</span><span class="nt">></span>$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)<span class="nt"></VSToolsPath></span>
<span class="nt"></PropertyGroup></span>
<span class="c"><!-- This is the important line: --></span>
<span class="nt"><Import</span> <span class="na">Project=</span><span class="s">"$(VSToolsPath)\\TextTemplating\\Microsoft.TextTemplating.targets"</span> <span class="nt">/></span>
<span class="nt"><PropertyGroup></span>
<span class="nt"><TransformOnBuild></span>true<span class="nt"></TransformOnBuild></span>
<span class="nt"><OverwriteReadOnlyOutputFiles></span>true<span class="nt"></OverwriteReadOnlyOutputFiles></span>
<span class="nt"><TransformOutOfDateOnly></span>false<span class="nt"></TransformOutOfDateOnly></span>
<span class="nt"><RunPostBuildEvent></span>Always<span class="nt"></RunPostBuildEvent></span>
<span class="nt"></PropertyGroup></span>
</code></pre></div></div>
<p>This is the final glue to ensure that you get identical behavior when compiling the project from any direction.</p>
<p>Once all these pieces are in place, msbuild should <strong>just work</strong>.</p>
<p>References:</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/modeling/t4-parameter-directive?view=vs-2019">T4 Parameter Directive</a></li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-in-a-build-process?view=vs-2019#parameters">Pass build context data into the templates</a></li>
<li><a href="https://github.com/clariuslabs/TransformOnBuild">TransformOnBuild</a> (I didn’t end up using this solution, but exploring the project helped me resolve some issues)</li>
</ul>
<h3 id="my-struggle">My Struggle</h3>
<p>The next time I run into this class of problem, I definitely want to track all of my uncommitted changes and correlate each attempted fix with the relevant errors that occur which drive me to all the URLs and searches for answers as I attempt each new iteration of the fix. Then, ideally, I could blog about each stage of the journey with a little more coherence. For now and for the sake of the reader, I will simply list all of the relevant bits (that I can find in my browser history) that have led me to the conclusion that (as of this moment) T4 and Core cannot coexist.</p>
<p>Incomplete Solutions:</p>
<ul>
<li><a href="https://github.com/mono/t4">Re-implementation of T4 in Mono</a></li>
<li><a href="https://notquitepure.info/2018/12/12/T4-Templates-at-Build-Time-With-Dotnet-Core/">T4 Templates at Build Time with Dotnet Core</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=TimMaes.ttexecuter">T4Executer</a></li>
</ul>
<p>Relevant GitHub Issues:</p>
<ul>
<li><a href="https://github.com/xamarin/TorchSharp/issues/27">dotnet build fails to generate TypeGeneration.cs on linux</a></li>
<li><a href="https://github.com/mono/t4/issues/12">Add MSBuild targets package</a></li>
<li><a href="https://github.com/dotnet/core/issues/2743">Several FileNotFoundException using Newtonsoft.Json inside T4 template</a></li>
<li><a href="https://github.com/dotnet/core/issues/2000">FileNotFoundException (System.Runtime, Version=4.2.1.0) when reflecting in T4 template</a></li>
<li><a href="https://github.com/nil4/dotnet-transform-xdt/issues/16">Package type ‘DotnetCliTool’ is not supported by project</a></li>
<li><a href="https://github.com/mono/t4/issues/42">PlatformNotSupportedException with dotnet-t4-project-tool</a></li>
<li><a href="https://github.com/dotnet-websharper/core/issues/903">build failing — and what worked for me</a></li>
</ul>
<p>Relevant StackOverflow Issues:</p>
<ul>
<li><a href="https://stackoverflow.com/questions/17170080/t4-subtemplates-transformtext-not-working">T4 subtemplates TransformText() not working</a></li>
<li><a href="https://stackoverflow.com/questions/47691299/texttemplating-target-in-a-net-core-project">TextTemplating target in a .Net Core project</a></li>
<li><a href="https://stackoverflow.com/questions/50471751/the-imported-project-c-program-files-dotnet-sdk-2-1-201-microsoft-visualstudio">The imported project “C:\Program Files\dotnet\sdk\2.1.201\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets” was not found</a></li>
</ul>
<p>Microsoft Docs:</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.texttemplating.texttransformation?view=visualstudiosdk-2019">TextTransformation Class</a></li>
<li><a href="https://developercommunity.visualstudio.com/idea/535990/filenotfoundexception-systemruntime-version4210-wh.html">FileNotFoundException (System.Runtime, Version=4.2.1.0) when reflecting in T4 template in .NET Core 2.1 app</a></li>
</ul>
<p>As always, I hope this has helped someone with a similar quest. Please feel free to correct anything I have missed, suggest corrections or alternatives, or otherwise reach out to collaborate on solutions for this journey.</p>CFSometimes best intentions and good ole fashioned elbow grease are no match against the tyrannical fist of Reality. In my previous post, I discussed some of the initial ambitions and achievements in my attempt to convert the Entity Framework Core + MVC project into a dynamically generated template using T4. The good news? T4 is a perfectly adequate way to generate code from templates. The bad news? There is no way to make this completely integrated in a pure .NET Core project. What does this mean, and why is this a problem? The Story Full disclosure: if you want something approximating a tldr; just skip to the next section. For starters, the beauty of .NET Core is that I can compile and run a .NET Core app as easily on my Pixelbook as I can on my Windows devices. Getting a Core app up and running is just a git clone and dotnet build away! This simplicity is bruised, battered and beaten when we can’t run the transforms required to generate that code. In an ideal world, when I run dotnet build on the AutoEcMvc solution, the CodeGeneration project would compile and output the generated code into the AutoEcMvc project, which would then compile. If this worked, the project could then drop seamlessly into Azure Pipelines which would automatically compile, test and deploy the project to my Azure app container! (It should be noted, I can still make this work, but it’s extra work that should be unnecessary). Before I dive into the full autopsy of the deceased dream, I’ll explain my temporary solution and a few alternatives that I considered. For reasons that I’ll explain momentarily, the only way for even msbuild to work with a T4 project is to base the project on .NET Framework. In order to keep the T4 free from compilation issues (because Text Transformation happens before build, you can find yourself in a situation where the solution cannot compile without some minor hacking), I find it useful to keep the C# backing code for the templates in its own project. Unfortunately, the minimum project type that will work is .NET Standard (.NET Framework will also work, but the goal is to get as close to .NET Core as possible). For these reasons, my current solution’s solution has three projects, in build order: CodeGeneration (.NET Standard) > T4 (.NET Framework) > AutoEcMvc (.NET Core). CodeGeneration has only the utility functions required for the T4 project, which has only the metadata JSON and TT files, and AutoEcMvc has the user defined and generated content together. In another chapter, we’ll remove generated code from source control entirely, but for now I’m leaving it in place as a way to easily review and compare changes with the original project. With this configuration, msbuild works seamlessly and I’ll update my Azure Pipeline to use msbuild and get my CI/CD plans back on track. I’m less than thrilled with having to throw dotnet build under the bus, but I’ve also spent more hours trying to crack this nut than I want — and I have whales need fryin’. Before I completely abandoned the dream of a pure .NET Core solution, I explored a few options. There is Scripty, which “lets you use Roslyn-powered C# scripts for code generation. You can think of it as a scripted alternative to T4 templates.” While it sounds promising, the project hasn’t been updated in a while and seems to have outstanding issues with .NET Core. There is also the issue of documentation — any examples of converting a T4 template to Scripty would be enormously helpful. Another promising option was T5, but no amount of tinkering prevailed against the ineffable and inscrutable refusal from Core to comply. Finally, there is scaffolding built into ASP.NET Core, but this is specific to Razor pages and not really a way to keep generated code in sync with metadata in the way I want to use it. Absent other ideas, T4 still seems like the best approach without a major rewrite. I should note, my specific use of T4 is not terribly complicated, and it would be easy to ditch the templates altogether and simply write the code entirely in C#, but then it would cease to be generic and defeat the purpose of this little exercise. I may emerge from this experiment with a different opinion, but for now I’ll assume that T4 will remain the backbone of the project (until proven differently). As always, this has been a long winded series of asides, a slow and drifting detour from the main point: T4 and .NET Core do not mix. The latter does not abide the former. There is hostility, vitriol and threats of malice aforethought between the two. How do I know this? My Current “Solution” To understand the problems with trying to migrate T4 into .NET Core, I think it useful to explain the challenges presented in .NET Framework. There are two paths to text transformation. The first is a developer convenience baked directly into Visual Studio since at least 2015. When you add a new .tt file into a project, VS immediately recognizes the template and offers a few convenience options for you as a developer: (1) whenever you save changes to the template, VS immediately runs text transform and the output is regenerated, (2) VS gives context menu options to manually transform (aka Run Custom Tool) and to debug the template, which will launch the debugger and allow you to set breakpoints anywhere, and (3) VS offers the option to run all transforms at the project/solution level. All of these features are hugely beneficial to the development of templates. But. And this is a big “but”. The second is through msbuild which is what I would normally use in my CI pipeline. Msbuild launches text transform in a different context than VS, which means that the relative paths (e.g. $(SolutionDir) )that work in VS no longer work from msbuild. In order to reconcile the two different behaviors, we need to make some changes to the .csproj file. Unfortunately, a project using .NET Framework has to be unloaded to be edited, then reloaded. Personally, I edit the project file directly in VS Code and let VS trigger the reload warning after I save changes. This is tedious, but it eliminates a few right-clicks. If we start with a T4 import that looks like this: #><#@ assembly name="$(SolutionDir)CodeGeneration\\bin\\netstandard2.0\\CodeGeneration.Dll" #><#@ assembly name="$(SolutionDir)CodeGeneration\\bin\\netstandard2.0\\Newtonsoft.Json.Dll" #><#@ import namespace="Newtonsoft.Json" #><#@ import namespace="Newtonsoft.Json.Linq" #><#@ import namespace="CodeGeneration" #> we have two immediate problems. $(SolutionDir) cannot resolve outside of VS, and our 3rd party dependency on Newtonsoft will not be available from the bin directory. Starting with the latter, you can add this into a property group in the project file: <PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> Now, all reference binaries will be copied into the build output directory. Next, the challenge of resolving the path to that output directory can be solved as well. A custom mapping is required, which is also possible with a little XML markup: <PropertyGroup> <targetFolder>$(MSBuildProjectDirectory)\\..\\CodeGeneration\\bin\\netstandard2.0</targetFolder> </PropertyGroup> <ItemGroup> <T4ParameterValues Include="targetFolder"> <Value>$(targetFolder)</Value> </T4ParameterValues> </ItemGroup> Now, I can update the T4 imports to: #><#@ assembly name="$(targetFolder)\\CodeGeneration.Dll" #><#@ assembly name="$(targetFolder)\\Newtonsoft.Json.Dll" And this will work seamlessly between VS and msbuild. There are a few other changes to make, but these are much more clearly documented elsewhere. For reference here, you also need: <Import Project="$(MSBuildToolsPath)\\Microsoft.CSharp.targets" /> <PropertyGroup> <!-- Get the Visual Studio version: --> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">16.0</VisualStudioVersion> <!-- Keep the next element all on one line: --> <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath> </PropertyGroup> <!-- This is the important line: --> <Import Project="$(VSToolsPath)\\TextTemplating\\Microsoft.TextTemplating.targets" /> <PropertyGroup> <TransformOnBuild>true</TransformOnBuild> <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles> <TransformOutOfDateOnly>false</TransformOutOfDateOnly> <RunPostBuildEvent>Always</RunPostBuildEvent> </PropertyGroup> This is the final glue to ensure that you get identical behavior when compiling the project from any direction. Once all these pieces are in place, msbuild should just work. References: T4 Parameter Directive Pass build context data into the templates TransformOnBuild (I didn’t end up using this solution, but exploring the project helped me resolve some issues) My Struggle The next time I run into this class of problem, I definitely want to track all of my uncommitted changes and correlate each attempted fix with the relevant errors that occur which drive me to all the URLs and searches for answers as I attempt each new iteration of the fix. Then, ideally, I could blog about each stage of the journey with a little more coherence. For now and for the sake of the reader, I will simply list all of the relevant bits (that I can find in my browser history) that have led me to the conclusion that (as of this moment) T4 and Core cannot coexist. Incomplete Solutions: Re-implementation of T4 in Mono T4 Templates at Build Time with Dotnet Core T4Executer Relevant GitHub Issues: dotnet build fails to generate TypeGeneration.cs on linux Add MSBuild targets package Several FileNotFoundException using Newtonsoft.Json inside T4 template FileNotFoundException (System.Runtime, Version=4.2.1.0) when reflecting in T4 template Package type ‘DotnetCliTool’ is not supported by project PlatformNotSupportedException with dotnet-t4-project-tool build failing — and what worked for me Relevant StackOverflow Issues: T4 subtemplates TransformText() not working TextTemplating target in a .Net Core project The imported project “C:\Program Files\dotnet\sdk\2.1.201\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets” was not found Microsoft Docs: TextTransformation Class FileNotFoundException (System.Runtime, Version=4.2.1.0) when reflecting in T4 template in .NET Core 2.1 app As always, I hope this has helped someone with a similar quest. Please feel free to correct anything I have missed, suggest corrections or alternatives, or otherwise reach out to collaborate on solutions for this journey.Code Generation: Connecting T4 to Entity Framework Core2019-07-08T00:00:00-05:002019-07-08T00:00:00-05:00https://luddites.me/code-generation-connecting-t-4-to-entity-framework-core<p>I have enjoyed working with <a href="https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019">T4</a> in my .NET projects, and I have wanted to start exploring Entity Framework Core with ASP.NET Core. Fortunately, Microsoft has an excellent <a href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">suite of tutorials</a> which makes it dead simple to get a sample project up and running. I jumped straight to the end and began by copying down the project code from the <a href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final">ASP.NET Core Documentation</a> repo and I started my own git repo my new and intuitively named <a href="https://github.com/crfroehlich/AutoEcMvc">AutoEcMvc</a> (Automatic EF Core over MVC) project. I even went the extra mile and set up a free Azure account to host the project at <a href="https://autoecmvc.luddites.me/">https://autoecmvc.luddites.me</a>. The challenges of connecting the GitHub project to a CI/CD pipeline for hosting on Azure will be addressed in a follow up blog post.</p>
<p>This project is still in the early prototype phases, but the goal is to maintain feature parity with the original Microsoft tutorial project while eliminating the majority of the code. That said, it has most of the essential building blocks for dynamically generating models and controllers using code generation powered by T4.</p>
<p>Before diving in further, the most obvious question to answer is: What problems does this project solve? If you have ever needed to design, extend or maintain an application that either sits on relational database or exposes a concrete set of APIs, you may be familiar with the sudden weakening of the stomach as you realize just how many lines of boiler plate code need to be written in order to get your new classes or modifications to classes ready for consumption by the compiler and the consumers of the app. Factories must be updated, new view/model/controller classes must be written. Potentially hundreds of lines of code that must be manually maintained — hundreds of lines of code that are nearly identical in style and substance to the classes that came before. With code generation, we can eliminate all of that boiler plate and focus exclusively on just the (usually) small subset of things that are actually different from our new or extended schema changes.</p>
<p>T4 is one code generation/templating solution that can help us solve this problem. Since we’ll be using .NET Core as our project type, we never have to worry about adding/removing new files to/from the project — that happens automatically. T4 has some idiosyncrasies and shortcomings (also the subject of a follow-up blog post), but it works well enough for this prototype that I am comfortable recommending it as a starting point.</p>
<p>A few goals and guiding principles that I have applied:</p>
<ul>
<li>Code Generation should live in a separate project from the main application projects. This becomes essential as if your generated code does not compile, you can quickly get stuck in a chicken/egg/rooster situation where you cannot -pile to fix the compile.</li>
<li>All code templates should use structure data format for defining how to generate code. For this project, I use JSON files which represent each unique entity to be translated into actual project code.</li>
<li>Use partial classes everywhere possible to allow extension and custom properties logic.</li>
<li>Use abstract base classes to allow injecting custom logic inside the generated code. This is critical if you need custom logic to execute inside a constructor, for example, and do not want to overly complicate the templates.</li>
<li>Keep as much business logic out of the template as possible.</li>
<li>Separate generated code from user code and annotate generated code appropriately.</li>
</ul>
<p>If you look through the structure of <a href="https://github.com/crfroehlich/AutoEcMvc">AutoEcMvc</a>, you’ll notice that there are two main projects: AutoEcMvc, which is the app that gets deployed and CodeGeneration, which is just the templating logic. I picked .NET Standard as the project type for CodeGeneration, as I ran into numerous issues trying to get the project working using .NET Core. I will revisit that in the near future.</p>
<p>Perhaps the single most import part of code gen is the structured data format in use. I need to be able to map my JSON back to a C# class that can be used deterministically in T4, so my <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Transforms/schema/Course.json">Course</a> class is defined in JSON as:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"Description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A course represents a college course that a student can take"</span><span class="err">,</span><span class="w">
</span><span class="nl">"DisplayName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Title"</span><span class="err">,</span><span class="w">
</span><span class="nl">"HasControllers"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="err">,</span><span class="w">
</span><span class="nl">"ControllerMethods"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"Index"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Details"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Create"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Edit"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Delete"</span><span class="w"> </span><span class="p">]</span><span class="err">,</span><span class="w">
</span><span class="nl">"Name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Course"</span><span class="err">,</span><span class="w">
</span><span class="nl">"DatabaseGeneratedOption"</span><span class="p">:</span><span class="w"> </span><span class="s2">"None"</span><span class="err">,</span><span class="w">
</span><span class="nl">"PrimaryKeyDisplayName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Number"</span><span class="err">,</span><span class="w">
</span><span class="nl">"Columns"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="err">...</span><span class="p">]</span><span class="w">
</span></code></pre></div></div>
<p>Each entity has a collection of columns, and a column looks like:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"Description"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Unique name of the course"</span><span class="err">,</span><span class="w">
</span><span class="nl">"Length"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="err">,</span><span class="w">
</span><span class="nl">"MinimumLength"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="err">,</span><span class="w">
</span><span class="nl">"Name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Title"</span><span class="err">,</span><span class="w">
</span><span class="nl">"Order"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="err">,</span><span class="w">
</span><span class="nl">"Type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="w">
</span></code></pre></div></div>
<p>Honestly, it took quite a few iterations before I landed on the current data structure — and there is still quite a bit of cruft that can be removed to polish this. I started with the model classes, because they are the simplest and require the least amount of logic overall. I opted to use a numbered naming convention for the templates as a clue to the developer on the order in which things should be done: note this is simply an opinion and has no effect on the text transform step of compile — these templates can (and should always be able to) be transformed in any order. So <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Transforms/templates/02_Models.tt">02_models.tt</a> is the first step of the process.</p>
<p>First, include our imports for T4:</p>
<p><code class="language-plaintext highlighter-rouge"><#@ include file="imports.ttinclude" #><#</code></p>
<p>You’ll notice that I frequently start an opening tag immediately after a closing tag <code class="language-plaintext highlighter-rouge">#><#</code> . This is <a href="https://stackoverflow.com/a/19860881">just a trick</a> to avoid injecting extra white space into the output file.</p>
<p>Second, load our schema from JSON:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">tables</span> <span class="p">=</span> <span class="n">BuildMethods</span><span class="p">.</span><span class="nf">GetJsonFilesAsTables</span><span class="p">(</span><span class="n">Path</span><span class="p">.</span><span class="nf">GetDirectoryName</span><span class="p">(</span><span class="n">Host</span><span class="p">.</span><span class="n">TemplateFile</span><span class="p">)</span> <span class="p">+</span> <span class="s">"\\\\..\\\\schema"</span><span class="p">);</span>
<span class="k">foreach</span><span class="p">(</span><span class="kt">var</span> <span class="n">table</span> <span class="k">in</span> <span class="n">tables</span><span class="p">)</span> <span class="p">{</span>
</code></pre></div></div>
<p>It becomes easier as you scale the templates up and out to use utility methods. I have opted to store these in a static <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Core/BuildMethods.cs">BuildMethods</a> class for two reasons: (1) you get compile time errors that make sense if the methods don’t compile and (2) debugging is much simpler inside a C# class. You could just as easily write these in a shared T4 include, which I also do for the <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Transforms/templates/saveoutput.ttinclude">SaveOutput</a> methods. Either way works just as well. The plus sides of defining methods in T4 in this way are (1) you don’t need the “BuildMethods” prefix and (2) the methods do not need to compile before the transform executes. Personally, I generally prefer the static BuildMethods approach for most of my logic.</p>
<p>Third, we run through vanilla T4 concepts to construct our output model class. There are far better resources on the ins and outs of T4 to waste your time here, and I’d rather focus on the nuances of trying to model entities from JSON. Perhaps the biggest hurdle at the model layer is getting the property types correct. If you look at the final output for <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/AutoEcMvc/Generated/Models/Course.cs#L23">Course.cs</a>, you’ll notice that it doesn’t have many properties, but most of them are special in one or more ways.</p>
<p>First, we have <code class="language-plaintext highlighter-rouge">CourseID</code> which is the primary key for the Course table. Almost every table should have some unique identifier, and we can probably assume that it will be named <code class="language-plaintext highlighter-rouge">{tableNmae}Id</code> for the majority of cases (<a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/AutoEcMvc/Generated/Models/Person.cs#L19">Person</a> is an exception which required some <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Transforms/templates/02_Models.tt#L7">custom logic</a>).</p>
<p>Second, we have a relationship to <code class="language-plaintext highlighter-rouge">Department</code> which has the database column <code class="language-plaintext highlighter-rouge">DepartmentID</code> as well as the materialized, convenience property of <code class="language-plaintext highlighter-rouge">Department</code>. For almost all primitive properties (int, string, DateTime, etc), I use a column definition that references the primitive explicitly, e.g. <code class="language-plaintext highlighter-rouge">"Type": "int?"</code>. This works well for the most part — there are a variety of cases where we need extra information, such as to specify a string <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Transforms/schema/Course.json#L14">min/max length</a>. Relationships, whether one-to-one, one-to-many or many-to-many require a bit more work. I opted to use a dedicated set of types for these: <code class="language-plaintext highlighter-rouge">["relationship", "relagtionship?", "relationships"]</code> which I can then use inside my <a href="https://github.com/crfroehlich/AutoEcMvc/blob/master/CodeGeneration/Core/BuildMethods.cs#L328">type building logic</a> to write out the type exactly the way I want without having to specify multiple synonymous properties in JSON — that is, we could have accomplished this by defining two separate properties in the column definition, but that seemed wasteful and a potential pitfall for anyone maintaining the code — forget either property and the app won’t work as expected.</p>
<p>Third, we write out a model file for each JSON file that’s been processed:</p>
<pre><code class="language-t4"><# SaveOutput(table.Name + ".cs", "..//..//..//AutoEcMvc//Generated//Models"); } //foreach(var table in tables) #><#@ include file="saveoutput.ttinclude" #>
</code></pre>
<p>Since I want to have a single model template generate many model outputs, this handles the writing of the individual files. T4 still generates a single, backing file — which is annoying. I set the template output extension to <code class="language-plaintext highlighter-rouge">.ignore</code>, which generates a <code class="language-plaintext highlighter-rouge">02_models.ignore</code> file after each compilation. A post build event then deletes all .ignore files. It’s not the most elegant solution to the problem, but it works well enough.</p>
<p>I attacked the problem of generating the model classes from T4 by solving each class individually. From the starting project, I attacked each class in alphabetical order and committed the changes when I had each new class compiling and there were no regressions in the UI. If I were to start over, I would have written the tests first; but since the goal of this refactoring was to produce nearly 100% identical code to the original using code gen — most of the work was spent looking at the diffs to spot the bugs in my transform logic.</p>
<p>I would also note that this approach would be very different if I cared about producing the most well designed code/architecture. There are numerous edge cases I shimmed into the logic to handle inconsistent naming conventions; for example, if I were to write these classes from scratch, I would guarantee all properties were named consistently and could then throw away some of the custom logic required in transforms. Since the goal was to mimic the original code as closely as possible, I feel relatively at peace with the choices made to get here.</p>
<p>Next time, I’ll talk about some of the challenges with templating the controller classes — work that I have nearly finished. Following that, views are next up and potentially the most challenging.</p>
<p>If you enjoy working with T4 or other code generation technologies, let me know what your experience has been like. If you have any tips or tricks (especially trying to get T4 transforms running under <code class="language-plaintext highlighter-rouge">dotnet build</code>), please, please do let me know.</p>CFI have enjoyed working with T4 in my .NET projects, and I have wanted to start exploring Entity Framework Core with ASP.NET Core. Fortunately, Microsoft has an excellent suite of tutorials which makes it dead simple to get a sample project up and running. I jumped straight to the end and began by copying down the project code from the ASP.NET Core Documentation repo and I started my own git repo my new and intuitively named AutoEcMvc (Automatic EF Core over MVC) project. I even went the extra mile and set up a free Azure account to host the project at https://autoecmvc.luddites.me. The challenges of connecting the GitHub project to a CI/CD pipeline for hosting on Azure will be addressed in a follow up blog post. This project is still in the early prototype phases, but the goal is to maintain feature parity with the original Microsoft tutorial project while eliminating the majority of the code. That said, it has most of the essential building blocks for dynamically generating models and controllers using code generation powered by T4. Before diving in further, the most obvious question to answer is: What problems does this project solve? If you have ever needed to design, extend or maintain an application that either sits on relational database or exposes a concrete set of APIs, you may be familiar with the sudden weakening of the stomach as you realize just how many lines of boiler plate code need to be written in order to get your new classes or modifications to classes ready for consumption by the compiler and the consumers of the app. Factories must be updated, new view/model/controller classes must be written. Potentially hundreds of lines of code that must be manually maintained — hundreds of lines of code that are nearly identical in style and substance to the classes that came before. With code generation, we can eliminate all of that boiler plate and focus exclusively on just the (usually) small subset of things that are actually different from our new or extended schema changes. T4 is one code generation/templating solution that can help us solve this problem. Since we’ll be using .NET Core as our project type, we never have to worry about adding/removing new files to/from the project — that happens automatically. T4 has some idiosyncrasies and shortcomings (also the subject of a follow-up blog post), but it works well enough for this prototype that I am comfortable recommending it as a starting point. A few goals and guiding principles that I have applied: Code Generation should live in a separate project from the main application projects. This becomes essential as if your generated code does not compile, you can quickly get stuck in a chicken/egg/rooster situation where you cannot -pile to fix the compile. All code templates should use structure data format for defining how to generate code. For this project, I use JSON files which represent each unique entity to be translated into actual project code. Use partial classes everywhere possible to allow extension and custom properties logic. Use abstract base classes to allow injecting custom logic inside the generated code. This is critical if you need custom logic to execute inside a constructor, for example, and do not want to overly complicate the templates. Keep as much business logic out of the template as possible. Separate generated code from user code and annotate generated code appropriately. If you look through the structure of AutoEcMvc, you’ll notice that there are two main projects: AutoEcMvc, which is the app that gets deployed and CodeGeneration, which is just the templating logic. I picked .NET Standard as the project type for CodeGeneration, as I ran into numerous issues trying to get the project working using .NET Core. I will revisit that in the near future. Perhaps the single most import part of code gen is the structured data format in use. I need to be able to map my JSON back to a C# class that can be used deterministically in T4, so my Course class is defined in JSON as: "Description": "A course represents a college course that a student can take", "DisplayName": "Title", "HasControllers": true, "ControllerMethods": [ "Index", "Details", "Create", "Edit", "Delete" ], "Name": "Course", "DatabaseGeneratedOption": "None", "PrimaryKeyDisplayName": "Number", "Columns": [...] Each entity has a collection of columns, and a column looks like: "Description": "Unique name of the course", "Length": 50, "MinimumLength": 3, "Name": "Title", "Order": 0, "Type": "string" Honestly, it took quite a few iterations before I landed on the current data structure — and there is still quite a bit of cruft that can be removed to polish this. I started with the model classes, because they are the simplest and require the least amount of logic overall. I opted to use a numbered naming convention for the templates as a clue to the developer on the order in which things should be done: note this is simply an opinion and has no effect on the text transform step of compile — these templates can (and should always be able to) be transformed in any order. So 02_models.tt is the first step of the process. First, include our imports for T4: <#@ include file="imports.ttinclude" #><# You’ll notice that I frequently start an opening tag immediately after a closing tag #><# . This is just a trick to avoid injecting extra white space into the output file. Second, load our schema from JSON: var tables = BuildMethods.GetJsonFilesAsTables(Path.GetDirectoryName(Host.TemplateFile) + "\\\\..\\\\schema"); foreach(var table in tables) { It becomes easier as you scale the templates up and out to use utility methods. I have opted to store these in a static BuildMethods class for two reasons: (1) you get compile time errors that make sense if the methods don’t compile and (2) debugging is much simpler inside a C# class. You could just as easily write these in a shared T4 include, which I also do for the SaveOutput methods. Either way works just as well. The plus sides of defining methods in T4 in this way are (1) you don’t need the “BuildMethods” prefix and (2) the methods do not need to compile before the transform executes. Personally, I generally prefer the static BuildMethods approach for most of my logic. Third, we run through vanilla T4 concepts to construct our output model class. There are far better resources on the ins and outs of T4 to waste your time here, and I’d rather focus on the nuances of trying to model entities from JSON. Perhaps the biggest hurdle at the model layer is getting the property types correct. If you look at the final output for Course.cs, you’ll notice that it doesn’t have many properties, but most of them are special in one or more ways. First, we have CourseID which is the primary key for the Course table. Almost every table should have some unique identifier, and we can probably assume that it will be named {tableNmae}Id for the majority of cases (Person is an exception which required some custom logic). Second, we have a relationship to Department which has the database column DepartmentID as well as the materialized, convenience property of Department. For almost all primitive properties (int, string, DateTime, etc), I use a column definition that references the primitive explicitly, e.g. "Type": "int?". This works well for the most part — there are a variety of cases where we need extra information, such as to specify a string min/max length. Relationships, whether one-to-one, one-to-many or many-to-many require a bit more work. I opted to use a dedicated set of types for these: ["relationship", "relagtionship?", "relationships"] which I can then use inside my type building logic to write out the type exactly the way I want without having to specify multiple synonymous properties in JSON — that is, we could have accomplished this by defining two separate properties in the column definition, but that seemed wasteful and a potential pitfall for anyone maintaining the code — forget either property and the app won’t work as expected. Third, we write out a model file for each JSON file that’s been processed: <# SaveOutput(table.Name + ".cs", "..//..//..//AutoEcMvc//Generated//Models"); } //foreach(var table in tables) #><#@ include file="saveoutput.ttinclude" #> Since I want to have a single model template generate many model outputs, this handles the writing of the individual files. T4 still generates a single, backing file — which is annoying. I set the template output extension to .ignore, which generates a 02_models.ignore file after each compilation. A post build event then deletes all .ignore files. It’s not the most elegant solution to the problem, but it works well enough. I attacked the problem of generating the model classes from T4 by solving each class individually. From the starting project, I attacked each class in alphabetical order and committed the changes when I had each new class compiling and there were no regressions in the UI. If I were to start over, I would have written the tests first; but since the goal of this refactoring was to produce nearly 100% identical code to the original using code gen — most of the work was spent looking at the diffs to spot the bugs in my transform logic. I would also note that this approach would be very different if I cared about producing the most well designed code/architecture. There are numerous edge cases I shimmed into the logic to handle inconsistent naming conventions; for example, if I were to write these classes from scratch, I would guarantee all properties were named consistently and could then throw away some of the custom logic required in transforms. Since the goal was to mimic the original code as closely as possible, I feel relatively at peace with the choices made to get here. Next time, I’ll talk about some of the challenges with templating the controller classes — work that I have nearly finished. Following that, views are next up and potentially the most challenging. If you enjoy working with T4 or other code generation technologies, let me know what your experience has been like. If you have any tips or tricks (especially trying to get T4 transforms running under dotnet build), please, please do let me know.The Solstice Squid2018-12-20T00:00:00-06:002018-12-20T00:00:00-06:00https://luddites.me/the-solstice-squid<p>The Solstice Squid (TSS) lives at the South Pole; this much we know. How she came to live there or her reasons for making this her permanent place of residence, we do not; but we can perhaps draw some conclusions for her behavior from this simple fact.</p>
<p>In the depths of the ocean, deep beneath the Antarctic, where darkness reins supreme, TSS watches for light. At that moment, when the Earth is on the cusp of its return from longest nights into longer days, TSS reacts. Light is the celebration, to which TSS brings her joy.</p>
<p>Riding a sleigh of sea horses through the seven seas, TSS brings presents to the residents of this world, driving furiously through the night to enter each home through the plumbing that inevitably connects all water to the ocean. Flinging presents from her many tentacled arms toward whatever artifice those residents have established: be it tree of wood or tree of candles, TSS gently deposits gifts she has translated from the requests buried within our tears that have flowed from our eyes and sifted down into the depths of the deep.</p>
<p>TSS requires nothing of us from this, her annual sacrifice; at times, those who acknowledge TSS can compliment her by leaving plates laden with kelp or seaweed salad near the showers or bathtubs of their homes.</p>
<p>As the moon rises or sun sets on the eve of Solstice, consider TSS and her labors. She has considered yours.</p>CFThe Solstice Squid (TSS) lives at the South Pole; this much we know. How she came to live there or her reasons for making this her permanent place of residence, we do not; but we can perhaps draw some conclusions for her behavior from this simple fact. In the depths of the ocean, deep beneath the Antarctic, where darkness reins supreme, TSS watches for light. At that moment, when the Earth is on the cusp of its return from longest nights into longer days, TSS reacts. Light is the celebration, to which TSS brings her joy. Riding a sleigh of sea horses through the seven seas, TSS brings presents to the residents of this world, driving furiously through the night to enter each home through the plumbing that inevitably connects all water to the ocean. Flinging presents from her many tentacled arms toward whatever artifice those residents have established: be it tree of wood or tree of candles, TSS gently deposits gifts she has translated from the requests buried within our tears that have flowed from our eyes and sifted down into the depths of the deep. TSS requires nothing of us from this, her annual sacrifice; at times, those who acknowledge TSS can compliment her by leaving plates laden with kelp or seaweed salad near the showers or bathtubs of their homes. As the moon rises or sun sets on the eve of Solstice, consider TSS and her labors. She has considered yours.Remoting: It’s even better and even worse than you expected2018-05-12T00:00:00-05:002018-05-12T00:00:00-05:00https://luddites.me/remoting-its-even-better-and-even-worse-than-you-expected<p>Billions of gallons of ink have been spilled on this subject. Google if you want any other perspective. I think this one angle has received…</p>
<p>Billions of gallons of ink have been spilled on this subject. Google if you want any other perspective. I think this one angle has received less attention than most (angles).</p>
<p>I’ve had this thought rolling around in my head since at least November of last year. Previous title ideas included:</p>
<ul>
<li>Remoting: the terrific highs and terrible lows.</li>
<li>513 things you didn’t know about Remoting but wished you did before you started.</li>
<li>Remoting sucks. This is why you should do it.</li>
<li>Want to hate yourself a little? Try remoting.</li>
</ul>
<p>I jest. I’m only 3/8 serious. It’s important to be accurate when you work in the field of bioinformatics and statistical analysis.</p>
<p>We write a lot about our technical challenges, our innovations, our problem solving and tool adoption — all of that is exciting and fun to discuss. There’s a human element, a personal element, a uniquely individual element of working in this field and in this way that I think is oft ignored, and it is to that end that I’d like to call some attention. I think it’s as important as anything else — perhaps even more so. I can have the best of the best when it comes to hardware and software, but if I don’t have meaningful personal connections to those around the campfire — it’s all for naught.</p>
<p>Remoting is a challenge; and it’s supremely challenging because every single person on every single team is different and unique and has their own set of needs and expectations.</p>
<p>For me, I have five children. My day starts around 5:45 am. I’m sure that’s pretty late for some folks — I am not a morning person. I don’t like it. But that’s my day, and I love my kids, and I wouldn’t trade it for anything. So I go from an instant on, hard focus on the kids => breakfast, kids => dressed, kids =>packed and ready routine to a space from about 7:30 am to 9:00 am where I try to get a power nap and “really” get focused on the day. That almost never works. And then there’s the whole other separate reality which is my personal life vs my work life. The kids have karate, basketball, soccer, horse riding, concerts, plays, parent teacher conferences, doctors appointments, dentist appointments, play dates, birthday parties. My partner has her own life. We only have one car. Ignoring everything else about the nature of work — life is hard.</p>
<p>Add your job on top of that. Meetings, requirements discussions, deadlines, real-time communications, conflicts, emotional engagements in that virtual office. For some, the profession comes first and the personal comes after; others invert that; I’m sure for some it’s neutral — but the challenge of remoting is that we open ourselves up to this realm wherein these worlds are going to collide against each other.</p>
<p>I hope that it’s not a bait-and-switch. I don’t actually have any concrete advice or statistically significant analysis to offer to anyone. I couldn’t be the kind of father or partner or employee were it not for the ability to remote. Remoting has enabled/opened opportunities that would not exist otherwise.</p>
<p>Remoting is a challenge. I’ve used almost all of my sick days for vacation. No matter how awful I might feel after getting the flu, I do this, “But I can put myself in front of the computer, so I can’t cop out today” sort of self-talk. I don’t give myself the care and attention that I deserve. I work longer hours than I think I would otherwise. The lack of physical contact and interaction makes it hard to self-assess about how well I’m executing/performing. A certain neurosis can set it.</p>
<p>All of this is surmountable and solvable and usually (easily) addressed by just getting on a call with some other human and expressing my feelings. It’s a simple solution. But it’s an easy solution to forget. I think if I could say anything concrete or absolute, it would be that a person’s ability to recognize when they just need to physically (as much as is possible) connect with another human is the single most important criteria for determining whether remoting is right for you or no.</p>
<p>I stand by it. It’s not easy, but it’s worth it.</p>CFBillions of gallons of ink have been spilled on this subject. Google if you want any other perspective. I think this one angle has received… Billions of gallons of ink have been spilled on this subject. Google if you want any other perspective. I think this one angle has received less attention than most (angles). I’ve had this thought rolling around in my head since at least November of last year. Previous title ideas included: Remoting: the terrific highs and terrible lows. 513 things you didn’t know about Remoting but wished you did before you started. Remoting sucks. This is why you should do it. Want to hate yourself a little? Try remoting. I jest. I’m only 3/8 serious. It’s important to be accurate when you work in the field of bioinformatics and statistical analysis. We write a lot about our technical challenges, our innovations, our problem solving and tool adoption — all of that is exciting and fun to discuss. There’s a human element, a personal element, a uniquely individual element of working in this field and in this way that I think is oft ignored, and it is to that end that I’d like to call some attention. I think it’s as important as anything else — perhaps even more so. I can have the best of the best when it comes to hardware and software, but if I don’t have meaningful personal connections to those around the campfire — it’s all for naught. Remoting is a challenge; and it’s supremely challenging because every single person on every single team is different and unique and has their own set of needs and expectations. For me, I have five children. My day starts around 5:45 am. I’m sure that’s pretty late for some folks — I am not a morning person. I don’t like it. But that’s my day, and I love my kids, and I wouldn’t trade it for anything. So I go from an instant on, hard focus on the kids => breakfast, kids => dressed, kids =>packed and ready routine to a space from about 7:30 am to 9:00 am where I try to get a power nap and “really” get focused on the day. That almost never works. And then there’s the whole other separate reality which is my personal life vs my work life. The kids have karate, basketball, soccer, horse riding, concerts, plays, parent teacher conferences, doctors appointments, dentist appointments, play dates, birthday parties. My partner has her own life. We only have one car. Ignoring everything else about the nature of work — life is hard. Add your job on top of that. Meetings, requirements discussions, deadlines, real-time communications, conflicts, emotional engagements in that virtual office. For some, the profession comes first and the personal comes after; others invert that; I’m sure for some it’s neutral — but the challenge of remoting is that we open ourselves up to this realm wherein these worlds are going to collide against each other. I hope that it’s not a bait-and-switch. I don’t actually have any concrete advice or statistically significant analysis to offer to anyone. I couldn’t be the kind of father or partner or employee were it not for the ability to remote. Remoting has enabled/opened opportunities that would not exist otherwise. Remoting is a challenge. I’ve used almost all of my sick days for vacation. No matter how awful I might feel after getting the flu, I do this, “But I can put myself in front of the computer, so I can’t cop out today” sort of self-talk. I don’t give myself the care and attention that I deserve. I work longer hours than I think I would otherwise. The lack of physical contact and interaction makes it hard to self-assess about how well I’m executing/performing. A certain neurosis can set it. All of this is surmountable and solvable and usually (easily) addressed by just getting on a call with some other human and expressing my feelings. It’s a simple solution. But it’s an easy solution to forget. I think if I could say anything concrete or absolute, it would be that a person’s ability to recognize when they just need to physically (as much as is possible) connect with another human is the single most important criteria for determining whether remoting is right for you or no. I stand by it. It’s not easy, but it’s worth it.Code Generation: There and Back Again2017-10-24T00:00:00-05:002017-10-24T00:00:00-05:00https://luddites.me/code-generation-there-and-back-again<p>I can’t remember a project (engineering or otherwise) during which I haven’t paused to ask myself: “Why did I design this thing that way?” Sometimes as a result of this introspection, I find myself feeling remorse or self-loathing, regret or the hollow embrace of ennui. Sometimes the buyer’s remorse can begin to settle in only after years of work. Sometimes the anthropomorphic representation of the design conceit simply lurks in the shadows sewing mischief as it’s able. I’ll defer to future versions of myself to conclude the relative merits or lack thereof of this particular set of concerns.</p>
<p>Every application — from this humble blog to the social behemoths starts with data. Most projects start with a fairly predictable set of questions: what language(s) are we going to write this thing in, what type of application is this, and where are we going to store the data? Vast amounts of our data is purely relational; equal volumes of equally critical data isn’t. At the end of the day, a relational database seemed the right choice — and most grown up databases these days support storing and searching on structured and unstructured data.</p>
<p>I think this choice continues to make sense. Personally, I’ve always found managing relational databases at scale at the lower end of the spectrum of things which bring me joy as a developer. Data migrations, schema changes, wrestling with referential integrity constraints as customer requirements change…the whole mess of managing data leaves a foul taste that’s difficult to rinse out. So a younger version of myself, a rather clever fellow in his own mind, came up with a solution:</p>
<p>Code generation!</p>
<p>Looking back to the earliest commits in our repo, some of the very first were the JSON files that form the backbone of our code generating homunculus. A few simple properties in our library of JSON files are responsible for generating every C# class that backs the tables in our database. Tired of a property? Update a JSON file. Need more tables, more properties, more relationships? It’s all just JSON.</p>
<p>This makes other aspects of developing the architecture rather pleasant. Need to create or maintain a factory? Never write another line of factory code by hand. Need certain classes to implement an interface? Automate it. Need DTO versions of your table classes? Already done. RESTful web services that automatically implement ALL the verbs for every class and every possible relationship between entities? Our homunculus did that for you the day before you asked for it.</p>
<p>Orthogonally, at the database tier, we made a rather nice design choice to use globally unique ids. Our first table committed to code is a simple dictionary of Ids and Types. Every other table inherits from this base table, which means that given any valid Id, I can find the corresponding dog, cat, person or object with no extra information. When it comes to representing these data structures as REST resources, our routes can be as terse or verbose as desired. If we were so inclined, the route to add a dog to a person’s pets collection could be as simple as posting to <em>/api/{personId}/{petId}</em>, although in practice we rarely deviate from RESTful norms (<em>/api/person/{personId}/pets/{petId}</em> is the actual route).</p>
<p>The flexibility that working with globally unique identifiers would be half as pleasant if we could not automatically create and maintain the factories required to fetch an object by id and then cast it to the appropriate implementation class. As objects mature, they often have a tendency to develop greater and deeper relationships with other objects in the database. Automatically generating these relationships and the pathways between them at every tier of our framework has been a boon.</p>
<p>I regret none of this automation. As long as fundamental design choices remain constant (or at least change slowly), vertical changes to the code — changes to the JSON that result in the creation/deletion of code, scales smoothly.</p>
<p>Life gets much more interesting as we scale horizontally — changing the templates that sit between the JSON and the final C# files. Diabolical bugs can lurk by manner of a single typo in a template, waiting to reproduce themselves across hundreds of files with the click of a button. Whitespace changes annoy to the extreme. We can (usually do) anticipate and surmount many of these hurdles. Frequent commits guarantee that noise doesn’t swallow avoidable faults. When refactoring a template, always make sure that optimization changes to the template code always produce identical outputs before other refactorings.</p>
<p>Changes to behavior lead to the nightmarish class of faults that lurk under the bed and are far more insidious: changes to validation logic, unique validation, how objects are cached inside a database transaction, when/how permissions are evaluated. It is trivial to change a template in such a way that crippling performance issues are immediately injected into the app. Fail to properly dispose an object, and the app can begin gradually leaking memory. Hunting down these bugs is time consuming and tedious.</p>
<p>Orthogonally (yet again), the technology choices we made to drive code generation are somewhat dated by today’s standards. T4 would be far easier to maintain than our antiquated format; and we have inconsistencies in where template code is defined: inside the template itself or in an external “code generation” project which has to be compiled before the templates can run. While it all technically works, the cost to maintain the code gen library has only increased over time — and the cost to refactor the project to use modern frameworks is difficult to justify relative to providing new features that someone would be willing to pay for.</p>
<p>We have extracted a tremendous amount of value from this design decision overall, so I cannot condemn the philosophical approach we have taken; but within that bundle of ideas, design and technology choices there are multitudes of tiny decisions that certainly could have been better planned with an eye toward the future. The elegance of the design choices that I admire sadly must coexist with a certain amount of spaghetti, but such is the nature of development at times.</p>
<p>I suspect these dichotomies are somewhat ubiquitous in nature, but I do look forward to the opportunity to either perfect our approach to code generation or discover a superior path forward.</p>CFI can’t remember a project (engineering or otherwise) during which I haven’t paused to ask myself: “Why did I design this thing that way?” Sometimes as a result of this introspection, I find myself feeling remorse or self-loathing, regret or the hollow embrace of ennui. Sometimes the buyer’s remorse can begin to settle in only after years of work. Sometimes the anthropomorphic representation of the design conceit simply lurks in the shadows sewing mischief as it’s able. I’ll defer to future versions of myself to conclude the relative merits or lack thereof of this particular set of concerns. Every application — from this humble blog to the social behemoths starts with data. Most projects start with a fairly predictable set of questions: what language(s) are we going to write this thing in, what type of application is this, and where are we going to store the data? Vast amounts of our data is purely relational; equal volumes of equally critical data isn’t. At the end of the day, a relational database seemed the right choice — and most grown up databases these days support storing and searching on structured and unstructured data. I think this choice continues to make sense. Personally, I’ve always found managing relational databases at scale at the lower end of the spectrum of things which bring me joy as a developer. Data migrations, schema changes, wrestling with referential integrity constraints as customer requirements change…the whole mess of managing data leaves a foul taste that’s difficult to rinse out. So a younger version of myself, a rather clever fellow in his own mind, came up with a solution: Code generation! Looking back to the earliest commits in our repo, some of the very first were the JSON files that form the backbone of our code generating homunculus. A few simple properties in our library of JSON files are responsible for generating every C# class that backs the tables in our database. Tired of a property? Update a JSON file. Need more tables, more properties, more relationships? It’s all just JSON. This makes other aspects of developing the architecture rather pleasant. Need to create or maintain a factory? Never write another line of factory code by hand. Need certain classes to implement an interface? Automate it. Need DTO versions of your table classes? Already done. RESTful web services that automatically implement ALL the verbs for every class and every possible relationship between entities? Our homunculus did that for you the day before you asked for it. Orthogonally, at the database tier, we made a rather nice design choice to use globally unique ids. Our first table committed to code is a simple dictionary of Ids and Types. Every other table inherits from this base table, which means that given any valid Id, I can find the corresponding dog, cat, person or object with no extra information. When it comes to representing these data structures as REST resources, our routes can be as terse or verbose as desired. If we were so inclined, the route to add a dog to a person’s pets collection could be as simple as posting to /api/{personId}/{petId}, although in practice we rarely deviate from RESTful norms (/api/person/{personId}/pets/{petId} is the actual route). The flexibility that working with globally unique identifiers would be half as pleasant if we could not automatically create and maintain the factories required to fetch an object by id and then cast it to the appropriate implementation class. As objects mature, they often have a tendency to develop greater and deeper relationships with other objects in the database. Automatically generating these relationships and the pathways between them at every tier of our framework has been a boon. I regret none of this automation. As long as fundamental design choices remain constant (or at least change slowly), vertical changes to the code — changes to the JSON that result in the creation/deletion of code, scales smoothly. Life gets much more interesting as we scale horizontally — changing the templates that sit between the JSON and the final C# files. Diabolical bugs can lurk by manner of a single typo in a template, waiting to reproduce themselves across hundreds of files with the click of a button. Whitespace changes annoy to the extreme. We can (usually do) anticipate and surmount many of these hurdles. Frequent commits guarantee that noise doesn’t swallow avoidable faults. When refactoring a template, always make sure that optimization changes to the template code always produce identical outputs before other refactorings. Changes to behavior lead to the nightmarish class of faults that lurk under the bed and are far more insidious: changes to validation logic, unique validation, how objects are cached inside a database transaction, when/how permissions are evaluated. It is trivial to change a template in such a way that crippling performance issues are immediately injected into the app. Fail to properly dispose an object, and the app can begin gradually leaking memory. Hunting down these bugs is time consuming and tedious. Orthogonally (yet again), the technology choices we made to drive code generation are somewhat dated by today’s standards. T4 would be far easier to maintain than our antiquated format; and we have inconsistencies in where template code is defined: inside the template itself or in an external “code generation” project which has to be compiled before the templates can run. While it all technically works, the cost to maintain the code gen library has only increased over time — and the cost to refactor the project to use modern frameworks is difficult to justify relative to providing new features that someone would be willing to pay for. We have extracted a tremendous amount of value from this design decision overall, so I cannot condemn the philosophical approach we have taken; but within that bundle of ideas, design and technology choices there are multitudes of tiny decisions that certainly could have been better planned with an eye toward the future. The elegance of the design choices that I admire sadly must coexist with a certain amount of spaghetti, but such is the nature of development at times. I suspect these dichotomies are somewhat ubiquitous in nature, but I do look forward to the opportunity to either perfect our approach to code generation or discover a superior path forward.The Tetraktys by Pythagoras2017-07-15T00:00:00-05:002017-07-15T00:00:00-05:00https://luddites.me/the-tetraktys-by-pythagoras<p>Mr. George Pyncheon bolted upright in bed and stared at the ceiling for a moment, before he reached to the corner stand at his bedside to pick up the phone. His fingers trembled in the spaces between the buttons on the phone as he hastily tried to dial his office. The trembling in his fingers had shifted to his voice.</p>
<p>“Ms. Mansfield?”</p>
<p>“Yes, I’m very sorry — I won’t be in to work today.”</p>
<p>“Sick? No, no — nothing like that. No, quite the opposite, I feel wonderful.”</p>
<p>“Well, it’s just that — I’ve discovered something, something quite incredible.”</p>
<p>He paused to inhale deeply; the air raked across the roof of his mouth, gurgling in little eddies as he tried to exhale in the same moment. His fingers danced along the handle of the phone, and he struggled to maintain his grip.</p>
<p>“Yes, I know it’s a rather unique request.”</p>
<p>“Of course, I am just an accountant — you needn’t stress over that.”</p>
<p>“Yes, well, I just need the day off — this is enormous, you see; it will change everything.”</p>
<p>“No, no — I imagine that it’s sort of a permanent change.”</p>
<p>“No, of course I’m not quitting, I’m talking about the discovery.”</p>
<p>“Perhaps, tomorrow. We’ll see. Goodbye.”</p>
<p>Martha Pyncheon rolled onto her side and judgingly watched George leap out of bed, as he rushed to his dresser, flinging clothes into the air, a few of which lighted atop his head.</p>
<p>Rushing into the bathroom, George quickly dressed, barely stretching his arm through the sleeve of his shirt in time to rescue a toothbrush his other sleeve had aggressed. Walking back into the bedroom, he found Martha staring at him with a mixture of contempt and apathy. She began,</p>
<p>“George, whatever are you doing?”</p>
<p>“Martha, it just struck me. I’ve had a most singular revelation. It’s going to change this whole muddled mess of things.”</p>
<p>“I hadn’t realized there was a mess, or that it was muddled. What are you talking about?”</p>
<p>George paused to look about the room, apparently searching for some visual aid to help his forthcoming explanation. At last, he said, “Come to the kitchen — I’ll show you.”</p>
<p>Martha detachedly watched George as he sped through the bedroom to the kitchen, letting his clothes struggle desperately to keep pace and eventually finally make their way onto his body. For a moment, George stood restlessly in the kitchen, glancing about at cabinet doors, while he finished pulling his pants up to their appropriate height. At last, his gaze settled on a drawer, which he quickly pulled open.</p>
<p>With a satisfied smile, George called out to Martha as he began pulling four apples out of the drawer and placed them on the counter. Time passed. George found himself pondering the nature of breakfast and was absentmindedly lifting one of the apples to his mouth, when Martha emerged into the kitchen.</p>
<p>“Well, George, what is it?”</p>
<p>The question called up to George as if from the bottom of a staircase, which he presently began descending for reasons he could not accurately define. The stairs seemed solid enough to him, though he could not quite fathom why they needed to be employed at this moment. At last, he had reached the question and begun to size it up, when his wife repeated,</p>
<p>“Well? What is it?”</p>
<p>“Oh yes, quite right.” George slowly looked about the kitchen. He felt certain that something of great importance had brought him here. “Just a moment.” Searching for a clue, hint or remnant of purpose, he continued, “It will come to me; I’ve just forgotten momentarily.”</p>
<p>His wife heaved a sigh from her shoulders and turned to exit the kitchen. “I should have known.” Taking a step forward, she stopped and looked at him briefly, “George, go back to bed, or go to work, or do something useful.”</p>
<p>George nodded as if he had heard her, mumbling automatically, “Yes, dear;” while his eyes made a quick escape through the office of his mind, stopping at the doorway to render a sharp salute, before they about-faced and began to march the line along the counter from the sink to the row of apples. Finally, his mind peered up from its desk, rushed forward through the doorway and apprehended the eyes en route back to the apples. Taking them firmly in hand, mind and eyes approached the four apples and stood resolutely and placidly as if waiting for a sign. A minute passed.</p>
<p>“Martha! Martha! How silly of me — I’ve remembered. Of course! Come here. Quickly, now. Have a look at this!”</p>
<p>A voice called from the bedroom, “What is it, George?”</p>
<p>“You have to see it to believe it. Come here!”</p>
<p>Martha reemerged into the kitchen, barely catching up to the sigh, which had preceded her. “Yes?” she asked, fatigued.</p>
<p>George stood with the eagerness of a schoolboy, who has finally arrived at the right answer after repeated failure. “Watch this.” George paired the apples apart. “Look, there’s four of them, right?” Not waiting for an answer, “Well, there are two of them on one side, and another two are on the other side.” George paused, “You see?”</p>
<p>Martha made no move to answer. “Look here, the two plus the other two equals four. It’s so simple; it’s amazing.”</p>
<p>Martha met George’s eagerness like she might have met a stray cat with a broom.</p>
<p>“George — you’re an accountant, not a philosopher. Come back to bed.” Almost turning to leave it at that, she thought better of it and continued, “Besides, you haven’t considered the drawer yet. You may as well say 16+7=4; it’s all the same thing. Any child could tell you that, George.”</p>
<p>“No, but Martha, I’m not talking about the apples in the drawer. I’m only talking about the four apples on the counter. Pretend the others don’t exist; or better yet, pretend we’re not even talking about apples at all, just the numbers themselves. I think that 2+2 always equals 4.”</p>
<p>“George, look, there’s no use being foolish this early in the morning. You can’t dismiss all of the numbers that do exist and pretend that only a few of them matter. Look here, ‘two’ doesn’t exist. You know that. Or look at it this way, does it matter whether we call it two apples or a couple of apples? No, of course not. It’s just an adjective. A descriptive adjective. It doesn’t mean anything. We could just call them a group of apples, or we could pick any other word to describe them: two, three, fourteen — it doesn’t matter.” Sensing that George still needed further coaxing, she continued, “Look, let’s say there’s just the one apple — to use a metaphor. We know that one apple doesn’t exist. Of course not. There has to be a tree to make the apple, which means that other trees with apples have to pollinate that tree, which means that ‘thousands’ of apples and seeds and trees have to exist to produce the illusion of this, one apple. There’s never really one or two or four. You know that.”</p>
<p>“Yes, of course, I know,” he said rather sheepishly; “but if you didn’t consider all the rest of them. What if we just pretend that the only apples that matter are these four apples, these four on the counter here? We could take them and say that 2+2=4 or 3+1=4 or anything else we wanted. You see?”</p>
<p>“George, if you want to wake me up every time you feel like playing make-believe, don’t. Stop this nonsense and come to bed.”</p>
<p>“But why is this nonsense? Look, it’s plain as day. 4 apples. 2 groups of 2. 4.”</p>
<p>“George…” Martha stopped to run an angry hand over her eyes, “where were the apples before you put them on the counter? In the drawer, right? Where will they be in an hour? Who can say? Maybe back in the drawer, maybe eaten, maybe they’ll be thrown out with the trash, right? Well, it stands to reason that they only appear to be in groups of two for the moment — because you don’t really know where they are. It’s only an illusion, George. It doesn’t mean anything. You might as well try to figure out everywhere they’ve ever been and everywhere they’re going to be. You have to realize, George, that you can’t say anything real about them. The sky isn’t blue, now is it, George?”</p>
<p>Flustered, George responded, “No, of course not.”</p>
<p>Pressing him, Martha continued, “And it’s not pink, either, is it?”</p>
<p>Reverting to his schoolboy form, George almost recited, “No, colours are just an illusion, a product of imprecision. Everyone knows that.”</p>
<p>“Yes, and numbers are the same thing. What appear to be two one moment may be three the next moment. Numbers are inefficient ways to describe temporary abnormalities.”</p>
<p>George looked down at his feet and almost pleaded with them to agree with him, “But what if they weren’t? I mean, who says that they have to be temporary or abnormal? What if we just pretended for a moment that there was some real, definite and quantifiable way to look at these apples? What does it matter if the quantity changes? Couldn’t we just add them again afterwards?”</p>
<p>Martha almost struck George across the face, but in a quick feat of composure, resumed her lecturing. “Look here, if numbers were real, you’d be separating groups of apples into twos, ‘adding’ and ‘subtracting’ constantly. Don’t you see? You’d never be saying anything about anything else. Isn’t that what’s most important, George — saying something true? There’s no way to make progress by controlling the ‘number’ of apples. You see that, don’t you? You’re trying to impose your own system of order where it doesn’t belong instead of trying to say what can be said.”</p>
<p>Martha felt relieved. She had established her point, and George would surely accept it. The matter had been resolved satisfactorily. Pleased with herself, she finished, “No, George, you just stick to accounting; and all will be well.”</p>
<p>George was not, however, entirely convinced. “But…Martha, what if…you see, we could use the same sorts of numbers and arrange them to describe all of that. Wouldn’t that be grand? We could describe the number of apples coming on to and off of the counter just as easily as we liked. It would be no problem,” he paused, “really, it wouldn’t.”</p>
<p>The cool composure that Martha had struggled to achieve flew out of her with an exasperated cry of rage. “George, you ignorant fool! Sometimes I wonder how our marriage lasts! You self-conceited pig; you dumb ass! Don’t you see? You’re just trying to control the world. You feel dissatisfied with your place, because of some sick, twisted envy or greed for power that has overcome you. By ‘quantifying’ and ‘collecting’ you introduce some measure of control over a world that will not be controlled. You become powerful, assertive, aggressive, and for what? It’s a pleasant delusion, George; I agree with you there. But have you thought about the cost? The terrible cost? Where could we find freedom in a system that imposes such ridiculous and inconstant rules — or any rules at all? You do support, freedom; don’t you, George? Of course you do — you’re not a traitor, stupid as you are. We need to stay focused on what’s real, what’s important — on the things that matter.”</p>
<p>“Why shouldn’t this matter? It could be useful, helpful even. Imagine if I could tell Harry more than ‘Yes, we have money today,’ or ‘No, Harry, no money today.’” What if I could tell him, ‘Harry, we have 28,000 dollars.’? What might that be like? What if we created business exchanges based on quantities — on numbers?”</p>
<p>“To accomplish what, exactly? Look at the apples, George. Look at them! Do you see any numbers there? Are they separated into any groups? No! Do you know why that is? Because they don’t exist! Because you imagined them and imposed these things upon the apples. Where is a ‘one’? Do you see ‘one,’ because I don’t? Now stop all of this before you make me more upset than I already am. Stop it at once!”</p>
<p>George felt like the schoolboy, who had been publicly humiliated by the teacher, though he still felt certain, perhaps even more certain than he had been before, that he was right.</p>
<p>“Martha, listen to me — ”</p>
<p>But Martha had had quite, “ENOUGH.” With that, she stormed out of the kitchen to the bedroom. George stood by the counter, staring resolutely at the apples. The sound of dialing wafted into the kitchen with the scent of his wife’s perfume. He was vaguely aware of some rapid, hushed dialog; though, his mind paid attention only to the groups of two that he observed beneath him. After a moment, he was aware of the sound of a handle being placed quietly on the receiver. Cautiously, he turned and approached the bedroom and peaked through the doorway to look at his wife, who sat huddled on the bed, her knees drawn up to her chin. She was crying, he noticed.</p>
<p>“Martha, Martha — what’s the matter. Why are you crying?” George began.</p>
<p>“George, are you ready to drop all this nonsense about numbers and apples?” She raised her eyes over the knees she had hid them behind to look at him, slowly wiping a tear from her eye.</p>
<p>“Martha, perhaps I’ve explained it all badly. Let me try again in a way that won’t upset you.”</p>
<p>“No, you needn’t bother, George.” Martha sobbed. “There’s someone I think you should talk to.”</p>
<p>The car ride passed in silence. George stared out of the passenger-side window of the car into the countryside. As the car ambled along the road, George caught his eyes and mind closed within their offices, calculating odd sums, counting telephone poles and bridges, and creating little equations. George left them to their business and looked at the heavy silence that sat like a wet loaf of bread between him and Martha. He briefly considered eating his way through. In the end, he followed his eyes out the window and passed the car ride agreeing with his own conclusions. He didn’t turn back to look at Martha until he noticed that the car had stopped moving and the engine was cold.</p>
<p>“George, are you still certain of these little ideas of yours?”</p>
<p>“Martha, I feel as if I’ve never been more certain of anything in my life. The whole countryside seems to be alive with sums and calculations. I don’t know how I could have missed them for so long.”</p>
<p>Martha struggled to maintain her composure. She felt tears welling up inside her, but resisted them with the desire to be strong for her husband, who needed her now more than ever. “Ok, George…” she paused to wipe her palm against her brow, “…I just hope Mr. Laughton can help.”</p>
<p>George felt as if there was something very large that should be obviously apparent to him that he could simply not make out. “Help? Whatever with?”</p>
<p>Stepping out of the car, Martha said, “Just follow me, George.”</p>
<p>George followed her automatically. The office building that stood before him made no impression on George. It seemed to him to be vaguely familiar, if only because it looked like every other office building he had ever seen. The only distinguishing characteristic that drew George’s attention stood against a sign, which faced inward toward the building, showing the word “Integration” to all the open windows of the office. George followed Martha into the lobby towards a receptionist.</p>
<p>“Well, well, welcome,” the rosy woman greeted them. The receptionist briefly glanced at a clipboard on her desk. Smiling broadly, she said, “George, Martha, so good to see you. Mr. Laughton is waiting for you.”</p>
<p>“Thank you,” Martha said.</p>
<p>“Wonderful, wonderful. Marvelous.”</p>
<p>Martha pointed George in the right direction, and released him like a wind-up toy. Martha began to follow sadly behind him, when the receptionist quietly motioned to her.</p>
<p>“Pardon me, Martha, how bad is it?” she whispered.</p>
<p>“Worse than you can possibly imagine.”</p>
<p>“Don’t worry, there’s a girl. Mr. Laughton will know what to do. No worries.”</p>
<p>George and Martha had stood in the waiting room less than a moment, before Mr. Laughton appeared, a mountain of hand-shaking and ‘how-are- you’s. Laughton’s face had almost been split in two with the smiles that flashed across it in rapid succession.</p>
<p>“Well, well, what a wonderful surprise, what a pleasant surprise we have here. My goodness, my. Yes, wonderful. Well, what seems to be our little problem? Yes, what indeed? What seems to be our situation? Goodness. My. And how are you George? Looking wonderful. Yes, my — goodness. What can be done? What can I do?”</p>
<p>Martha gushed, “Oh, please Mr. Laughton, you have to help him. You simply must. Please, he woke up this morning half-mad, talking about twos and fours, apples, and a whole lot of other nonsense; and he won’t give it up. He’s even getting worse, talking about ‘certainties’ and ‘equations’ and who-knows what else.”</p>
<p>“Who-knows, indeed. Oh my! Goodness! George? What’s all this? Come, George, tell me what’s on your mind. What can be done, I say. I say, what can we do?”</p>
<p>George stared down at his feet, wondering fleetingly how a sheep might describe the look. “Well, it’s just that…” he paused to take a deep breath, “…I was looking at these apples this morning, four of them, you see; and I noticed that you could divide them into two groups of two and then add them back together again to make four, you see. Well, I was rather thinking that you could do that in general.”</p>
<p>“I say, what? Divide apples, you say? In general? Come George, let me have it all.”</p>
<p>“Well, yes, of course apples, I suppose; but I was thinking that you could make a sort of general principle out of it, you know. Like, you could say 2+2=4.”</p>
<p>Martha spurted, “Do you see what I mean? I’ve been arguing with him all morning, but he just won’t listen to reason. You see how he is.” She pouted, jabbing her thumb toward George.</p>
<p>Laughing vigorously, Mr. Laughton said, “Martha, why don’t you wait out here, while I talk to George inside.”</p>
<p>Turning, he took George by the arm and led him through the doorway to his office. Laughing and closing the door behind him, he continued, “Wonderful! Marvelous! George, of course you can! 2+2=4? Quite rich, George. Quite funny. You’re absolutely right, George. Quite right. Let me show you something.”</p>
<p>George looked around the small office, while Laughton searched his bookcase for a specific volume. The bookcase itself, was little more than a piece of rusted wire, bent and twisted in a long series of angles, upon which sat a great many volumes, resting against each other unevenly. Between George and the bookcase stood a tall, gold-framed picture of a dark, mahogany bookcase, filled with leather bound volumes. Next to the bookcase sat a cardboard box, upon which someone had scribbled, “Desk.” Another picture sat adjacent to the box, featuring a mahogany desk in the same style as the bookcase. Behind the desk sat a metal, foldout chair, next to which stood a picture of a high-back, leather-upholstered chair. In front of the box, George noticed another foldout chair, next to which stood a picture of a long leather couch.</p>
<p>Turning from the bookcase, Mr. Laughton said, “George, have a seat on the couch; make yourself comfortable. Relax, George, that’s the thing. Nothing to stress over. No reason to be uncomfortable. Oh no! Not here, George. No reason at all.”</p>
<p>George sat down in the chair.</p>
<p>“That’s the spirit, George. What do you think about that couch there? It’s fresh in from Europe — very expensive, very, I dare say, sheik. Oh yes. My! Goodness! Now…about your revelation, your little hypothesis, let’s have a look.”</p>
<p>Mr. Laughton retrieved a book from the top shelf and turned toward George. “2+2=4? Wonderful. Marvelous! It’s so avant-garde. It’s so prosaic. Very post-modern. Very, dare I say, edgy. That’s the thing, when you’re writing poetry; you want it in their faces, upfront and uncomfortable. I dare say. Not like here, not like now — oh no. You want to express something. Am I right?”</p>
<p>“Well, yes, I do suppose that’s right. I do want to express something — ”</p>
<p>“ — Of course you do, my boy, of course you do. Are you familiar, I wonder, with some of the ancient Greek poetry? I dare say you aren’t. It’s very dry reading, very drab, very prosaic — but quite profound, quite unique.”</p>
<p>Taking the volume in his hand, he walked towards George and handed him the book.</p>
<p>“Here’s a fellow, quite extraordinary, quite delicious, name of Euclid. Take a look at him now, if you like. Quite harmless, quite vague. He has written a neat collection of poems there in a unique “Earth meter,” I believe. He coined the phrase, you know. Very edgy. Of course, it’s a question of interpretation, mind you. Is he talking about sunsets or rose gardens? You see where I’m driving at, do you not? You see my direction?”</p>
<p>George opened the book and turned a few pages. “A point is that which has no parts.”</p>
<p>Flipping through the book, he looked up, “What if…I mean…suppose we interpreted him literally, you know?”</p>
<p>Mr. Laughton paused and scratched his head before an enormous grin united his ears.</p>
<p>“George, it might be genius! I think I see where you’re driving at, George, where you’re driving to — this is interesting. Very. Perhaps, you’ve been wasted as an accountant. Perhaps you should have been a schoolteacher for literature. Your grasp on these things is quite intuitive. Perhaps you are right. It could be that Euclid is using poetry as a medium to speak philosophically. There was that undercurrent of ambient philosophy with the Greeks — their form is always so legalistic, so rigid — always so difficult to understand what they were trying to say. But that’s another matter, George. Quite another, distant matter. The important thing, the thing of importance, the thing I cannot stress enough, George, is that all of this is quite normal. Quite usual. Quite healthy. You wouldn’t believe the quiet, normal people who come in here for a quick spot of advice on their way to work, now and again.”</p>
<p>“So other people have had the same thoughts?”</p>
<p>“Oh my! Yes, George. All the time. They just need a push in the right direction, like you, to help them say what it is that they want to express. Sometimes, you get a notion in your head, and it becomes difficult to separate this thought from the Truth. One moment, you don’t like your job, or you have the thought that you’d be better off skydiving than accounting. You don’t like skying diving, do you George?”</p>
<p>“Why, I suppose not, no,” George said.</p>
<p>“Of course you don’t. But sometimes you have this thought, and the next thing you know the only thing in your life worth a toss is the idea of throwing yourself out of an airplane. You see what I mean.”</p>
<p>“Well, I’m not sure that I do; I’m not sure how all of this relates to me. I just had this idea, you know…I don’t really see what all of the fuss is about.”</p>
<p>“Ah! Hrmmm…I see…Well, George, I hadn’t wanted to get into this — but, well, perhaps. Let me put it this way, George. We, you and I, George, are not terribly smart men. We’re competent, I dare say, technically proficient, you know — we function well, you and I. We are not great minds. We are not ‘the thinkers,’ George. There have been and will always be the great minds. These men wrestle with ideas. They’ve been doing it since the Greeks. Now, you would object to a carpenter, who began to lecture you about how to perform accounting, would you not? I dare say you would. As would I. Well, in the same right, it is the job of the great minds to do some amount of thinking. I say, it’s their job, you know. They think these thoughts; I say, these things have been thought through. They’ve been decided. Resolved. Sometimes, it’s true; the great minds have a change of opinion. Evidences come to light. Proofs. It’s true. It happens. But look at yourself, George. Are you a man to challenge a carpenter? Will you build a better house? Have you the tools, my good man? I mean, of course, have you studied? Have you been to university? Have you trained? Have you researched and conferred with peers the same caliber as yourself? No? Well, I am not such a man to be arrogant about these things. Not so proud that I dare to challenge what men smarter than myself have learned. Do you not think they are men just like yourself, with the best intentions? Men after the Truth? Men looking out for the good of their work and the pursuit of freedom? Do you not? These are men of science, George. Men of Progress. Yes. Now, I know you, George. You’re no more arrogant than I am. No, clearly not. You’re right of course, men have ideas. You have ideas. This is the right and proper thing for men to do. But more than this, George, we must learn how to express ourselves. That’s the thing. Thoughts crave expression. Expression is part of Freedom, is it not, George?”</p>
<p>George nodded his agreement.</p>
<p>“Of course it is. Now, we are civilized men, you and I — we are properly progressive. We are supporters of the Institution of Freedom, are we not? We are not the types to cry ‘fire!’ in a theater. We are not treasonous. No. We are both servants, you and I, to our proper commissions. There is no great fuss, you see — no cause for alarm. We must strive to do our best by doing that which we do well, as we have always done. You see what I mean, don’t you, George?”</p>
<p>“Well, yes, of course. I suppose I do. I hadn’t thought of it all quite like that. You must be right, I’m sure.” George paused to look at the picture of the bookshelf. “That is a lovely bookcase.”</p>
<p>“Quite right, George. Quite. Hmm…the bookshelf? Oh, yes.” Mr. Laughton paused to allow himself a confident grin. “Yes, I suppose that they do allow me certain privileges, certain liberties. It is a positive, yes. But these fine things,” he gestured toward the whole room, “are as much for your comfort and pleasure as they are for mine. I am only a servant.”</p>
<p>“So this has been studied before, I take it? The great minds have researched it?”</p>
<p>“Quite thoroughly, George. Quite. Volumes have been written. Critical responses. Whole libraries of poetry have been dedicated to questions such as these. The important thing, I say, the thing to note is that we know how to express ourselves. We do not wish to run about shouting that the sky is blue or the world is round or any such nonsense, not unless we mean to make a point, unless we mean to say something about Truth, unless we are exercising our Freedom, George. As long as we recognize the metaphor for what it is, we are free to use it however we feel.”</p>
<p>“So I’m free to use it — ”</p>
<p>“ — Free indeed, George! Free indeed. We mustn’t do anything to jeopardize Freedom, George. That is the golden rule, dare I say, the only rule. We cannot challenge our universal right to freedom — that is the thing that must be protected, valued, I say, defended at all costs. You are free to be free. And this great charge has but only one price: you must not limit freedom. It must free to grow and expand, as it will, free to flourish. Yes. If I were a smarter man than I am, I might speculate that this very notion may have been present before the great minds when they decided on such things as numbers and adjectives and metaphors — this very notion may have prompted their studies, their diligent inquiries, their painstaking research in some small way. But this is my speculation, mind you; only my humble hypothesis shared between close friends, only a wild guess — not a fact, not by any means a certainty. The important thing, George is that you not challenge the march of Freedom. Certainly not.”</p>
<p>“I believe that I begin to see your meaning,” George began. “I must confess, I hadn’t thought of these things quite this way before. I hadn’t realized — ”</p>
<p>“ — Worry not, George! You have no reason to feel anything but totally liberated, totally free. As I said in the beginning, there is nothing to worry about. Nothing unusual. No fuss, I dare say, no problems whatsoever. Martha, no doubt, has your best interest always in mind, so to speak. Marriage can be trying, you understand. It’s easy to react, to overreact, to jump to conclusions, I won’t wager. Easy to misunderstand. That’s why we must be careful, considerate, ‘forgiving’ so to speak. There’s no fault to be found, no reason to be ungrateful. No, no, quite not. Quite the opposite. Wonderful, really, all of it. No, I’ll just have a quick word with her to explain today’s misunderstanding, a quick note of reassurance passed between friends, a quick chat to sooth the seas.”</p>
<p>George stood up from his chair, looking most pleased and grateful for Mr. Laughton’s sudden proposal of kindness. “Thank you. I would appreciate it. You know…”</p>
<p>George stopped to peer again at his feet, which had been hidden so recently beneath the chair; satisfied that they were each in order, “You know, I do hate to be a bother.”</p>
<p>Laughing and smiling preceded Mr. Laughton’s reassuring, “Bother? Don’t be absurd, George. No bother at all. None whatsoever. None at all. This is all quite usual. Quite normal. Ordinary. I am your servant. Just ask Margaret on your way out, and she’ll have transportation arranged to your office. No sense missing work, am I right, George?”</p>
<p>“Oh, yes, most certainly. Thank you again for your assistance. I shill be on my way, then.”</p>
<p>“Anytime, George, anytime. I am here for you. For you, I dare say, I am here.”</p>
<p>Moments later, George observed his feet as they stood on the edge of the sidewalk looking toward the road. An unmistakably plain van pulled around the corner and stopped in front of George. Stepping between a picture of a stretch limousine and the door, he climbed into the vehicle. “To the Ministry of Accounting, then, George?” the driver asked.</p>
<p>“Please, if you will, thank you.”</p>
<p>Mr. Laughton took Martha into his office with the grave air of a surgeon about him. His many smiles had been replaced by concentrated frowns.</p>
<p>“Martha…” he paused to place a hand on her shoulder, “you did the right thing, I say, the thing to do. George is in bad shape, Martha. It’s not the worst I’ve seen. I have seen worse. We need to watch him, though; keep a close eye on him. The thing to keep in mind through all of this is that you don’t want to keep the embers burning. You don’t want him to flare up again. You don’t want to fan the fire. You don’t want to suggest that his delusions are in fact delusions. You want him to feel quite ordinary, quite free. The feelings are the thing. When these common people snap, when the common man suffers from these mental fancies, when they take their dreaming a step too far, you must humor them to a point — to a point, Martha. We want them to adjust properly. Believe it or not, nothing is more dangerous to the cause of Freedom than the common man. The confused thinker, the dissident mind, that ghastly, uneducated mind, which begins to make leaps without a proper foundation, can incite a most unfree spirit among its peers.</p>
<p>It’s not the thoughts that are important so much as the feeling. That sense of challenge, of pride, of awful vanity can spread infectiously from man to man. No, at all costs, George must not suspect that anything is wrong. Nothing unusual about his thoughts. He must believe them to be quite usual. He must begin to express himself properly. As I said, Martha, you did the right thing. Quite. But let us not react too violently to his thoughts. Let our reaction be of no reaction. Interpret his meanings for him. Compliment him on his cleverness and quick wit. That’s the medicine, that’s the ticket to be bought, that’s the course to be followed. Of course, do let me know if the situation becomes worse. Measures may need to be taken. Measures may be needed. We may need to follow certain paths. Indeed. Quite.”</p>
<p>Martha extended her thanks as she nodded seriously throughout Mr. Laughton’s prognosis. Exiting the office, she allowed herself a sigh of relief. Once the door had been shut, Mr. Laughton turned toward his desk, glancing about the room. “Now, where did I set that Euclid?”</p>
<p>Seating himself in his cubicle, George glanced up to look at the picture of his workplace, which portrayed a solid cherry desk, several gold-trimmed leather chairs, and a series of other odd pieces of furniture. Shifting uncomfortably in the metal foldout chair, upon which he sat, he grasped the ringing phone. “Hello?” “Yes, of course.”</p>
<p>George stood and walked toward the department manager’s office. He had barely begun to knock when the door swung open to greet the manager himself, who peered down at George through a pair of horn-rimmed glasses, which seemed to be struggling desperately to remain in place atop the manager’s nose. Smiling enormously, he swept George into the office with a broad welcome. “Well, George, it’s good to see you. Come in, come in.”</p>
<p>The manager closed the door behind him.</p>
<p>“We’re all so glad you’re well. Ms. Mansfield told me that you had called in sick; now, here you are, right as rain! I talked to Martha a few moments ago — she called to make sure you had arrived here safely. I just wanted to talk to you privately for a moment, to express how valuable you are to this department. You are valuable, George. What’s more, to show our appreciation, I think you may have noticed that we have taken the liberty of refurnishing your office. How do you like it?”</p>
<p>George beamed, “It’s wonderful, thank you.”</p>
<p>“Think nothing of it, George. We’ll spare no expense for you, George. Not for you.”</p>
<p>The manager stopped as if to assess the situation. Apparently finding everything in order, he continued, “Well, that about covers it. I can expect the usual finance report from you today?”</p>
<p>Nodding assuredly, “Yes, of course.”</p>
<p>“Wonderful. I know you haven’t had a chance to go over the books yet, so to speak; but can you tell me ‘off-the- record,’ have we got any money?”</p>
<p>“Yes, I would say that we’ve got quite a lot of it.”</p>
<p>The manager laughed instantly and heartily, “That’s too rich, George. Quite a sense of humor you’ve got. Keep up the good work then.”</p>CFMr. George Pyncheon bolted upright in bed and stared at the ceiling for a moment, before he reached to the corner stand at his bedside to pick up the phone. His fingers trembled in the spaces between the buttons on the phone as he hastily tried to dial his office. The trembling in his fingers had shifted to his voice. “Ms. Mansfield?” “Yes, I’m very sorry — I won’t be in to work today.” “Sick? No, no — nothing like that. No, quite the opposite, I feel wonderful.” “Well, it’s just that — I’ve discovered something, something quite incredible.” He paused to inhale deeply; the air raked across the roof of his mouth, gurgling in little eddies as he tried to exhale in the same moment. His fingers danced along the handle of the phone, and he struggled to maintain his grip. “Yes, I know it’s a rather unique request.” “Of course, I am just an accountant — you needn’t stress over that.” “Yes, well, I just need the day off — this is enormous, you see; it will change everything.” “No, no — I imagine that it’s sort of a permanent change.” “No, of course I’m not quitting, I’m talking about the discovery.” “Perhaps, tomorrow. We’ll see. Goodbye.” Martha Pyncheon rolled onto her side and judgingly watched George leap out of bed, as he rushed to his dresser, flinging clothes into the air, a few of which lighted atop his head. Rushing into the bathroom, George quickly dressed, barely stretching his arm through the sleeve of his shirt in time to rescue a toothbrush his other sleeve had aggressed. Walking back into the bedroom, he found Martha staring at him with a mixture of contempt and apathy. She began, “George, whatever are you doing?” “Martha, it just struck me. I’ve had a most singular revelation. It’s going to change this whole muddled mess of things.” “I hadn’t realized there was a mess, or that it was muddled. What are you talking about?” George paused to look about the room, apparently searching for some visual aid to help his forthcoming explanation. At last, he said, “Come to the kitchen — I’ll show you.” Martha detachedly watched George as he sped through the bedroom to the kitchen, letting his clothes struggle desperately to keep pace and eventually finally make their way onto his body. For a moment, George stood restlessly in the kitchen, glancing about at cabinet doors, while he finished pulling his pants up to their appropriate height. At last, his gaze settled on a drawer, which he quickly pulled open. With a satisfied smile, George called out to Martha as he began pulling four apples out of the drawer and placed them on the counter. Time passed. George found himself pondering the nature of breakfast and was absentmindedly lifting one of the apples to his mouth, when Martha emerged into the kitchen. “Well, George, what is it?” The question called up to George as if from the bottom of a staircase, which he presently began descending for reasons he could not accurately define. The stairs seemed solid enough to him, though he could not quite fathom why they needed to be employed at this moment. At last, he had reached the question and begun to size it up, when his wife repeated, “Well? What is it?” “Oh yes, quite right.” George slowly looked about the kitchen. He felt certain that something of great importance had brought him here. “Just a moment.” Searching for a clue, hint or remnant of purpose, he continued, “It will come to me; I’ve just forgotten momentarily.” His wife heaved a sigh from her shoulders and turned to exit the kitchen. “I should have known.” Taking a step forward, she stopped and looked at him briefly, “George, go back to bed, or go to work, or do something useful.” George nodded as if he had heard her, mumbling automatically, “Yes, dear;” while his eyes made a quick escape through the office of his mind, stopping at the doorway to render a sharp salute, before they about-faced and began to march the line along the counter from the sink to the row of apples. Finally, his mind peered up from its desk, rushed forward through the doorway and apprehended the eyes en route back to the apples. Taking them firmly in hand, mind and eyes approached the four apples and stood resolutely and placidly as if waiting for a sign. A minute passed. “Martha! Martha! How silly of me — I’ve remembered. Of course! Come here. Quickly, now. Have a look at this!” A voice called from the bedroom, “What is it, George?” “You have to see it to believe it. Come here!” Martha reemerged into the kitchen, barely catching up to the sigh, which had preceded her. “Yes?” she asked, fatigued. George stood with the eagerness of a schoolboy, who has finally arrived at the right answer after repeated failure. “Watch this.” George paired the apples apart. “Look, there’s four of them, right?” Not waiting for an answer, “Well, there are two of them on one side, and another two are on the other side.” George paused, “You see?” Martha made no move to answer. “Look here, the two plus the other two equals four. It’s so simple; it’s amazing.” Martha met George’s eagerness like she might have met a stray cat with a broom. “George — you’re an accountant, not a philosopher. Come back to bed.” Almost turning to leave it at that, she thought better of it and continued, “Besides, you haven’t considered the drawer yet. You may as well say 16+7=4; it’s all the same thing. Any child could tell you that, George.” “No, but Martha, I’m not talking about the apples in the drawer. I’m only talking about the four apples on the counter. Pretend the others don’t exist; or better yet, pretend we’re not even talking about apples at all, just the numbers themselves. I think that 2+2 always equals 4.” “George, look, there’s no use being foolish this early in the morning. You can’t dismiss all of the numbers that do exist and pretend that only a few of them matter. Look here, ‘two’ doesn’t exist. You know that. Or look at it this way, does it matter whether we call it two apples or a couple of apples? No, of course not. It’s just an adjective. A descriptive adjective. It doesn’t mean anything. We could just call them a group of apples, or we could pick any other word to describe them: two, three, fourteen — it doesn’t matter.” Sensing that George still needed further coaxing, she continued, “Look, let’s say there’s just the one apple — to use a metaphor. We know that one apple doesn’t exist. Of course not. There has to be a tree to make the apple, which means that other trees with apples have to pollinate that tree, which means that ‘thousands’ of apples and seeds and trees have to exist to produce the illusion of this, one apple. There’s never really one or two or four. You know that.” “Yes, of course, I know,” he said rather sheepishly; “but if you didn’t consider all the rest of them. What if we just pretend that the only apples that matter are these four apples, these four on the counter here? We could take them and say that 2+2=4 or 3+1=4 or anything else we wanted. You see?” “George, if you want to wake me up every time you feel like playing make-believe, don’t. Stop this nonsense and come to bed.” “But why is this nonsense? Look, it’s plain as day. 4 apples. 2 groups of 2. 4.” “George…” Martha stopped to run an angry hand over her eyes, “where were the apples before you put them on the counter? In the drawer, right? Where will they be in an hour? Who can say? Maybe back in the drawer, maybe eaten, maybe they’ll be thrown out with the trash, right? Well, it stands to reason that they only appear to be in groups of two for the moment — because you don’t really know where they are. It’s only an illusion, George. It doesn’t mean anything. You might as well try to figure out everywhere they’ve ever been and everywhere they’re going to be. You have to realize, George, that you can’t say anything real about them. The sky isn’t blue, now is it, George?” Flustered, George responded, “No, of course not.” Pressing him, Martha continued, “And it’s not pink, either, is it?” Reverting to his schoolboy form, George almost recited, “No, colours are just an illusion, a product of imprecision. Everyone knows that.” “Yes, and numbers are the same thing. What appear to be two one moment may be three the next moment. Numbers are inefficient ways to describe temporary abnormalities.” George looked down at his feet and almost pleaded with them to agree with him, “But what if they weren’t? I mean, who says that they have to be temporary or abnormal? What if we just pretended for a moment that there was some real, definite and quantifiable way to look at these apples? What does it matter if the quantity changes? Couldn’t we just add them again afterwards?” Martha almost struck George across the face, but in a quick feat of composure, resumed her lecturing. “Look here, if numbers were real, you’d be separating groups of apples into twos, ‘adding’ and ‘subtracting’ constantly. Don’t you see? You’d never be saying anything about anything else. Isn’t that what’s most important, George — saying something true? There’s no way to make progress by controlling the ‘number’ of apples. You see that, don’t you? You’re trying to impose your own system of order where it doesn’t belong instead of trying to say what can be said.” Martha felt relieved. She had established her point, and George would surely accept it. The matter had been resolved satisfactorily. Pleased with herself, she finished, “No, George, you just stick to accounting; and all will be well.” George was not, however, entirely convinced. “But…Martha, what if…you see, we could use the same sorts of numbers and arrange them to describe all of that. Wouldn’t that be grand? We could describe the number of apples coming on to and off of the counter just as easily as we liked. It would be no problem,” he paused, “really, it wouldn’t.” The cool composure that Martha had struggled to achieve flew out of her with an exasperated cry of rage. “George, you ignorant fool! Sometimes I wonder how our marriage lasts! You self-conceited pig; you dumb ass! Don’t you see? You’re just trying to control the world. You feel dissatisfied with your place, because of some sick, twisted envy or greed for power that has overcome you. By ‘quantifying’ and ‘collecting’ you introduce some measure of control over a world that will not be controlled. You become powerful, assertive, aggressive, and for what? It’s a pleasant delusion, George; I agree with you there. But have you thought about the cost? The terrible cost? Where could we find freedom in a system that imposes such ridiculous and inconstant rules — or any rules at all? You do support, freedom; don’t you, George? Of course you do — you’re not a traitor, stupid as you are. We need to stay focused on what’s real, what’s important — on the things that matter.” “Why shouldn’t this matter? It could be useful, helpful even. Imagine if I could tell Harry more than ‘Yes, we have money today,’ or ‘No, Harry, no money today.’” What if I could tell him, ‘Harry, we have 28,000 dollars.’? What might that be like? What if we created business exchanges based on quantities — on numbers?” “To accomplish what, exactly? Look at the apples, George. Look at them! Do you see any numbers there? Are they separated into any groups? No! Do you know why that is? Because they don’t exist! Because you imagined them and imposed these things upon the apples. Where is a ‘one’? Do you see ‘one,’ because I don’t? Now stop all of this before you make me more upset than I already am. Stop it at once!” George felt like the schoolboy, who had been publicly humiliated by the teacher, though he still felt certain, perhaps even more certain than he had been before, that he was right. “Martha, listen to me — ” But Martha had had quite, “ENOUGH.” With that, she stormed out of the kitchen to the bedroom. George stood by the counter, staring resolutely at the apples. The sound of dialing wafted into the kitchen with the scent of his wife’s perfume. He was vaguely aware of some rapid, hushed dialog; though, his mind paid attention only to the groups of two that he observed beneath him. After a moment, he was aware of the sound of a handle being placed quietly on the receiver. Cautiously, he turned and approached the bedroom and peaked through the doorway to look at his wife, who sat huddled on the bed, her knees drawn up to her chin. She was crying, he noticed. “Martha, Martha — what’s the matter. Why are you crying?” George began. “George, are you ready to drop all this nonsense about numbers and apples?” She raised her eyes over the knees she had hid them behind to look at him, slowly wiping a tear from her eye. “Martha, perhaps I’ve explained it all badly. Let me try again in a way that won’t upset you.” “No, you needn’t bother, George.” Martha sobbed. “There’s someone I think you should talk to.” The car ride passed in silence. George stared out of the passenger-side window of the car into the countryside. As the car ambled along the road, George caught his eyes and mind closed within their offices, calculating odd sums, counting telephone poles and bridges, and creating little equations. George left them to their business and looked at the heavy silence that sat like a wet loaf of bread between him and Martha. He briefly considered eating his way through. In the end, he followed his eyes out the window and passed the car ride agreeing with his own conclusions. He didn’t turn back to look at Martha until he noticed that the car had stopped moving and the engine was cold. “George, are you still certain of these little ideas of yours?” “Martha, I feel as if I’ve never been more certain of anything in my life. The whole countryside seems to be alive with sums and calculations. I don’t know how I could have missed them for so long.” Martha struggled to maintain her composure. She felt tears welling up inside her, but resisted them with the desire to be strong for her husband, who needed her now more than ever. “Ok, George…” she paused to wipe her palm against her brow, “…I just hope Mr. Laughton can help.” George felt as if there was something very large that should be obviously apparent to him that he could simply not make out. “Help? Whatever with?” Stepping out of the car, Martha said, “Just follow me, George.” George followed her automatically. The office building that stood before him made no impression on George. It seemed to him to be vaguely familiar, if only because it looked like every other office building he had ever seen. The only distinguishing characteristic that drew George’s attention stood against a sign, which faced inward toward the building, showing the word “Integration” to all the open windows of the office. George followed Martha into the lobby towards a receptionist. “Well, well, welcome,” the rosy woman greeted them. The receptionist briefly glanced at a clipboard on her desk. Smiling broadly, she said, “George, Martha, so good to see you. Mr. Laughton is waiting for you.” “Thank you,” Martha said. “Wonderful, wonderful. Marvelous.” Martha pointed George in the right direction, and released him like a wind-up toy. Martha began to follow sadly behind him, when the receptionist quietly motioned to her. “Pardon me, Martha, how bad is it?” she whispered. “Worse than you can possibly imagine.” “Don’t worry, there’s a girl. Mr. Laughton will know what to do. No worries.” George and Martha had stood in the waiting room less than a moment, before Mr. Laughton appeared, a mountain of hand-shaking and ‘how-are- you’s. Laughton’s face had almost been split in two with the smiles that flashed across it in rapid succession. “Well, well, what a wonderful surprise, what a pleasant surprise we have here. My goodness, my. Yes, wonderful. Well, what seems to be our little problem? Yes, what indeed? What seems to be our situation? Goodness. My. And how are you George? Looking wonderful. Yes, my — goodness. What can be done? What can I do?” Martha gushed, “Oh, please Mr. Laughton, you have to help him. You simply must. Please, he woke up this morning half-mad, talking about twos and fours, apples, and a whole lot of other nonsense; and he won’t give it up. He’s even getting worse, talking about ‘certainties’ and ‘equations’ and who-knows what else.” “Who-knows, indeed. Oh my! Goodness! George? What’s all this? Come, George, tell me what’s on your mind. What can be done, I say. I say, what can we do?” George stared down at his feet, wondering fleetingly how a sheep might describe the look. “Well, it’s just that…” he paused to take a deep breath, “…I was looking at these apples this morning, four of them, you see; and I noticed that you could divide them into two groups of two and then add them back together again to make four, you see. Well, I was rather thinking that you could do that in general.” “I say, what? Divide apples, you say? In general? Come George, let me have it all.” “Well, yes, of course apples, I suppose; but I was thinking that you could make a sort of general principle out of it, you know. Like, you could say 2+2=4.” Martha spurted, “Do you see what I mean? I’ve been arguing with him all morning, but he just won’t listen to reason. You see how he is.” She pouted, jabbing her thumb toward George. Laughing vigorously, Mr. Laughton said, “Martha, why don’t you wait out here, while I talk to George inside.” Turning, he took George by the arm and led him through the doorway to his office. Laughing and closing the door behind him, he continued, “Wonderful! Marvelous! George, of course you can! 2+2=4? Quite rich, George. Quite funny. You’re absolutely right, George. Quite right. Let me show you something.” George looked around the small office, while Laughton searched his bookcase for a specific volume. The bookcase itself, was little more than a piece of rusted wire, bent and twisted in a long series of angles, upon which sat a great many volumes, resting against each other unevenly. Between George and the bookcase stood a tall, gold-framed picture of a dark, mahogany bookcase, filled with leather bound volumes. Next to the bookcase sat a cardboard box, upon which someone had scribbled, “Desk.” Another picture sat adjacent to the box, featuring a mahogany desk in the same style as the bookcase. Behind the desk sat a metal, foldout chair, next to which stood a picture of a high-back, leather-upholstered chair. In front of the box, George noticed another foldout chair, next to which stood a picture of a long leather couch. Turning from the bookcase, Mr. Laughton said, “George, have a seat on the couch; make yourself comfortable. Relax, George, that’s the thing. Nothing to stress over. No reason to be uncomfortable. Oh no! Not here, George. No reason at all.” George sat down in the chair. “That’s the spirit, George. What do you think about that couch there? It’s fresh in from Europe — very expensive, very, I dare say, sheik. Oh yes. My! Goodness! Now…about your revelation, your little hypothesis, let’s have a look.” Mr. Laughton retrieved a book from the top shelf and turned toward George. “2+2=4? Wonderful. Marvelous! It’s so avant-garde. It’s so prosaic. Very post-modern. Very, dare I say, edgy. That’s the thing, when you’re writing poetry; you want it in their faces, upfront and uncomfortable. I dare say. Not like here, not like now — oh no. You want to express something. Am I right?” “Well, yes, I do suppose that’s right. I do want to express something — ” “ — Of course you do, my boy, of course you do. Are you familiar, I wonder, with some of the ancient Greek poetry? I dare say you aren’t. It’s very dry reading, very drab, very prosaic — but quite profound, quite unique.” Taking the volume in his hand, he walked towards George and handed him the book. “Here’s a fellow, quite extraordinary, quite delicious, name of Euclid. Take a look at him now, if you like. Quite harmless, quite vague. He has written a neat collection of poems there in a unique “Earth meter,” I believe. He coined the phrase, you know. Very edgy. Of course, it’s a question of interpretation, mind you. Is he talking about sunsets or rose gardens? You see where I’m driving at, do you not? You see my direction?” George opened the book and turned a few pages. “A point is that which has no parts.” Flipping through the book, he looked up, “What if…I mean…suppose we interpreted him literally, you know?” Mr. Laughton paused and scratched his head before an enormous grin united his ears. “George, it might be genius! I think I see where you’re driving at, George, where you’re driving to — this is interesting. Very. Perhaps, you’ve been wasted as an accountant. Perhaps you should have been a schoolteacher for literature. Your grasp on these things is quite intuitive. Perhaps you are right. It could be that Euclid is using poetry as a medium to speak philosophically. There was that undercurrent of ambient philosophy with the Greeks — their form is always so legalistic, so rigid — always so difficult to understand what they were trying to say. But that’s another matter, George. Quite another, distant matter. The important thing, the thing of importance, the thing I cannot stress enough, George, is that all of this is quite normal. Quite usual. Quite healthy. You wouldn’t believe the quiet, normal people who come in here for a quick spot of advice on their way to work, now and again.” “So other people have had the same thoughts?” “Oh my! Yes, George. All the time. They just need a push in the right direction, like you, to help them say what it is that they want to express. Sometimes, you get a notion in your head, and it becomes difficult to separate this thought from the Truth. One moment, you don’t like your job, or you have the thought that you’d be better off skydiving than accounting. You don’t like skying diving, do you George?” “Why, I suppose not, no,” George said. “Of course you don’t. But sometimes you have this thought, and the next thing you know the only thing in your life worth a toss is the idea of throwing yourself out of an airplane. You see what I mean.” “Well, I’m not sure that I do; I’m not sure how all of this relates to me. I just had this idea, you know…I don’t really see what all of the fuss is about.” “Ah! Hrmmm…I see…Well, George, I hadn’t wanted to get into this — but, well, perhaps. Let me put it this way, George. We, you and I, George, are not terribly smart men. We’re competent, I dare say, technically proficient, you know — we function well, you and I. We are not great minds. We are not ‘the thinkers,’ George. There have been and will always be the great minds. These men wrestle with ideas. They’ve been doing it since the Greeks. Now, you would object to a carpenter, who began to lecture you about how to perform accounting, would you not? I dare say you would. As would I. Well, in the same right, it is the job of the great minds to do some amount of thinking. I say, it’s their job, you know. They think these thoughts; I say, these things have been thought through. They’ve been decided. Resolved. Sometimes, it’s true; the great minds have a change of opinion. Evidences come to light. Proofs. It’s true. It happens. But look at yourself, George. Are you a man to challenge a carpenter? Will you build a better house? Have you the tools, my good man? I mean, of course, have you studied? Have you been to university? Have you trained? Have you researched and conferred with peers the same caliber as yourself? No? Well, I am not such a man to be arrogant about these things. Not so proud that I dare to challenge what men smarter than myself have learned. Do you not think they are men just like yourself, with the best intentions? Men after the Truth? Men looking out for the good of their work and the pursuit of freedom? Do you not? These are men of science, George. Men of Progress. Yes. Now, I know you, George. You’re no more arrogant than I am. No, clearly not. You’re right of course, men have ideas. You have ideas. This is the right and proper thing for men to do. But more than this, George, we must learn how to express ourselves. That’s the thing. Thoughts crave expression. Expression is part of Freedom, is it not, George?” George nodded his agreement. “Of course it is. Now, we are civilized men, you and I — we are properly progressive. We are supporters of the Institution of Freedom, are we not? We are not the types to cry ‘fire!’ in a theater. We are not treasonous. No. We are both servants, you and I, to our proper commissions. There is no great fuss, you see — no cause for alarm. We must strive to do our best by doing that which we do well, as we have always done. You see what I mean, don’t you, George?” “Well, yes, of course. I suppose I do. I hadn’t thought of it all quite like that. You must be right, I’m sure.” George paused to look at the picture of the bookshelf. “That is a lovely bookcase.” “Quite right, George. Quite. Hmm…the bookshelf? Oh, yes.” Mr. Laughton paused to allow himself a confident grin. “Yes, I suppose that they do allow me certain privileges, certain liberties. It is a positive, yes. But these fine things,” he gestured toward the whole room, “are as much for your comfort and pleasure as they are for mine. I am only a servant.” “So this has been studied before, I take it? The great minds have researched it?” “Quite thoroughly, George. Quite. Volumes have been written. Critical responses. Whole libraries of poetry have been dedicated to questions such as these. The important thing, I say, the thing to note is that we know how to express ourselves. We do not wish to run about shouting that the sky is blue or the world is round or any such nonsense, not unless we mean to make a point, unless we mean to say something about Truth, unless we are exercising our Freedom, George. As long as we recognize the metaphor for what it is, we are free to use it however we feel.” “So I’m free to use it — ” “ — Free indeed, George! Free indeed. We mustn’t do anything to jeopardize Freedom, George. That is the golden rule, dare I say, the only rule. We cannot challenge our universal right to freedom — that is the thing that must be protected, valued, I say, defended at all costs. You are free to be free. And this great charge has but only one price: you must not limit freedom. It must free to grow and expand, as it will, free to flourish. Yes. If I were a smarter man than I am, I might speculate that this very notion may have been present before the great minds when they decided on such things as numbers and adjectives and metaphors — this very notion may have prompted their studies, their diligent inquiries, their painstaking research in some small way. But this is my speculation, mind you; only my humble hypothesis shared between close friends, only a wild guess — not a fact, not by any means a certainty. The important thing, George is that you not challenge the march of Freedom. Certainly not.” “I believe that I begin to see your meaning,” George began. “I must confess, I hadn’t thought of these things quite this way before. I hadn’t realized — ” “ — Worry not, George! You have no reason to feel anything but totally liberated, totally free. As I said in the beginning, there is nothing to worry about. Nothing unusual. No fuss, I dare say, no problems whatsoever. Martha, no doubt, has your best interest always in mind, so to speak. Marriage can be trying, you understand. It’s easy to react, to overreact, to jump to conclusions, I won’t wager. Easy to misunderstand. That’s why we must be careful, considerate, ‘forgiving’ so to speak. There’s no fault to be found, no reason to be ungrateful. No, no, quite not. Quite the opposite. Wonderful, really, all of it. No, I’ll just have a quick word with her to explain today’s misunderstanding, a quick note of reassurance passed between friends, a quick chat to sooth the seas.” George stood up from his chair, looking most pleased and grateful for Mr. Laughton’s sudden proposal of kindness. “Thank you. I would appreciate it. You know…” George stopped to peer again at his feet, which had been hidden so recently beneath the chair; satisfied that they were each in order, “You know, I do hate to be a bother.” Laughing and smiling preceded Mr. Laughton’s reassuring, “Bother? Don’t be absurd, George. No bother at all. None whatsoever. None at all. This is all quite usual. Quite normal. Ordinary. I am your servant. Just ask Margaret on your way out, and she’ll have transportation arranged to your office. No sense missing work, am I right, George?” “Oh, yes, most certainly. Thank you again for your assistance. I shill be on my way, then.” “Anytime, George, anytime. I am here for you. For you, I dare say, I am here.” Moments later, George observed his feet as they stood on the edge of the sidewalk looking toward the road. An unmistakably plain van pulled around the corner and stopped in front of George. Stepping between a picture of a stretch limousine and the door, he climbed into the vehicle. “To the Ministry of Accounting, then, George?” the driver asked. “Please, if you will, thank you.” Mr. Laughton took Martha into his office with the grave air of a surgeon about him. His many smiles had been replaced by concentrated frowns. “Martha…” he paused to place a hand on her shoulder, “you did the right thing, I say, the thing to do. George is in bad shape, Martha. It’s not the worst I’ve seen. I have seen worse. We need to watch him, though; keep a close eye on him. The thing to keep in mind through all of this is that you don’t want to keep the embers burning. You don’t want him to flare up again. You don’t want to fan the fire. You don’t want to suggest that his delusions are in fact delusions. You want him to feel quite ordinary, quite free. The feelings are the thing. When these common people snap, when the common man suffers from these mental fancies, when they take their dreaming a step too far, you must humor them to a point — to a point, Martha. We want them to adjust properly. Believe it or not, nothing is more dangerous to the cause of Freedom than the common man. The confused thinker, the dissident mind, that ghastly, uneducated mind, which begins to make leaps without a proper foundation, can incite a most unfree spirit among its peers. It’s not the thoughts that are important so much as the feeling. That sense of challenge, of pride, of awful vanity can spread infectiously from man to man. No, at all costs, George must not suspect that anything is wrong. Nothing unusual about his thoughts. He must believe them to be quite usual. He must begin to express himself properly. As I said, Martha, you did the right thing. Quite. But let us not react too violently to his thoughts. Let our reaction be of no reaction. Interpret his meanings for him. Compliment him on his cleverness and quick wit. That’s the medicine, that’s the ticket to be bought, that’s the course to be followed. Of course, do let me know if the situation becomes worse. Measures may need to be taken. Measures may be needed. We may need to follow certain paths. Indeed. Quite.” Martha extended her thanks as she nodded seriously throughout Mr. Laughton’s prognosis. Exiting the office, she allowed herself a sigh of relief. Once the door had been shut, Mr. Laughton turned toward his desk, glancing about the room. “Now, where did I set that Euclid?” Seating himself in his cubicle, George glanced up to look at the picture of his workplace, which portrayed a solid cherry desk, several gold-trimmed leather chairs, and a series of other odd pieces of furniture. Shifting uncomfortably in the metal foldout chair, upon which he sat, he grasped the ringing phone. “Hello?” “Yes, of course.” George stood and walked toward the department manager’s office. He had barely begun to knock when the door swung open to greet the manager himself, who peered down at George through a pair of horn-rimmed glasses, which seemed to be struggling desperately to remain in place atop the manager’s nose. Smiling enormously, he swept George into the office with a broad welcome. “Well, George, it’s good to see you. Come in, come in.” The manager closed the door behind him. “We’re all so glad you’re well. Ms. Mansfield told me that you had called in sick; now, here you are, right as rain! I talked to Martha a few moments ago — she called to make sure you had arrived here safely. I just wanted to talk to you privately for a moment, to express how valuable you are to this department. You are valuable, George. What’s more, to show our appreciation, I think you may have noticed that we have taken the liberty of refurnishing your office. How do you like it?” George beamed, “It’s wonderful, thank you.” “Think nothing of it, George. We’ll spare no expense for you, George. Not for you.” The manager stopped as if to assess the situation. Apparently finding everything in order, he continued, “Well, that about covers it. I can expect the usual finance report from you today?” Nodding assuredly, “Yes, of course.” “Wonderful. I know you haven’t had a chance to go over the books yet, so to speak; but can you tell me ‘off-the- record,’ have we got any money?” “Yes, I would say that we’ve got quite a lot of it.” The manager laughed instantly and heartily, “That’s too rich, George. Quite a sense of humor you’ve got. Keep up the good work then.”