Joseph Hallenbeck

Anno Domini 2018

December 22, 2018

Tech Reading List 2019

Filed under: Software Development part of Annual Reviews

test driven development cover

Books

Here’s my 2019 reading list for tech and career focused improvements. Guaranteed to change the minute that I wrote it down. A handful of these are good books that I’ve already read and need to revisit like Domain Driven Design, Implementing Domain Driven Design and The Go Programming Language. Others, have sat on my shelf for a long time unread (Code Complete 2) and are due for a second attempt.

For Improving Legacy Code

Architecture

Soft Skills

Languages

DevOps

Tech Focus

Last year, I was able to check learning Ansible and Docker off my todo list. I feel rather comfortable with both at this point. Yet, the world of web development ever marches onward. Here is what I would like to focus my attention on getting up to speed on this year:

  • React & Modern Javascript Development
  • Go for Web API Development
  • Godot, Solarus or Amethyst Game Engines (have to dream)
November 23, 2018

Todo.txt Practices

Filed under: Software Development

In 2016, I wrote about switching back to Todo.txt. At the time, I outlined the rough system I was using. In the two year’s since, I’ve refined my Todo list process greatly and wished to share.

The Todo.txt format has a ton of flexibility allowing the user to go wild. Very few articles out there seem to illustrate how individuals use the format for themselves. This leaves a lot of stumbling about to create good practice and habits.

Basic Practices

  • All tasks must have a project and context and only one project and context
  • The main todo list represents tasks to be done this quarter. A seperate tickler list is used for tasks in future quarters.
  • Always keep the main todo list under 120 tasks.
  • To reduce clutter, use “project stubs” as placeholders for upcoming projects. Maintain the project sub-tasks in their own todo lists and import them only once the “stub” reaches priority C.
  • Liberally use the recur plugin for daily and weekly interval tasks
  • Generally avoid using meta-data tags
  • Doubly do not use due dates. Manage appointments and meeting times in a dedicated calendar app. Add upcoming appointments to the main task list during the fortnight review and daily reviews.

Priorities

Use only priorities A-D, and with each having a particular meaning.

Priority A Tasks I am working on right now, never above three tasks
Priority B Tasks I will do today
Priority C Tasks I will do this fortnight
Priority D Blocked tasks to be priortized A-C when they become unblocked

Everything else is deprioritized, and typically hidden from view.

Projects

Projects both represent ongoing epics whose tasks are completed sequently as well as generic “grouping” of similar tasks. A few common projects are listed below.

+chores By taking the unison of the chores project and different context I can create sublists for housework (ls +chores @house), yardwork (ls +chores @yard) or errands (ls +chores @springerville).
+budgeting Dealing with anything related to personal finance
+admin Work related administrative tasks such as filing paperwork, planning meetings, or reviewing tasks
+literature, +games, +films Representing each form of media
+hike Details trails and distances hiked
+menu Identified recipes for this fortnight’s meals
+social Social outings
+wellbeing General medical and meditative tasks
+ops System related tasks

Contexts

Contexts are used to identify where a tasks will probably be done.

@office Task completed in the home or mobile office, and generally denotes a need for networked computing power, e.g. desktop, laptop, or phone.
@house Task completed at home indoors
@yard Task completed at home in the outdoors
@out Task completed in the outdoors, the wilderness within a half day’s drive
@alpine Task is an errand, completed in the local Alpine community
@springerville, @reserve, @showLow, @phx, @abq Task is an errand, completed in one of the larger neighboring communities

Fortnight Review

Every two weeks, I complete a full review of the main and tickler todo lists.

Clean Up

Evaluate all forms of inboxes: kanban, e-mail, phone, calendar. Add upcoming appointments, tasks to the main todo list.

Clean up dead or dangling tasks that are no longer needed. Then evaluate the list to make sure the existing tasks conform to my practices. Aggressively cull tasks, create “project stubs” and move clutter into seperate files.

Prioritize

Create a variety of views of the main todo list. Evaluate each unprioritized task and determine if I must or should work on that task in the next two weeks and if so bump prioritization to C.

De-Prioritize

Evaluate all tasks prioritized A-D. Determine if I must complete each task, or if it can wait. Favor trimming the overall list of prioritized tasks to shorter to avoid accidentally overburderning a week.

Nightly Review

Every night at 21:00, a cronjob runs the command faketime -f '+1d' todo recur which appends to the main todo list any daily or weekly recurring tasks.

At this time, I clean out my inboxes noting appointments and meetings for the following day, and then evaluate tasks A-C, determing if they should be culled, deprioritized, bumped to another day (C), or bumped to be worked on tomorrow (B).

Tmux Set Up

I aleays have a “todo” session running in Tmux which when using panes and the watch add on, I can create a window that shows a variety of always up-to-date views of the state of my main todo list.

Commonly, I keep a “today” window for referencing my day’s work and a “planning” window for when I’m planning the next day’s agenda.

Today

today

The today window displays my todo lists of tasks to be done today. From left to right we have:

Upcoming Tasks (t watch lsp c-d) Displays upcoming tasks in the fortnight and blocked tasks
Today’s Tasks (t watch lsp a-b) Displays my currently active tasks and tasks planned for today
Today’s House Tasks (t watch lsp a-b @house) Tasks to be done around the house
Today’s Office Tasks (t watch lsp a-b @office) Tasks to be done around the office
Today’s Yard Tasks (t watch lsp a-b @yard) Tasks to be done in the yard
Working Pane Pane not running watch for manipulating the todo list

Planning

planning

The planning window is used during the nightly review of the todo list. It mirrors the Today list in terms of the Upcoming, Today, and Working panes. However, the context-specific panes are replaced by project-specific panes displaying either the breakdown of specific projects (t watch ls +blog) or for larger projects spread across multiple contexts, the unison of a project and context (t watch ls +chores @project).

September 21, 2018

Entity-Component Systems

Filed under: Software Development

ecs

Catherine West gave an excellent closing keynote to Rust Conf on using Rust for game development which delved into using an ECS at the core of a game engine and in particular focusing on Data Driven architecture over a more traditional OOP approach.

What is an Entity-Component System (ECS)

ECS is an inversion of the OOP principals. Rather than workig from a subject-verb perspective, that is “The Dog acts,” we invert the language to make the verb promenent: “The Dog is acted upon.”

We do this by removing all data and methods from the “Dog” entity, and focus our design around verbs: input, animate, render, etc. The verbs are components, the thing acted upon is an entity which is a type.

This is a kind of Data Driven Programing where the data defines the implementation details of the business logic rather than the code defining the available business methods.

What is the Benefit of an ECS

An ECS removes the need to hard-code business relationships between entities such that rapid prototyping of business logic becomes possible.

This results in:

  • Building systems where stakeholders can modify business rules on the fly
  • Building concepts that cross-cut through many objects
  • Increased agility
  • Can take advantage of parallel processing
  • Becomes a replacement of the observer pattern

Cowboy Programming in Evolve your Heirarchy describes some of the disadvantages of moving forward without an ECS. Namely, a deep heirarchy that is difficult to manage, and the creation of god-objects to resolve common code duplication.

Notes on Implementation

T-Machine posits in Entity Systems are the Future that an ECS is not a programming paradigm but a type of system that exists in a larger OOP application that solves issues that OOP handles poorly. In practice it becomes an encoding of our business relationships into either a in-memory RDBMS or atual RDBMS (depending upon thuroughput needs).

A component, according to T-Machine, is an aspect of an entity. It contains a bucket of properties that define the entity from that aspect.

A system, according to T-Machine, contains all the actions that can be performed to mutate a component. A system performs it’s actionas against all entities with a particular aspect.

Example: We have dog-1, dog-2, dog-3. Each is an entity (in production usage these would be GUIDs). Each of these entities is entered into the component table as having the moveable component which pivots to a table defining the position and velocity. The move system runs, applies velocity to each component’s position and then updates the position properties.

In practice our table structure looks like:

Component table:

id identity name description table
1 1234-abcd-efgh renderable Render entity render
2 5678-efgh-lmno movable Update pos. movement
3 9012-lmno-pqrs destructable Manage health destruct

Entity table:

id identity
1 1234-abcd-efgh
2 5678-efgh-lmno
3 9012-lmno-pqrs

Entity-Component pivot:

id entity_identity component_identity component_props_id
1 1234-abcd-efgh 1234-abcd-efgh 1
2 5678-efgh-lmno 1234-abcd-efgh 2
3 1234-qbcd-efgh 5678-efgh-lmno 2

Finally the component data table (“movement”)

id pos_x pos_y velocity_x velocity_y
1 10 20 0.5 0
2 30 40 0 1

As an explanation of the above, we have three entities and three components. The first entity is renderable and movable, the second entity is movable (but not renderable). Looking into the movement table we see the first entity has an x/y position and is moving along the x axis. The second entity has an x/y position and is moving on the y axis.

We can add and remove entities from these tables.

T-Machine also notes that we can have “assemblers” to create various component quickly by bundling together similar collections of components and naming them. I do wonder if some factory or abstract factory style pattern fits in there.

June 29, 2018

Twenty Five Haunts

Filed under: Wanderlust

cover

The economist reports that people have roughly twenty-five usual haunts. Let’s consider what my haunts might be:

  1. Home

Local Shopping

  1. Alpine Mainstreet (Foxfire, Country Market, The Grill, The Post Office)
  2. Springerville Market (Safeway, Western Drug)
  3. Showlow/Lakeside/Pinestop Market (Eddie’s Mountain Coffee)

Big City Shopping

  1. ABQ
  2. Phoenix
  3. Tuscon

The Local Trails

  1. Correction Road
  2. George’s Lake
  3. Luna Lake
  4. Terry Flat
  5. Unnamed NM Border USFS Road
  6. Blue River
  7. Mt. Baldy Area
  8. Greenwood Area

Regional Hiking Haunts

  1. Clifton/Morenci
  2. Reserve/Glenwood
  3. Bluff, UT
  4. Wyoming/Idaho (Island Park, Driggs, Jackson Hole)

Long-Distance Traveling Haunts

  1. Durham, NC
  2. Spearfish, SD
  3. Mt. Angel, OR
  4. San Diego, CA
  5. Rhinelander, WI
  6. Sioux Falls, SD

leuchtturm

Sometime last Winter Nelson Elhage’s essays on using lab notebooks for software engineering made the rounds on Hacker News. One item in the early essay struck a cord with me:

Computer scientists are taught to document the end results of their work, but aren’t, in general, taught to take notes as they go

This seems to be current standard protocol for software versioned with git where care is taken to currate the repository history. Rather then record every wrong step and dead-end branch we are taught to prune and re-write the record by squashing our merge histories. A half-dozen commits showing the history of iterating on a problem are, in an instant transformed into a single commit as though the solution sprung spontaneously from the prior commit.

The result is that there is little record of the wrong turns that you took or the iterative steps taken to disover and correct errors from the initial design. Without a record of what has already been tried, it is easy to unneccessarily repeat your own footsteps or forget the reason behind a particular design call.

How I Use It

I may work with a lot of folks with backgrounds in science, but I myself was not trained in the discipline. Likewise, most of my work is hardly novel or experimentive – I make bog standard business software. So the metaphor of an “experiment” can feel stretched at times.

Digging into the question of what is a lab notebook and how does one keep one, I stumbled upon an excellent document put together by the National Institutes of Health. I derrived from it a practice that I started last December and continue to refine.

What is a lab notebook anyway?

The lab notebook is a bound append-only volume that provides a record of design decisions, procedures, tooling, observation, and background/reasoning for a unit of development work. In my case, it is a Leuchtturm1917 bound notebook which already includes an index, numbered pages, and space to record the date of each entry.

What it is not: a journal, a record of communication, or a place to compile standard operation procedures.

What does an entry look like?

Each entry is composed in pen (remember it’s append-only!). I begin a new entry for each user-story, bug report, or task as I begin work on them. The entries themselves become intersparsed as they represent the flow of my attention through the work day. I may take up an entry for a user-story, on the next page start an entry for a bug, then pick up the user-story again on the following page.

Each entry must include the following:

  • The date the work was done
  • A reference title (to connect together intersparsed entries)

Each entry may have the following sections:

  • The goal which states in one sentence our desired outcome
  • A discovery section which states any pre-conceptions and predicates to our problem.
  • A design plan which states, given our discoveries, the solution we believe will resolve the goal.
  • A test plan which states how we will determine that the design plan has met the goal
  • An observation section, which is perhaps the most important section and I will detail below
  • A next steps section to highlight any new tasks that may have spawned from the completion and observation of the prior work

Any given section can contain UML or SQL schema diagrams, prose, or any other conceivable free-form diagraming of my thoughts.

Observations & Triggers

The observation section is an attempt to keep a running log of the development process as it takes place. In particular, this section:

  • Records each step completed in the design plan
  • Records each deviation from the original design plan and why
  • Additional discoveries (references, unexpected findings in the code, external change requests, refinement of the concepts and domain language)
  • Each test run (both automated and manual), the outcome (both failure and success), and any changes necessitated by observing the software in action

Once completed, the observation section is often the longest and most useful component of an entry as it comes to contain both a record of all tests completed (and implicitly all test branch we failed to examine) and a record of all design decisions along with the catalyst for making each of those decisions.

I find the observation section is best managed using bullet journal syntax as I record both notes on discoveries or tests and tasks as they are done or occur to me in a free form mixed list. Skimming back each morning over the list gives an excellent view of my thoughts for where I left off the day prior.

However, this only works if I remain disciplined. Thus, it is best to keep a mental list of “triggers” to activate pausing and updating the observations section. Mine include:

  • Every time a design decision is made or rejected
  • Every time we must reference an external source or look up a section of code
  • Every time a test runs

Benefits

Largely, I have found that keeping a lab notebook, if done with discipline, has been a wonderfully beneficial experiance as it:

  • Cuts down on procrastination and time to mentally queue a design after a pause from a given task since where I left off is plainly recorded
  • Provides a written record of work for clients, employers, and stand-ups
  • Provides a written record should a coworker join or take over a task, not to mention your future self
  • Reduces the possibility of “retreading” rejected designs or completed test cases
  • Encourages continuous refinement and improvement of the design plan through the course of implementation

Cover photo: Trost, Fabian. “Leuchtturm” (CC BY-ND 2.0)

Kynda

Years ago I filed to incorporate a limited liability company. I did nothing with it since, but now find that I am at the juncture in my career when I should feel comfortable with taking on and managing client work beyond the stable income of my employer. This is the natural progression of a remote worker, and while I have no plans of leaving my day job, diversification in this age is absolutely necessary.

Kynda Consulting will focus on serving the White Mountain area, by providing website development and hosting at the local level, and bringing economic development to the region by enabling larger clients to outsource work to rural remote freelancers.

Primary services that I will focus on:

  • SMB custom website design, hosting, and maintenance promoting local business and nonprofit interests.
  • Staff augmentation for existing agencies and software products
  • Workflow and business automation to improve the efficiency of client employees and “automate the boring stuff”
  • Consulting services to address client legacy software product issues including feature additions, bug fixes, feature-complete rebuilds, architecture road maps, and security vulnerability audits
  • Consulting services to help existing teams incorporate BDD and DDD techniques into their architecture and testing strategies
  • Exploration into identifying potential SAAS ventures that solve SMB needs
  • Exploration of the production of financially solvent independent games, middleware, or freelance contributions thereof

This venture will be a new and exciting challenge for myself. It will challenge me to demonstrate that I can ship a client project (I can), but also to learn how to land a sale – a skill that I’ve yet to develop and terrifies me.

The Pragmatic Programmer

Continueing my book club notes on the the Pragmatic Programmer by Andrew Hunt and David Thomas.

Chapter 3

  • The best way to store knowledge is in plain text, not binary blobs
  • The drawback to plain text is that it comrpesses poorly, and may be expensive to process. This doesn’t seem particularly relevant with modern computers, but I suppose embeded systems still suffer this drawback.
  • Plaintext helps insure against obsolescence and eases testing
  • Shell beats GUI
  • Get good at one editor until it’s like playing the piano
  • Use source control (yeah we’re doing the obvious now)
  • Embrace debugging as just another form of problem solving
  • Turn your ego off when debugging. This is made possible by focusing on fixing the problem and not assigning blame
  • Avoid panicing when debugging, accept that the bug is possible, resist the urge to fix the symptoms while leaving the cause
  • You can only get so far with automated testing, at times its fastest to simply interview the user
  • Rubber Ducking, attempt to explain the problem to someone else, if it’s a rubber duck
  • Learn a scripting language (or these days, learn a systems language)
  • Have code generators actively monitor and rebuild generated code

Chapter 4

  • We are taught to code defensively and validate against bad input. We should also be defensive against ourselves
  • Design by Contract (DBC). Define a contract of the pre-conditions for a method call and the guranteed post conditions that method promises. Contstraint invariantss to occuring only within the call itself.
  • Be strict with the pre-conditions and make only small promises for the post conditions
  • Crash early, don’t ignore an error or assume the system will resume stability once one occurs
  • Use assertions to guarantee that events that won’t happen can’t happen. Keep assertions in production to detect these “impossible” events during operation (you won’t detect these during a normal test pass anyway)
  • Exceptions should rarely be used as they interupt the program flow.
  • If you remove all the exception handlers, then the code should crash.
  • The routine that allocates a resource is responsible for deallocating it.
February 09, 2018

Shell Notes: Find and Tree

Filed under: Software Development part of Notes

Continuing my deep dive into shell and editor commands to find, useful tools that I’m not taking full advantage. This week is the Find and Tree commands.

Find

Find is used for traversing a tree of files and performing some operation on them. It is one of the core Unix utilities and fairly universal on systems. My big discovery this time is the realization that I can use find for more than just searching for files. I can use find to perform operations on the results. There are multiple actions besides the default -print, e.g. -delete and -exec both open up a world of possiblities that I would have otherwise resorted to piping the results into a loop (or resorted to Python) to resolve.

$ find [-H] [-L] [-P] path... [expression]

The flag -P is the default behavior. -L specifies find to follow symbolic links. -H will follow symbolic links while procesing the command line arguments. The path parameter is required and can use globbing similar to ls or other terminal commands.

find excepts a number of operators for fine tuning our search. ( expr ) forces precedence, ! expr evaluates true if the expression is false, expr1 -a expr2 evaluates expr2 only if expr1 is true, expr1 -o expr2 evaluates as true if either expression is true. For example:

find . -name 'fileA*' -o -name 'fileB*'

Searches the current working tree for a file whose names start with “fileA” or “fileB.”

Example commands:

$ find . -name 'my*' Searches working directory for files starting with “my”
$ find . -name 'my*' -type f As above, but excludes directories and searches only for “regular files”
$ find . -name 'my*' -type f -ls As above, but pipes the results into the ls command.
$ find . ../Done -name 'my*' -type f -ls' As above, but this time we are searching both the working directory and the ../Done directory!
$ find . -name '*md' -o -name '*latex' Find all markdown or latex files in the working directory
$ find . -name '*.md' -type f -exec chmod 664 {} \; Finds all markdown files in the working directory and executes chmod 664 replacing the value {} with the path to the file. Note the required \; at the end of the command and that the command cannot be placed in quotes.
$ find . -type d -empty -delete Deletes all empty directories in the working directory. Note, that the delete option can simply be used as a replacement for the default option of -print. That is, whatever whould hae been returned without the -delete is what would be deleted.
$ find . -iname "*MD" Case insensitive name search
$ find . -size 100k -a -size -500k Find allows for searching by file size.
$ find . -mtime 30 Find all files modified in the last month. We can do -mtime +50 -mtime -100 to find files modified more than 50 days ago and less than 100 days.
$ find . -cmin -60 Find all files modified in the last hour. find . -mmin -1 does the same thing but with an interval of hours.

Tree

While reading on find last week, I stumbled upon tree. Tree is one of those commands that I ocassionally recall, think is really cool. Then completely forget about.

Tree gives you the ability to generate a visualization of the directory tree, much like the old Windows Explorer provided a tree view of your directory.

In simplest usage, you simple call tree, and it outputs a tree representation of the current working directory. If we want to display a different directory, we can provide that for the first argument: tree ~/Documents.

By default, tree displays symbolic links showing where they point towards. However, if the link is a directory, it does not, by default recurse into that directory.

Flags:

-a Display hidden files
-d List directories only
-f Display full paths
-i Don’t indent/show tree lines. Use in conjunction with -f to create a file list
-l That is a lowercase “L,” do recurse into symbolic directories
-P pattern or -I pattern List files that match the pattern, or list files that don’t match the pattern
-u, -g, -p, -s, -h Print the user, group, permissions, size in bytes, or human-readable sizes

The Pragmatic Programmer

Recently, I’ve been running a book club to cover the contents of the Pragmatic Programmer by Andrew Hunt and David Thomas. One of those volumes that has been held up, forever, as a text that any good Software Engineer should have read. The text itself is rather sound, although starting to show it’s age in the era of software-on-the-browser.

Probably not going to do much of an articulated look at the book. Rather, I think I will simply post my cliff notes as I, or we go through each chapter.

Chapter 1

  • Take responsibility for actions, career advancement, project, and day to day work while being honest about your shortcomings
  • Understand that responsiblity is something you actively agree to.
  • You don’t directly have control over the success of things that you take responsibility for.
  • You do have the right to not take responsiblity for an impossible task, but if you do accept responsiblity, then you are accountable for it’s success
  • Provide options, avoid lame excuses
  • “Broken windows” in the code encourage the code base to degrade over time
  • “Start up fatgue” sets in when you make a greenfield request too big. Start small, and work to larger
  • Keep the big picture in mind to avoid creep
  • Software needs to be good enough for the the user; the maintainer, and lastly; for yourself
  • Ask the users how good they want their software to be
  • Great software today is often preferable to perfect software tomorrow
  • Know when to stop making improvements
  • Your “Knowledge Portfolio” is your most important asset, but it has a half-life. Invest in it regularly, manage high and low risk skillsets, and keep a diverse portfolio
  • Some ideas to keep on top: learn a new language each year (particularly ones that introduce new paradigms), read a technical book each quarter, read non-technical books, participate in user groups and conferences, stay current on industry trends
  • You’re communicating only if you’re conveying information. Know what you want to say, know your audience, choose your moment, choose a style, make it look good, involve your audience, be a listener, and get back to people

Chapter 2

  • We are always maintaining software, it is a routine part of the development process
  • “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system” (DRY)
  • Wrong comments are worse than no comment at all
  • Keep code orthogonal, that is eliminate dependencies such that internal changes in a module do not change the external interface.
  • Orthogonal code reduces risk by isolating bad code, allowing for agile development, easing tests, and reducing vendor lock-in
  • Avoid excessive team overlap
  • When designing architecture, ask if you were to dramatically change the requirements how many modules must then change?
  • Develop shy code that doesn’t reveal it’s internal impelementations
  • Avoid global data
  • Use the stategy pattern to avoid functions with similar bodies
  • Do not approach projects with notion that there is only one way to do it
  • When a critical decision is made it narrows the pool of future possible decisions; put off such critical decisions until later by making code reversable
  • “Tracer Bullets:” start with a small, single aspect of the final system and complete the piece first. Iterate upon that piece to fully flesh out the system. Integrate daily, rather than building a single monolith and then integrating
  • Prototyping generates disposable code. Stakeholders must be made plainly aware that a prototype is not a finished product and cannot contribute to the final production product
  • Prototypes are creates to analyze and expose risk. They are designed to explore a single aspect of the software
  • Use prototypes for things that haven’t been tried before, critical systems, and anything unproven or experimental
  • The language of the domain suggests the programming solution
  • You can implement the domain language into an interpretive language
  • When estimating use the units of the quote to suggest uncertainty, e.g. a project doable in a sprint is quoted in days, a project doable in a month or two in weeks, a project doable in over a quarter, in months, etc.
February 02, 2018

Week One on Mastodon

Filed under: Journal

Mastodon

Giant scattering of random thoughts over the first week using Mastodon:

  • God this interface is confusing. Local, federated timelines?
  • Local timeline is just everyone posting publically on the instance
  • Federated timeline is all posts on the instance plus any posts from federated instances that my instance are interacting with
  • This is actually quite fun. The local timeline really encourages me to just reach out, favorite, “boost,” or reply to any public post that strikes my fancy.
  • There’s a lot of really great conversation going on, particular about the nature of social media, technology, art.
  • Advertising this as a “Twitter” clone missing a lot of the point. This is more like an async or threaded version of IRC. There’s quite a firehose of comments on the local timeline, each inviting me to just hop in and start chatting away on the topic.
  • I’m actually having a lot of fun with this, more fun then I’ve had since the old BBS days. The social barrier (the thought that someone is going to judge you for hoping into their feed) is rather low.
  • I realize that my initial impression with Twitter was, this is a really boring platform. Everything is empty. The platform is encouraging me to follow some celebrities or news organizations. The emphasis was on becoming a follower high-volume “influencer.” It’s another consumption platform. I quickly felt like if I wasn’t a celebrity or obsessive interested in growing my following then I had nothing to say on the platform and should just shut up and listen. Most of the big names were insipid or posted so much that I couldn’t keep up. It took a long time to fine tune a list of eighty people to follow before I started to find the platform useful. I’ve probably posted more on Mastodon in a week then I have posted on Twitter in the two years that I actively used it.
  • People are nice. They reply to your random interjections into their threads. The community is generally friendly. There’s a progressive vibe, but not the kind where people are screaming their frusterations and outrage at the state of the world constantly.
  • You know what. Let’s just perma-block Twitter and Facebook. Still need the later for people stuck on Messenger, but if I’m going to be wasting time on a social network, I think I know which one I want to be spending time on. Love that multilingual is the default.
  • Traditional social media seems so balkanized – I have to intentionally leave the Anglosphere. As someone whose spent years trying to learn French and Spanish, its nice to not have to intentionally go hunting for it. Love seeing Arabic and the east-Asian scripts as well. Not turning them off. Can’t read them. But seeing them will make me want to try someday. Makes me feel much more cosmopolitan. The internet of the last decade has grown far too provincial. Whereas my early online friends hailed globally – the UK, Finland, Norway, Australia, Japan, France, Germany, Brazil the recent fashion has been to push people into regional or cultural groupings.
  • On one hand, don’t worry about federation. On the other hand, its all about the federation. Federation maintains the small community feel. There may be 1 million Mastodon accounts out there, but there will only be a small handful of active accounts on your instance. Names quickly become recognizable. Reputations, interests, etc. mill in much as they would on a small community bulletin board or an active chat room. What federation does though, is allows you or ot her community members to reach out to other instances and invite interesting people to participate in your local conversation. Thus if someone from your instances likes or boosts an article off the federated timeline, then it gets promoted to their local followers. And if someone follows a user from another instance, then that users public posts populate into your instance’s federated timeline. The dynamics of this system were not obvious to me at first, but quickly becomes apparent in it’s ability to create small social hubs, like a virtual pub where “everyone knows your virtual name.”
  • One thing that I now realize is just how tense my online precense has become with the fear of judgement, that words flung into the void would come back to haunt me. I have become very precise, almost shy in the expression of ideas. Mastodon brings back a kind of immediacy that melts away very quickly. Rapidly, I am posting off the wall thoughts, engaging in deeper conversations with people, offer to help, doing things that I never imagined on Twitter or Facebook which have both become such public-you-are-a-brand style interfaces
January 26, 2018

Shell Notes: Vim XDEBUG

Filed under: Software Development part of Notes

Exiting Vim

Continuing my deep dive into shell and editor commands to find, useful tools that I’m not taking full advantage. This week is debugging PHP using Vim and XDEBUG.

XDebug in Vim

XDebug has been installed on every development machine that I’ve worked on for as long as I’ve worked. It outputs wonderfully formatted stacktraces and var_dump values. However, the interactive debugger side of XDebug remains little used due to the overhead of setting it up.

When I developed using PHPStorm, the interactive debugger seemed extraordinarily unstable. After taking the time to set up a project, map the directories correctly, configure ports and then trigger the debugger it would run for a few lines then halt. I eventually stopped using it.

The Vim VDebug plugin, running locally on the server seems a much more stable implementation. However, I still use it much less often then I should. Largely, this is due to comfort level. I’m not comfortable enough with it, so I don’t bother triggering it.

Yet, it would be easy to become comfortable. Any time that I want to inspect the value of a variable under an operations, instead of echoing or var_dumping that value out – put a breakpoint, and trigger the debugger. After a while, it will become like second nature to enter the debugger instead of printing the variable. Consequentially, if after inspecting the first variable, I discover the need to inspect a second variable, well the debugger has already started and inspecting the second variable is a zero-cost operation.

Installing and configuring XDebug, I leave to the documentation. Initiating the interactive debugger is done through VDebug, a Vim plugin that works with PHP, Python, Ruby, Perl, and NodeJS debuggers – or as it’s documentation says, any debugger that implements the DBGp standard.

Starting the XDebug Plugin:

Debugging starts by selecting a breakpoint line, navigating to it and pressing <F10> to toggle the breakpoint. Second, we start the debugging session by pressing <F5>. We then have 30 seconds to start the session which can be done in one or two ways.

If accessing our PHP script via the browser, we add XDEBUG_SESSION_START=$ideKey to the URL query string. If accessing our script via the commadn line, we start the script via:

php -dxdebug.remote_enable=1 \
    -dxdebug.remote_autostart=On \
    -dxdebug.idekey=$ideKey \
    -dxdebug.remote_port=9000 \
    some-script.php

Where $ideKey by convention is the unix username and port is 9000 or whatever port XDebug was configured to use.

Debug controls:

<F5> Run to next breakpoint/end of script
<F2> Step over a function or method call
<F3> Step into a function or method call
<F4> Step out of a function or method call
<F6> Terminate script
<F7> Detach from script, run to it’s normal end
<F9> Run to cursor
<F10> Toggle breakpoint
<F12> Evaluate variable under cursor

When to Step Over, Into, or Out

The step over, into, and out of always tricks me up. First, contrary to what I thought, you can’t use step-over to step over loops. They only effect whether you are stepping into, over, and out of function or method calls. Essentially, if a function is to be called on the line under evaluation if you step-into it, then we step into the function and debug line by line that function. If we step-over it, then the debugger executes the function and takes us to the next line in the current context. Step-out is used if we first stepped into a function and now want to simply execute to the end of that function and step back up to the calling context.

January 12, 2018

2017 Cultural Review

Filed under: Literary Criticism part of Annual Reviews

One sentence micro-reviews of each film, show, book, and game that I watched, read or played over the last year. Each item recieves a letter grade from F (terrible) to A (a must watch/read). This year, I add some additional signfiers:

(B)
Reserve for items that are so good and re-watchable/readable that they deserve to bought as a physical addition to my library.
(R)
This is a re-read or re-watch of a volume in my library.
(S)
A multi-episode show, an ongoing comic, or series of books instead of a single contained volume.

Film & Shows (48)

Q1 (11)

Rogue One B+
This is only the second new Star Wars film and I’m already getting franchise fatigue. Nonetheless, an excellent addition – likable characters and an exciting premise that plays out like an old Star Wars FPS game.
Secret Life of Pets C
An unremarkable animated feature that did nothing particularly novel or groundbreaking but was enjoyable none-the-less.
The Shining A- (B)(R)
I am rather fond of the works of Stanley Kubrik, and the Shining is an outstanding film although perhaps not in the same catgegory as Clockwork Orange or 2001.
Gosford Park A (B)
A strange favorite of the year. Gosford Park is a standard murder mystery with the added take of Brittish black comedy and insights into Brittish classism.
The Black Cat B+
Great horror from the Italian director Lucio Fulci.
The Big Sleep A- (B)
Continuing the noir theme. Good film. Not mu
Eyes Wide Shut B+
Not sure what to say. The film was good. The charaters and scenario interesting. But for the folks involved, I kind of expected more.
Necromancy B+
Fun schlock horror anthology
Kafka the Last Story D
Just an atrociously boring
The Saga of Tanya the Evil C (S)
Not quite sure how I started watching this, it did turn out better than you would think.
Flip Flappers C (S)
Beautiful scenary, but the show didn’t really seem to know where to go. After a handful of nice episodes it just loses all steam.

Q2 (12)

Point Break D
Bad acting. Mediocre plotting and filming.
Ex Machina C
Ok science fiction film of the Hollywood variety
Lost in Translation B+
Friends have recommended this film to me for some time. I found myself, actually disappointed in it, but perhaps it was due to the hype.
Lavendar C
Another forgetable horror film
Vertigo B
Hitchcock at his finest
Lars & The Real Girl A-
This film starts out making you feel really uncomfortable, but by the end you love it.
Escape from Alcataraz B+
Good old film
The Arroyo F
Stupid
Dazed and Confused A+
Started a theme of “night” movies. This is one of those quotable films that somehow never actually get watched. Excellent social commentary, atmosphere, a kind of film that takes you back.
Before Sunrise C
Continuing the night theme. I see where the directory has started a kind of reputation for making movies where people hang out and talk.
A Brighter Summer Day A (B)
This film is absolutely brilliant! But do set aside the time to watch it. I didn’t realize that it’s novel length.
Night on Earth B
Night theme. A series of short stories interconnected by the late night taxi rides.

Q3 (13)

The Life of David Gale D
Forgetable Kevin Spacey film. Starts with an agenda and doesn’t get far.
Baby Driver B-
Big name Hollywood film. Good music. Surprising lack of actual car chases.
Shutter Island B
Finally finished Shutter Island. I’ve started this film three or four times. A good dark mystery, a psychological thriller of the mind-fuckery variety
What We Do in the Shadows A-
Fun mockumentary comedy out of New Zeland
The Dark Tower C
Sort of a mess, but that was my view of the books as well.
Blackwell Ghost D
More forgettable horror films
Mulholand Drive A-
Starts out slow, but transitions into a much better film. It is oddly obvious when Lynch got the funding to take this from a TV Special to feature film.
The Great Gatsby B+
Brilliant big-cinema film that captures the excess of the period and highlights much that might be missed by a contemporary reader of the book.
The Warriors B
I keep telling the pets to “Come out to Play”
The Black Swan B-
A Perfect Blue rip-off.
Escape from New York B
Love John Carpenter’s various takes on the Science Fiction genre. His visuals continue to live up and the characters are fun.
Jurassic World C+
Kickstarting Jurassic Park again. Hollywood blockbuster. On the better end of the scale for these kinds of films, but still not worth it.
Guardians of the Galaxy Vol 2 B+
Just as good as the first.

Q4 (12)

The Conjuring 2 C+
Better than average horror, not great cinema, but entertaining.
The Maltese Falcon A
The source of the maguffin! A must watch for the noir and film history buff.
The Battle of the Sexes B
Watched this in downtown Durham. Fun. Worth it if you were burning time on a double feature.
The Woman in the Window B+
Short noir film, but one that really captures all of the different themes and styles of the genre.
The Oblong Box B+
Help! I am running out of Vincent Price films!
The Thaw D
Dumb
The Lady in the Van B-
A nice feel-good film
Skyfall C
I am so far behind on James Bond films.
Valarian and the City of a Thousand Planets B
Beautiful! Wonderful blockbuster with all the giant special effects. A pitty
Kiss the Girls C-
Described as a “neo-noir psychological thriller,” I didn’t really find it worthy of being called nor, nor pyschological
Intruders D
Dumb
Red Skeleton Holiday Special A
Great way to end the year.

Books (18)

Statistics in Plain English by Timothy C. Urdan B
A helpful, straightforward introduction to statistics that is perhaps useful to the social scientist but unfortunately skips most of the math useful for Machine Learning which was why I was reading it.
Peopleware by Tom DeMarco and Tim Lister
Didn’t find much use out this business book.
Norse Mythology by Neil Gaiman (B)
Very fast read and, as expected of Gaiman, a very well written contemporary interpretation of Norse myth.
The Book of Yokai by Michael Dylan Foster
Deep dive into all things Yokai and a great overview of thse Japanese monsters.
Stories of Your Life and Others by Ted Chiang (B)
Extremely well written short Science Fiction. Every single one of these is a must read.
IQ84 by Haruki Murakami F
An astonishingly boring and disapointing thousand page read that rehashes the tropes of Murakami’s earlier books.
The Great Gatsby by F Scots-Fitzgerald
Following watching the Film, I had a sudden urge to read the book. It holds up well and continues to be relevant to our divided nation.
Wizards First Rule by Terry Goodkind
Adolescent drivel and wish fullfilmment. A novel that I would have probably eaten up as a teenager, but can’t stand as an adult.
Opus by Satoshi Kon B+
Satoshi Kon’s unfortunate early demise leaves this book unfinished. Yet, it remains a fun run.
Nijigahara Holograph by by Inio Asano (B)(R)
Asano’s take on horror. This is my third run through Holograph, the narrative is exteremly dense requiring close attention to untangle the twisted motivations of these characters.
Ryuko by Eldo Yoshimizu C+
Beautiful artwork, but dreadfully cliched plot. The French edition is an easy read for a beginner in the language.
Nausicaa of the Valley of Wind by Hayao Miyazaki (B)(R)
Miyazaki’s masterpiece of manga. A darker take on the environmental themse present in Nausicaa.
Genshiken by Shimoku Kio A (B)
I found myself relating rather uncomfortably with the characters of Genshiken. A realistic and non-romantic take on the situation. I hear the sequel rather undermines it’s themes and ending though.
Yoon-suin by David McGrogan (B)
A strange, far-eastern themed OSR book.
Micropend6 by Sigil Stone Publishing
Sure would be fun to find a group to play these games with. The D6 system was a favorite for me as it focused on cinematic gameplay over crunchy numbers.
Tiny Dungeon by Gallant Knight Games
Another attempt at a paired down rules system for easy play.
Dungeons & Dragons: The Players Handbook 5th Edition A (B)
5th Edition is a truly exciting return to what I enjoy in a D&D game. If only I could find a group to play with these days.
The Misty Isles of Eld Aby Chris Katulik and Robert Parker (B)
An adventure that would be fun to play, but was quite a fun read non the less.

Games

The Legend of Zelda A (B)
Never played the original until I got it on the 3DS virtual console. The title has aged well and is still worthy of a playthrough.
Pillars of Eternity B
I really wanted to like Pillars of Eternity as I’ve been reminisce for the old Infinity Engine style games. Yet, Pillars just couldn’t quite keep my attention and started to be feel like a grind.
Borderlands 2 A (B)
Endless piles of content and all of it a wonderful. Perhaps one of the best PC titles this decade and a blast to play with friends.
Don’t Starve Together A (B)
Another fun multiplayer title. Don’t Starve is a survival game that really tests your teamwork to survive.
Team Fortress 2 A (B)
A fun FPS that has a strong community and plays well on almost any system. Valve is still patching and updatingthe content so it doesn’t go stale.
Windswept D
Beautiful, but shallow game. It took roughly a single evening to explore the full potential of the game and put it back on the virtual shelf.
Minecraft A (B)
Finally took the dive into Minecraft and found it just as fun and addictive as I always feared it would be.
The Legend of Zelda: A Link Between Worlds A (B)
A perfect return on the handheld to the traditional Zelda formula.
Paperclips A
Free online game and a really fun take on the paperclip maximizer thought experiment.
January 12, 2018

Shell Notes: Less

Filed under: Software Development part of Notes

One of my professional goals this year is to make a marked improvement on my shell (zsh) and editor (vim) skills. I know enough commands to get me through the work day, yet every time I see a real shell or vim poweruser go to town, I am reminded that I am probably only confident in 10% of the commands that I could be using.

Every now and then, I’ll force myself to use h, j, k, l instead of ←, ↑, ↓, → to navigate in Vim and my Tmux panels. The skill lasts about a week before I’m back to the arrow keys and mouse. Every now and then, I’ll try to expand beyond ls, grep, cd, cp, mkdir, mv, rm, pwd, clear and cat, in the shell. I always rebound after a couple weeks, because I can get 90% done with those nine programs.

Hence, a series of articles summarizing the man pages for different applications. A process that hopefully sees me making more regular use of them.

Less

My typical solution to navigating a read-only text file is clear && cat $filename and then scrollback with the mouse or to pipe. My solution to log files are to pipe them into text files and open them in Vim (not recommended on memory-limited systems). So my first Unix command for the year is less, that wonderful program that I get dumped into by Git all the time.

Less is a program that outputs a text file or stream with a buffer to display either more of the stream or page up to previously output lines.

Less gives me something that I’ve been trying, incorrectly to do with clear && cat all along: display a buffer of just the text file. With my old solution, on long file outputs, it was easy to scroll up past the start of the file and into old commands. With Less, this isn’t a problem. The buffer starts and ends with the contents of the text file. Likewise, I frequently output formatted excerpts from my Todo List using the XP and LSGP/LSGC add-ons and pipe them into text files or open new terminals to have a clean buffer to scroll back on. Less solves this by outputing the multi-screen-height output into a single buffer.

Useful Commands/Options

SPACE Scroll down a screen.
RETURN Scroll down one line.
d Scroll down half a page.
u Scroll up half a page
y Scroll up one line.
F Scroll to the end then tail the stream.
g Go to line N
G Go to end of file.
m + Char Marks position with that letter.
’ + Char Return to marked position.
/ Search forward
? Search backwards
@ Search for pattern in file
n Repeat search to next result
N Repeat serach to previous result
t Go to next tag
T Go to previous tag
v Open file in Vim
! + Cmd Invokes shell from inside less
-R Terminal colors maintained
-N Show line numbers
-JM Status columns
January 01, 2018

2017 In Review

Filed under: Journal part of Annual Reviews

We started 2017 with the simple goal of settling into our cabin in Alpine, exploring the nearby trails and outdoor opportunities, and reconnecting with side project long abandoned to hiatus. As the year progressed, it took on an increasingly fever pitch that left us longing for that empty stretch of winter duldrums.

Sprint Highlights

Sprint A
Hotelled at the Wigwam Village in Holbrook, AZ
Sprint B
Started waking early and walking three miles each morning
Sprint C
Explored downtown Raleigh, NC
Sprint D
Spent the weekend at La Posada in Winslow, AZ
Sprint E
Spent the sprint sick with norovirus
Sprint F
Exploring creating a single-player Damasca using Solarus
Sprint G
Visited Wisconsin for my niece’s baptism
Sprint H
Visited my grandparents in Cleveland, OH
Sprint I
Investigating growing Orchids
Sprint J
Camping trip to Blue Crossing
Sprint K
Writing retreat at Cottonwood Campground, Reserve, NM
Sprint L
Jess visited Portland
Sprint M
First time playing Dungeons & Dragons in five years
Sprint N
Cabin trip in Bluff, UT
Sprint O
Converted my blog to Jekyll with a new design and posts
Sprint P
Attended funeral for Grandpa James in Cleveland, OH
Sprint Q
North American Mycological Association Regional Foray in the White Mountains
Sprint R
Backpacked West Mount Baldy Trail
Sprint S
Jess on Fire
Sprint T
McBride Mesa Trail #26 (13+ Mile/16 hour Hike of Doom)
Sprint U
Quarterly Vacation to Durham
Sprint V
Clint Visited & Apache Box
Sprint W
Katie Visited
Sprint X
Grandma James’ Funeral in Cleveland, OH
Sprint Y
Zend Framework Fundamentals Class
Sprint Z
Christmas in Spearfish

Personal Highlights

Q1

Whale skeleton in the NC Natural History Museum

  • The most relaxing quarter. Found time to play – games, films, reading; and to pick up time for writing and pursueing creative projects.
  • In exploring, found George’s Lake Trail. A beautiful oak glade at the base of Escudilla and just outside of town (indeed it’s within a half mile walk of the house). A complex of old roads in the area affords over six miles of hiking end to end.
  • Started the year at over 215 lbs in weight which puts me into the obese category for my height. Started the RealAppeal program, offered by my health insurance and through my employer, with a goal of dropping to 180 lbs. Dropped my weight to 194 lbs at it’s lowest, but spent most of the year at 198 lbs.
  • Explored a lot of culinary delights: crawfish casserole, shrimp in pesto-tomato sauce, turkey breast with almonds, butter chicken, celery and sausage frittata, lentils and rice, squash and browned butter pasta, chicken scarporiello, caldo verde, creamed spinacha nd cauliflowr soup, lamb chops, and miso chicken
  • Replaced the single-pane windows on the house and officially became a resident of Arizona, although saddly not in time to put in for an Elk tag (need six months of residency.)
  • Started a dialog with Dart Zaidyer about the Solarus Engine and its potential for creating a single-player Damasca game. He converted the old Magrathea maps into the Solarus engine format and we began working to fix linking them together as I researched Lua and the API that powered the game engine.
  • Home adventures included hotelling at the Wigwam Village in Holbrook and La Posada in Winslow, AZ as we explored the delights of North-Western AZ.
  • Followed Jess to a training session in Flagstaff
  • Started taking extra time in the Quarterly meeting to really explore the Triangle area. If I am to be flown across the country, I ought to take the chance to look into museums, buy souvenirs, attend concerts and such.
  • Dana visited and we took her to Sante Fe.
  • Ended Quarter with trip to Rhinelander for Felicity’s baptism followed by my last trip to see my Grandparents before their funerals later in the year.

Q2

A beagle cools off in a mountain stream in the shade of a boulder

  • Culinary delights continued: quinoa pasta and burnt butter sauce, french onion stratta, schnitzel and beat sandwiches
  • Continued exploring and hiking, cover over seventy miles and adding Lamphier Trail, Juan Miller Road, MS Mountain Trail, Pueblo Park Interpretive Trail, Indian Creek Lookout, Cottonwood Canyon, Bonanza Bill, and Goose Point road to the list of trails that I explored.
  • Rewrote joehallenbeck.com from Wordpress to Jekyll including a new mobile-friendly design. Implemented a system for updating the site, analytics via a personal Pikwik install instead of Google spyware, and several new posts. Took down the Wind-Up blog and imported the posts into my Portfolio site. Started working on a similar treatment for Dreamscapes, but never got around to it.
  • Played D&D at Flying Rook Games while Jess was out in Portland, but just couldn’t find the time to make the commitment to the three-hour round trip biweekly to attend.
  • Picked up zazen over lunch and kept at it through the summer, although tailed off by Q3. It is a practice that I have long wanted to make routine, but also find that my life is plenty busy without adding another daily item. I have been interested in the Zen center in Silver City, and perhaps if I could make it down there, I could find instruction in the matter and better practice. As such, I’ve put meditation on the back burner of things to do, time permitting.

Q3

Basket of wild foraged mushrooms

  • Completed the third year of a “social media fast,” with several interesting introspections coming from it. Namely the observation that Social Media creates the illusion of being connected to friends. That smaller, more tight knit communities create better interactions. That I ought to spend more time seeking friendships among my immediate peers, or at least maintaining relationships through direct contact. Also, that I largely get nothing from Facebook. Find Twitter and Hacker News amusing, but ultimately distracting. That I would be better
  • Found time to regularly play Team Fortress 2 with Will and Clint
  • Celebrated our sixth anniversary with a trip to Bluff, UT to stay at the Comb Ridge Bistro and explore Bear Ears National Monument (our interests in the area pre-date the creation of the Monument).
  • Grandpa James passed away, necessitating an emergency trip to Ohio to attend the funeral.
  • Attended the Regional North American Mycological Association Foray at Sunrise Ski Resort. Learned a ton about mushroom collecting in the area and set about amassing thirty-some pounds of mushrooms (pre-dried). Signed up for a membership with the organization and looking forward to future mushroom hunting next year.
  • Moved into the house as I disposed of three bags of the prior owner’s linens. Purged an exsessive amount of old paperwork to the fire bin. Decorated the Arizona room.
  • Ended the quarter with a two night backpacking trip to the top of Mt Baldy via the western trail. Sprained an ankle.

Q4

Winding mountain road descending through juniper covered hills

  • Got cat, Tilde!
  • Started the quarter with a 13.5 mile all day hike of the McBride Mesa Trail. A volunteer activity for the Forest Service as we checked the trail conditions and determined the true path of the trial via multiple GPS unit.
  • In total we hiked a 100 miles this quarter, and according to my Garmin, took half a million steps.
  • Jess came along on the Quarterly trip to Durham this time. We saw a Robert Cray concert, toured the triangle area and had a generally good time.
  • Clint visited. Took him on the grand tour of the area.
  • Katie and Ben flew out to visit.
  • Grandma went into hospice and for three long weeks we wondered about her condition. She passed away in November on Thanksgiving Week. This necessitated a wild drive across the country to Cleveland, trailer in tow, for a second funeral.
  • Returned home for two weeks before needing to leave again for our Christmas plans in Spearfish. Two days driving up, celebrated over the weekend, two days driving back, and then back to work.
  • Ended the year with lobster at the Foxfire in Alpine

Professional Development

  • Peopleware book club
  • Started a Modern React and Redux UDemy Course; took a deep dive into the React ecosystem but really I don’t do enough front-end UI/UX work these days to keep on top of it or make much use of it on a daily basis.
  • Abandoned Pomodoro, it isn’t an appropriate technique for development except as a means of breaking a procrastination cycle.
  • Big research into accounting platforms, from Quickbooks, Freshbooks, Zohobooks, and their integration pain-points for a business interested in offloading a bespoke accounting system (integrated into a software monolith). The particular painpoints where the need to export over ten years of pre-existing accoutning data, and also create an automated platform that could record a large volume of daily orders from an external system. Found Zohobooks perhaps the easiest platform for this use case. Would spend the next two quarters implementing this integration.
  • Create a self-sylalbus for studying Machine Learning. Started with reading and completing the example problems in Statistics in Plain English and Statistics: A First Course. Read through the Tensorflow documentation. Completed the first half of Coursera’s Macine Learning course.
  • Work signed us up for Zend Fundamentals I. Completed the course before the end of December.