A list of programs I've written and now recall. There are lots, organized first by where I was.
20% named and 15% documented. Even at this low penetration, there are some good reads here.
The programs I remember the most have always been created in a social or service context.
Acquiring Mastery
As a student, my programs were not complete until I had shown them to my friends.
Highland High School 1964-67
Purdue University 1967-1977
Tektronix 1977-1987
Home Computing 1977 - Present
Sharing the Knowledge
Work for hire established bounds. But I always felt entitled to create outside of them when it served the greater goals of a project.
Knowledge Systems 1987
Wyatt Software 1987-1990
Cunningham & Cunningham 1990-2019
IBM Consulting 1995
Unix Administration 1994-Present
Distinguished Positions
I continue to code. My reputation opens doors but my chosen medium, programming, confuses those who invite me in.
Microsoft 2003-2005
Eclipse Foundation 2005-2007
AboutUs 2007-2011
Citizen Global 2011-2013
Nike 2011-2012
New Relic 2013-2022
Federated Wiki 2011-Present
# Interviews
Brainstorm Interview with video showing off projects.
Gadget Basement video interview by Scott Hanselman.
.
I've been touched in some way by every programming language I've learned including some quirky ones like APL and Lisp. I carry in my fingertips basic idioms drawn from daily use of Pascal, Smalltalk and Javascript in each era of my programming life.
My first jobs were in newspaper photography, pizza delivery, steel mill labor, and air-conditioning repair.
Lasting Technology I've turned to over and over.
Presidential Platform a fantasy of what-ifs.
The Ward Way to write interesting software.
.
Unsure what we will find we try scraping this emergent schema and render it as aspects.
CLICK NEIGHBORS code CODE index 2 CLICK SOLO CLICK POPUP state CLICK PREVIEW items CLICK DOWNLOAD index.json
let pages = new Map() let site let Graph export async function index(clicks) { Graph = this.api.graph let context = this.context let page = context.page let slug = context.slug site = context.site pages.set(slug, page) let tree = await scan(slug,clicks) this.json = tree let result = tree.children.map(tree => ({name: tree.title||tree.slug, graph:aspect(tree)})) this.aspect =[{id:tree.title,result}] this.items = missing(this.neighborhood) return `${pages.size} pages` }
async function scan(slug, clicks) { if(clicks == 0) return {slug} let page = await pages.get(slug) if(!page) return {slug, page:null} let title = page.title let slugs = page .story.map(look) .filter(item => item) load(slugs) categories(page) let children = await Promise.all(slugs .map(slug => scan(slug, clicks-1))) return {slug, title, children} }
function look(item) { if(!item.text) return null if(!item.text.startsWith('[[')) return null let parts = item.text.split(/\[\[|\]\]/) let slug = wiki.asSlug(parts[1]) return slug }
async function load(slugs) { let doing = slugs .filter(slug => !pages.has(slug)) .map(slug => pages.set(slug,fetch(`//${site}/${slug}.json`) .then(res => res.ok ? res.json() : null))) }
function aspect(tree) { let graph = Graph() walk(graph,tree) return graph } function walk (graph,tree) { let nid = graph.addNode('',{ name:(tree.title||tree.slug) .replaceAll(/[ -]/g,"\n"), slug:tree.slug, site:site }) for(let child of tree.children||[]) { let cid = walk(graph,child).nodes.length-1 graph.addRel('',nid,cid,{}) } return graph }
function categories(page) { let items = page.story .map((item,i) => Object.assign({i},item)) let start = 0 let title = "none" let heads = [...items,{i:items.length,title:'done'}] .filter(item => item.text?.startsWith('<h3>')) .map(head => { let slugs = items .slice(start,head.i) .map(look) .filter(slug => slug) let result = {title,slugs} title = head.text start = head.i return {title, slugs}}) console.log(page.title,heads) }
function missing(code) { let here = code.map(info => info.slug) let have = new Set(here) let found = new Set(pages.keys()) let links = s => `<ol>${[...s] .sort() .map(slug => `<li>${slug}`).join("\n")}` let missing = links(have.difference(found)) let surplus = links(found.difference(have)) return ["Missing",missing,"Surplus",surplus] }