On Writing Books

This month I published the second volume of A Programmer’s Guide to Computer Science. One thing I’ve been asked is: why write books?

Four or five years ago, I was looking for a side project and I asked myself, what makes me unique? What can I do that doesn’t have a million other people trying to do the same thing? A number of items in my background pointed to writing a book as a likely option:

  • I used to write regularly for Scrye magazine, so I already know that I can write nonfiction.
  • My last full time job before becoming a programmer was as a math textbook editor.
  • I work as a senior software developer and have managed projects involving multiple programmers.
  • I have a PhD in computer science.
  • I enjoy teaching, but I was often unhappy with the available textbook options for the classes I taught.
  • I’ve previously published short ebooks (most notably, Healthcare in the 21st Century), so I have experience navigating Amazon’s system.
  • I’ve spoken at several conferences on computer science topics (sorting algorithms, graph theory) and seen that there are a number of programmers interested in learning these topics.

So writing a computer science textbook seemed like a good way to utilize my background and do some teaching (I do miss teaching), while also being completely separate from my day job (meaning there’s zero chance I run afoul of the non-compete clause in my contract).

I’ve advised a few people on the book writing and publishing process lately, so I thought I’d put some of that down in my blog. I want to call out that this post is not going to cover marketing your book, which is an entirely different subject altogether. You can write the best book in the world, but unless you can find a way to get it in front of people, nobody is going to purchase it.

Also, the steps below are for books that I self-published. I’ve considered traditional publishing, but chose to self-publish my books for three reasons:

  1. I keep more control over the process.
  2. I keep more of the earnings.
  3. Turnaround is faster; once the book is written and edited, it’s available for sale almost immediately.

That said, volume 1 has been translated into Russian by a traditional publisher and I may choose to work with one in the future if I have a book that I feel would be appropriate for them.

Write

I will assume that you already know how to write, and have a topic in mind that you want to write about. You can use any writing software you like, but be aware that you may need to convert it to an acceptable format.

I wrote the Programmer’s Guide books in LaTeX, for several reasons:

  • I can use tikzpicture to generate graphs.
  • I really hate trying to typeset formulas in Word.
  • I really like how the finished product looks.

That said, creating the ebooks afterwards was a major pain. I can compile directly to PDF for the print book, but getting the content into something that could be used for a reflowable ebook was difficult. (A reflowable ebook is one where the page can be resized and the content will be rearranged appropriately, so the same book will look fine on a paperback-sized ereader or a full-sized tablet. PDF is an image format and is very much not reflowable). There are plugins to compile .tex files to html or import into Word, but I found that they did not work well with the complex documents I was creating. For volume 1 I created the html file, then manually fixed everything that didn’t get set up correctly before using Amazon’s software to create the .mobi file. For volume 2, I used Adobe Acrobat to create a Word file from the PDF, then loaded that Word file into Vellum and used it to create the ebook. In both cases, a lot of cleanup was required. (The second method did result in a nicer book, and I’ll be redoing the volume 1 ebook when I get a chance).

For future books that don’t depend on creating graphs and formulas, I’ll probably just use Scrivener or Word and avoid the whole problem. (Added bonus: spellcheck! I don’t have spellcheck functionality in LaTeX). I may consider still typesetting the print book in LaTeX after it’s all done, since I really do like the output, but I’ll probably give the print functionality in Vellum a shot first.

In between writing and editing, I’ll also be getting graphics made. Many of them I can do myself in LaTeX, but the cover and some images I outsource to a professional graphic designer (fortunately for me, I happen to be married to one).

Edit

I’ve always been a pretty clean writer; my first drafts are pretty close to most people’s final drafts. It doesn’t matter; your work needs to be edited. Preferably, it needs to be edited by somebody who is not you. It’s entirely too easy to read what you meant instead of what you actually wrote. When that’s not possible, at least put the work aside for a while so you can forget what you wrote, then read it in a different medium. For the last book I wrote, my process was:

  1. Write the chapter.
  2. Put it aside for a bit
  3. Print it out and edit the printout.
  4. Repeat step 3 until I stop finding errors. (Remember I used to be an editor)
  5. Send it to my technical editor. Make changes based on his feedback.
  6. Send it to my copy editor. Make changes based on her feedback.
  7. Convert to an ebook. Fix anything that Word, Vellum, or Amazon’s processing software flags.
  8. Read on my Kindle. Fix anything that looks off there.
  9. Publish!

As you can see, the entire process is somewhat involved. I don’t always go to this much trouble – my science fiction, which I publish under a pen name, I don’t even have an outside editor for – but for technical material in particular I really want to make sure that everything is correct. Self-published books have had a bad reputation due to being rushed out without proper editing, and I aim to have mine be as good or better than anything that’s traditionally published.

Publish

Now it’s time to publish! This is actually the easiest part of the process.

If you already have an Amazon account, you can go to kdp.amazon.com and log in. Making your book available for sale is a simple matter of filling out a three-page form and then waiting a few days for it to be approved. Here you’ll need to know things like your price, whether you want your ebook to be enrolled in Kindle Unlimited, etc. If it’s your first time, you’ll probably spend a while figuring out the best options for your book.

Amazon is the big dog in book publishing, but not the only one. I want my paperbacks to be available from places that don’t want to purchase from Amazon, and I also want hardcovers, which aren’t available from Amazon. So my books are also printed at Ingram Spark. Unlike Amazon, which is free to publish with, Ingram charges a setup fee (and a change fee if you need to make updates later) but you can generally find coupons; I have not yet paid Ingram anything except printing and shipping fees. There are also other places to sell ebooks, including Apple and Kobo. Figuring out your publishing strategy is outside the scope of this article.

Objects, Inheritance, and X-Wings

Not too long ago, a friend who has only done procedural programming asked me to explain object-oriented programming. Today it occurred to me that it might be fun to explain objects in terms of the X-Wing Miniatures Game. [Obligatory disclaimer: this game is owned by Fantasy Flight. I have no rights to it and use it solely because I thought it would be a fun example. Rules may be simplified.]

In the X-Wing Miniatures game, players send fleets of ships against each other until one side is destroyed. Each ship is, naturally, a physical object that we can model with a logical object. How can we do that efficiently?

Base class: Ship

There are certain properties that are common across all ships, regardless of their physical aspects. Each ship has a name and a physical location in space. It has an attack value (how much damage it could potentially do), an agility value (how quickly it can maneuver), and a hull value (how many hits it can take before it is destroyed). It may or may not have shields. We can’t actually play a generic ship; this is just our common attributes. In our code, we can create the Ship class as an abstract class, which can be inherited from (we can have other classes that “are” Ships) but not instantiated (we can’t just create a Ship).

Subclass: Small, Medium, or Large Ship

A given ship may be small, medium, or large. While a small ship and a medium ship each have all the attributes of the generic Ship class, they use different size bases (plastic bases, not to be confused with the base class) and follow slightly different rules.

Two plastic squares, one larger than the other, on top of a playmat.
Abstract classes cannot be instantiated; they only form the base for the concrete class to be used later.

These will also be abstract classes; we can’t actually fly a copy of SmallShip.

Object: The actual ship

When we instantiate an object, we create it in memory and provide values for its required attributes. For example, suppose we wish to instantiate a T-65 X-wing fighter. We create an XWing class which inherits from SmallShip (and thus indirectly inherits from Ship). The constructor sets the ship name (T-65 X-wing) and attributes (3 attack, 2 agility, 4 hull, 2 shields). We also need to assign a pilot to fly the ship, so we’ll instantiate an instance of Jek Porkins (a Pilot object) and associate it with the XWing object.

Jek needs some support, so we’ll instantiate a second XWing object and associate it with a Luke Skywalker Pilot object. The two X-wings were instantiated from the same class and have identical properties (although the pilots will use them in different ways) but they are different objects; what happens to one does not necessarily affect the other.

 

Four small ships (2 TIE fights, an X-wing, and a Y-wing) prepare to engage in battle over the Death Star.
Concrete classes can be instantiated, giving us objects we can manipulate. Here we have four ship objects, two of which are instantiations of the TIEFighter class.

Using the objects

Now that we’ve instantiated our fleet, we’re ready to send it out to battle some TIE fighters! The Ship class has Move as an abstract method; each of the concrete classes that inherits from Ship must implement this method. We’re in a hurry to blow up some TIEs, so we’ll call xwing1.Move(3) and xwing2.Move(4) to send our small fleet straight ahead into battle. If a pair of TIE fighters zero in on Jek and do four damage, his shields will be wiped out and his hull reduced to two. This doesn’t immediately affect Luke’s X-wing, but he’d better get over there and help…

tldr

With object-oriented programming, we model the system as a collection of objects, each of which has properties (hull, agility) and methods (move, attack). Each object is responsible for keeping track of its own state, freeing the programmer from keeping track of it in an external data structure. A class that inherits from another class “is a” thing of that class. In our X-wing example, an X-wing and a Lambda-class shuttle may have different implementations of the Move() method, but because they are both Ships, we can call any method defined on the Ship class and get the actual method implemented on the associated class. Thus, we can have a function which takes a Ship as a parameter and calls ship.MoveSlowly(), and we can pass that function any object which is instantiated from a class that derives from Ship; we don’t need a separate function for X-wings and TIE fighters (or even for SmallShips and MediumShips).

Now go blow up some TIEs.

Difficult for Us, Easy for Them

Suppose you’re working on a complex piece of software with a due date that’s coming up fast. At the last minute, someone realizes that several of the help text popups contain typos. Is it worth fixing?

One thing I’ve noticed – and this is true in general, not just in software – is that a lot of people (and businesses) just don’t really care about what they might see as “little things” like this. I’ve lost count of how many times I’ve seen misplaced apostrophes or quotation marks on business materials, even for large chain stores that presumably can afford graphic designers and proofreaders.

The argument for ignoring the “little things” is simple: most people probably won’t notice or care. I would argue, however, that taking the time to fix even a minor misspelling or grammatical error is worthwhile, for several reasons.

By flickr user volkspider. Used under creative commons license.

The obvious one is professionalism. All of the written content you put out is part of how you present yourself. When a business cuts corners on proofreading, I have to wonder what else they cut corners on. This seems particularly relevant in a field like software development where attention to detail can be extremely important.

Possibly more important, though, is the effect that sloppy writing can have on the ability of your customers to use your software. The amount of attention customers have is limited. Any little bit of that that’s being used up on understanding a poorly written prompt is attention that’s focused on your application instead of on the task the customer is attempting to complete.

This is one small element of a larger topic: keeping the software out of the way of the user. Ideally, when the user is attempting to accomplish a task with your software, the software should be intuitive and require minimal thought to use. If I’m creating a document in Word and I’m not using any special formatting, I don’t have to think about how to use the program; my attention is all on what I’m writing. Anytime I have to actually pay attention to the software – if, for example, I’m trying to typeset mathematics (in which case, yes, I really should be using LaTex) – it’s going to lower my productivity.

When designing and developing software, it’s worth asking: what are the pain points going to be for the user? Is it possible to smooth out those points, making the software simpler from an end user perspective even if that makes it more complicated behind the scenes?

We get paid to deal with complexity. Part of that complexity is figuring out how to make things as easy as possible for our users.

MVVM and MVC

Those of us who have been putting together websites for a long while will remember back when everything was included in the .html (or even .htm) file. Eventually this was replaced by a separation of concerns – content in the .html file, behavior in the .js file, appearance in the .css file.

We can see a similar separation for a web application, where we keep the data itself in one file and behaviors that interact with that data in another file (or several files). This makes the application easier to test and maintain.

For example, suppose that we are writing an application which deals with customers. Using the MVVM (Model-View-View Model) or MVC (Model-View-Controller) pattern, the model itself holds information about the customer – name, address, and so forth. It may optionally contain methods for manipulating and validating the properties it holds. This is the back end of the website; the structure of the data can be developed without needing to know anything about the user interface.

The view is the user interface – in a web application this is the .ascx page that the user interacts with. In MVVM, the view knows about the model and view model; it may have bindings to properties on the model and may call functionality on the view model to manipulate the model. Given information about what data will be available in the model, the UI can be designed independently.

The View Model (in MVVM) or Controller (in MVC) is what ties the view and the model together. When the user attempts to do something in the view, it will actually call functionality on the view model or controller rather than manipulating the model directly.

In MVC, the controller sends commands to the model to update the state of the data and also sends commands to the view to change the presentation. In MVVM, the view model is essentially an abstraction of the view through which the view is bound to the model. Rather than using a reference to the view to communicate with it, as a controller does, the view model updates properties which the view is bound to. A view will be paired with exactly one view model.

A single model may have multiple views that display and (through the view model or controller) manipulate the model in different ways. The model doesn’t know about any of the views; it simply exposes the appropriate properties (possibly setting limits on how they can be manipulated).

Understanding these patterns makes it easier to see where a given property or method should be located. Something which is always loaded from the database in the same way regardless of which view is in use will be found on the model, as will (usually) the validators for that information. Methods which are view-specific – for example, security checks to verify whether the user of the view has the right to manipulate a given piece of data – are found on the view model. The view itself doesn’t contain data, but displays the contents of the model (and possibly additional content from the view model) to the user.

No comment?

I was listening to a podcast recently and one of the hosts made a comment that I’ve heard before. “There are two types of comments – lying and useless.”

For the most part, it’s a fair point. When people comment for the sake of commenting, we end up with useless comments – those that simply repeat the obvious. In the following example, the comment doesn’t add to the user’s understanding and in fact makes the code harder to read:

DateTime admissionDate = new DateTime(year, month, day); // a date

In this case, because the variable is descriptively named, the code is self-documenting; the urge to comment here would suggest that the variable name needs to be updated.

Similarly, a comment that describes how a function works is in danger of becoming outdated the next time the function is updated, if the developer doesn’t notice and update the comment as well. This leads to confusion as the comment no longer accurately describes the functionality. In this case, it’s worth looking at whether we can refactor the code to be more clear so that it doesn’t need a comment.

What I take issue with is the suggestion that these are the only kinds of comments; I actually find comments to be useful in a variety of situations. Here are some times I use comments:

  • Explaining the why
    • For a while, I had an extra line of code that worked around an outstanding issue I needed another team to fix. A comment explained why the line was there and when it could be removed (with a link to the issue that needed to be fixed)
  • XML comments
    • I wrote a function recently where a particular option should be used only in certain situations, where it didn’t make sense to include the entire situation in the variable name. An XML comment on the function helped make sure it was used correctly; the next time I referred to it the intellisense helped me set the parameters correctly.
  • SVN comments
    • This one might be cheating a bit, since it’s not strictly a code comment…but when trying to find one particular change among many commits (when I don’t know exactly where the change is), having descriptive svn comments is a huge help.

Self-documenting code (in particular, good naming) and version control (no need to leave large blocks of code commented out when you can simply retrieve them later if needed) greatly reduce the need for comments, but don’t remove it entirely. Your code should show intent – that is, what you want to do. Let your comments show motivation – why you’re doing it.

Analysis of a Difficult Project

In the eight years that I’ve been a software developer, I’ve had my share of difficult projects.

Early on, the difficulty might have been because I was new to development and new to the code base. I had to learn my team’s conventions and how to use our internal tools.

Recently, however, I had my most stressful project so far. The initial development seemed to go well enough, but getting the quality to where it needed to be took much, much longer than anticipated. I’m now taking the opportunity to reflect on what went wrong, so I can avoid making the same mistakes in the future.

Project Summary

In this project, I was taking some legacy code and rewriting it to be web-based. I’ve probably done this ten times before, but this was one of our most complicated activities. It was also one of my first projects since we switched to a quarterly release cycle, which meant more pressure from deadlines.

I won’t go into more detail than that, except to say that due to the nature of my job, the quality of released code has to be very, very high. The possibility of a data integrity error – either from a programming mistake or because the user is confused – is simply not acceptable.

Design

Part of our process is to have a design for each new piece of development, describing what we’re going to do and why. This is partially so that we can discover issues early on – much better for someone to realize that what we’re going to do won’t work before we start coding than after we’re finished – and partially so we have a record we can refer back to later if we’re not sure why we did something the way we did.

For this type of project – migrating legacy code to web – the assumption is that the functionality of the new activity will be the same as that of the old one, with the exception of changes that are explicitly called out. Usually, just listing out the changes is sufficient. In this case, however, because the activity is so complex, nobody on the team was familiar with all of it. This led to two issues:

  1. The quality assurance (QA) people reviewing the design weren’t fully familiar with the functionality, so they didn’t realize that there were changes they would like until they started testing the completed development. At that point, it was a lot more difficult to make the changes than it would have been if they had been brought up during the design. If the existing behavior had been fully spelled out in the design it would have been easier to catch changes we needed to make.
  2. Part of functional testing involved performing the same workflows in the old and new activities and ensuring that the functionality matched except where called out in the design. Since we didn’t have a complete list of functionality, testing was more difficult.

Development

The original project plan called for 300 hours of development.

However, this project was not the only thing on my plate, and I was assigned a lot of other work that kept pushing it back. At the same time, I was under pressure to get it done so we could keep making progress towards getting rid of our legacy code.

As a result, I pushed harder than I should have, finishing the initial development in just over 100 hours. That put me way ahead of schedule, development-time-wise (if not by the calendar) but with three big problems:

  • I barely had any unit tests. What I did have covered only a small fraction of the code.
  • I hadn’t done enough manual testing to ensure everything worked as anticipated.
  • I didn’t have a complete description of how the activity was supposed to work, so the new activity had less than 100% functionality.

Testing

As I mentioned above, we have very high quality standards, and as such every piece of new development has to undergo inspection by multiple people. This would normally mean that two other developers would review my code and two QAers would test it. Due to the complexity involved, we actually ended up with three QAers assigned to test and two unscripted testing sessions when additional QAers tried out the activity. We also had usability sessions when nontechnical people came in and tried out the new functionality.

The lack of unit tests hit me again at this stage. When doing a fix, it was difficult to ensure that I wasn’t causing any new issues – and we were still pushing hard to meet (new) deadlines. As a result, in the first round of code review and QA, we ended up with a fair number of new issues created by fixing the old ones.

Towards the end of the first round of testing, we were still finding differences between the old and new activities – an indicator that we really needed to have a detailed written description of exactly how everything worked.

Conclusion

This was a project in which it seemed that everything which could go wrong, did. Requirements kept changing – both technological and functional. We were constantly brushing up against (and shooting past) deadlines. Getting the quality up to expectations took much longer than anticipated.

We did have some wins. From a usability perspective, the new activity is much better than the old one, and the users who participated in usability testing were excited to see the improvements. Accessibility – which presented its own challenges – is also much improved. The process worked – while it took a long time to make the code stable, it was never in danger of being released to end users before the quality was where it needed to be.

For future projects, my takeaways were:

  • Take the time to make the design as detailed as it needs to be – even if that means (as it would have in this case) spending an extra week on it. It’ll pay off in the long run.
  • Test, test, test. An extra two-four weeks up front writing unit tests and doing manual testing would have easily paid for itself in the long run. I’ve been pushing unit tests for a while and I’m now getting buy-in for spending the extra time required.
  • Given unrealistic deadlines, push back. I have a reputation for fixing problems quickly, especially when it’s a high-priority bug, but in this case I was simply being assigned too much work and I should have said so instead of trying to get everything done. Not pushing back enough left me stressed out as I struggled to finish everything, and quality suffered – which meant taking more time to ensure that the code was in the state it needed to be in.

I have many more projects like this to take care of over the next year (although this was the most complex). I’ll make things a lot less stressful on myself by insisting on following our best practices, even if it takes more time up front. And now I have an updated list of possible bugs to watch for in the future.

This was definitely a learning opportunity. Here’s to being better.

Instant Family

Last week I finally got around to seeing Instant Family.

If you’re not familiar with the movie, it follows a childless couple who decide to adopt out of foster care. As expected, crazy hijinks ensue.

I have to say that I enjoyed the movie quite a bit. It has a lot of humor, while still (pretty) accurately representing what it’s like to be a foster parent.

One thing to be aware of is that this movie is definitely from the foster parent perspective; it’s about how the foster parents fight through the process and (of course) come to learn that their kids are what was missing from their lives. If it was written from the foster child perspective it would be a very different (and probably much less funny) movie. From the perspective of the parents, their lives are being turned upside down because they now have three kids with behaviors that they aren’t prepared for and can’t control. From the perspective of the kids, their lives are turned upside down because they’ve been moved to a new home and don’t know what’s going to happen to them; almost everything in their lives is outside of their control.

I don’t know if I would show this movie to (especially younger) foster kids – as I said, it’s not aimed at them and could be upsetting – but for people considering adoption from the foster care system, or just enjoy a good movie, I highly recommend it.

On Writing

I’ve been working on a technical book for several years now.

Partially, this is because I have a million things to do (coincidentally, my son just turned two). Partially this is because I’m a slow writer. And partially…it’s because writing is hard! Here are a few things to improve the process:

  • Don’t write technical material in Word. Seriously, just don’t. Fortunately I learned this one many years ago – I used to type up my homework for my Algorithms class (due to my lousy handwriting) and it didn’t want long to determine that the effort to figure out LaTeX was less than the effort to get mathy things to work correctly in Word.
  • Once you’ve written something, leave it along for a while and then print it out to proofread it. It’s amazing how many typos you can find once you’re looking at something in a different format and state of mind and can read what you wrote rather than what you meant to write.
  • If at all possible, have somebody else read your work. Sentences that make complete sense to you might not work for someone else. If possible, get a reader who belongs to your target audience and can confirm that you’re not assuming background knowledge or ability that your readers won’t have.
  • Don’t assume you know what your readers want. In my case, I was expecting to write a 400-page book; I was told by multiple people that I should break it up into multiple shorter volumes. Bonus: the first one will be ready a lot sooner!
  • Don’t assume you have to make every change your beta reader suggests. Take their suggestions seriously, but remember, it’s your book – you’re in charge!

You don’t have to be the world’s top expert on something to write a book about it; you just need to have something to say or a way to say it that’s different from what’s been done before. In my case, I have a PhD in computer science and experience as a teacher, a textbook editor, a writer, and a software developer – so writing a book about computer science for software developers seemed like a good way to combine all of those elements. What does your background make you uniquely suited to do?

Doing big things

Fans of Marvel movies know to wait around until the end of the credits to see the extra scene. This adds a bit of time to the theater experience, as the credits go on for quite some time; it takes hundreds of people to make a movie on that scale.

At work, I’m one of a dozen developers on my team and one of several thousand developers in the company. While each team largely sets its own policies, there are some general standards for consistency across the company.

Even relatively small side projects tend to involve several people. I’m currently finishing a small computer science textbook that I’ve been working on for the last few years. Even though I have a PhD, work experience in both writing and editing, and a tendency to do everything myself, my book still has a technical editor, a copy editor, and a graphic designer. I could certainly finish the book without any of those people, but they’ll help me to make it as good as it can be.

In short, any project of significant complexity, even if it’s small enough to be done by one person, will benefit from having multiple sets of eyes. When multiple people are working on the same content, however, it’s important to have standards for consistency and for resolving disagreements. Sometimes this means there’s one person in charge – the director, the lead developer, the author – who makes decisions that the rest of the team will follow. Sometimes it’s a collaborative process. But consistency is key.

What are some things to do to help ensure that your projects are successful?

1. Save frequently and use version control.
Not too long ago, I needed to retrieve some code that had been deleted by another developer who had left the company over a year before. Although the code never made it to production, I was still able to retrieve it from svn, which saved me dozens of hours of work.

1a. Make small commits with good comments.
In the past, my habit was to save when I finished a chunk of development or at the end of the day, whichever came first. That meant that even if a disaster occurred I wouldn’t lose more than a day’s work, but it also meant that my svn commits while working on a project tended to be rather large and contain a number of fixes, making it more difficult to locate a specific change. Now, I generally commit (with a descriptive svn comment) every time I fix one bug or add one new feature. The primary reason for this is so that when I go on to the next change, if I screw it up it’s easy to roll back to the last stable state without losing any of my previous work, but it will also make it easier for any future developer (including future me) to find a specific fix if needed.

1b. Delete commented-out code.
I’m not opposed to comments – I’m in the school that believes that what the code is doing should generally be clear from reading it, but comments are useful to explain why the code is doing what it’s doing and document any assumptions. When working it’s easy to comment out sections of code for testing or because they’re not currently needed, but leaving those in afterwards clutters up the code and makes it more difficult to tell if something should have been turned back on. Version control means not needing to keep commented-out code. Just delete it – it can be restored if it’s needed again in the future.

2. Have consistent standards.
There are a lot of areas where there are multiple ways to do something and it doesn’t really matter which one you pick, but being consistent in your choice makes things easier. For example, my team consistently puts the list of properties for a class at the bottom of that class; while it’s easy enough to use F12 to jump to a given property definition, having all the properties together in the same place in each class makes it easier to look through them when needed, without having to think about it.

3. Use good names.
Few things result in as much unneeded mental effort as deciphering code with unclear or misleading variable names. I’ve certainly had instances where towards the beginning of a decent-sized project I’ve given two properties similar names and by the end I’m having trouble remembering which is which. If it’s not clear what information a variable or property is holding, then the name needs to be updated! Similarly, function names should accurately describe what the function does.

4. Test everything that needs to be tested.
What I’ve struggled with the most as a developer is making sure to test all the things that could possibly go wrong with my code. Unit tests can do a big chunk of the actual testing, but the developer still needs to come up with the test cases. This can be a challenge because as the developer you (hopefully) understand how the code is supposed to work, so you use it correctly. Take the time to figure out all the logic-impaired things your users might do and try those also.

5. Understand the desired outcome.
When I’ve had development that’s gone way over the expected timelines, it’s been because requirements have changed repeatedly over the course of writing the code. While that is sometimes unavoidable, do try to minimize it as much as possible for larger projects by writing a reasonably complete design document and getting buy-in from the relevant people before you start development. Sometimes you even get lucky; I’ve had projects end up becoming much less complex before I ever started coding, because my initial design was more complicated than it needed to be and my design reviewers were able to point out a better way to accomplish the same task. Aside from getting buy-in from key people, a good design helps you be sure that you understand the requirements, which makes it easier to implement them correctly.

It’s always worthwhile to make things easier for the next person who will look at your code. Very often, that person is you.

Thoughts on foster care

I recently gave an “intro to foster care” presentation. What was interesting is that I was trying to both encourage people to consider becoming foster parents, and discourage them from doing so.

Why both? There’s always a shortage of good foster parents – people who really care about the kids and are willing to do whatever it takes to make sure the kids feel safe and have their needs met. At the same time, there are too many foster parents who don’t treat foster kids right. It’s not that they’re necessarily abusing kids, but they’re not willing to put in the effort to become trauma-informed or don’t treat the kids like they’re really members of the family. So I’m trying to increase the number of available foster parents, but only those who are reasonably confident that they can treat foster kids as their own. I emphasize this a lot in my talk – while you have the kids, they’re your kids and deserve to be treated like your kids. If you wouldn’t leave your biological kids out of something, you shouldn’t leave your foster kids out either.

We recently re-opened our home for new placements (we closed after our daughter went home to ensure that we’d be available to support her and her mom as needed), but we’re being pretty selective in who we take because we need to find a kid that we’re the right family for – someone whose needs we can do a good job meeting. It’s not enough to find homes for these kids; they need to be homes where they can be comfortable, where they can feel supported, where they can belong.

Everybody needs a family – whether that be biological relatives, close friends, or otherwise. Are you in a position to be family for someone who needs it?