Joseph Hallenbeck

Notes

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.
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

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