Recovering from Tragedy

After last week’s post I made a simple click that I’ve made probably hundreds of times before when I updated WordPress on the MassHOSA website. The difference this time, however, was that I wasn’t only updating the WordPress core but also the theme that was currently being used on the website. Depending on the update, you can sometimes get away with updating themes without losing customizations. If, however, the update includes changes to say styles.css, for example, your customizations will be obliterated.

I have nobody to blame but myself for this mistake. I was fully aware that updating a theme could wipe out customizations, and WordPress even has a handy warning on the theme update screen:

But, I was not thinking and clicked update – and lost all of the customizations that I had made to the theme, permanently. Here lies another issue: backups. I should have been making regular backups of both the WordPress filesystem and SQL databases, since at this point I have put a significant amount of effort into both the design (stored mainly on the filesystem in CSS and PHP files) and the content (stored mainly in the SQL database).

While this incident was certainly frustrating, it’s not that tragic. I was able to restore the customizations (this time in a child theme) in a matter of a few hours, and am happier with the outcome this time than I was after my original modifications. Using a child theme forced me to do things a bit differently than the first time around, but at this point I already had a pretty good idea of the changes that needed to be made. I am happy to be doing things the right way now, as my original design would not have been sustainable. Making changes directly to the themes CSS files means that you cannot apply updates as they become available. While this would be fine if updates only ever contained feature additions or style modifications that you were not interested in, this is not advisable when some updates contain security patches. Given the choice between leaving my website vulnerable to attack and losing customizations, I would rather put in a couple of hours of doing customizations the right way than face the repercussions of a breach.


Money Shouldn’t be the (Only) Motivator

While money is certainly important, and should be a consideration – it should never be the primary motivator for choosing a particular career or even for choosing particular projects or roles in a position. Making decisions based on financial considerations alone is a quick way to end up hating what you do and having little opportunity to improve your situation. Making the correct choices about what you use at motivating factors to drive decision-making can help make software craftsmanship a more rewarding and valuable career. Following some of the advice given by Hoover and Oshineye in Apprenticeship Patterns should allow a new or aspiring software craftsman to identify the motivating factors that drive success in the position and lead to a satisfying career.

It is easy to stay motivated when things are going your way and you are working on projects that you find engaging, fun, and adequately challenging without being overly difficult. The problem that the Sustainable Motivations pattern is hoping to address, rather, is when things get a bit more difficult. Sometimes it becomes difficult to see the passion in software craftsmanship. For example, sometimes in the course of developing the necessary technical skills to become a master craftsman, the aspiring develop will be faced with hurdles such as ambiguously specified projects, or shifting and conflicting demands of customers. It’s times like these, argue Hoover and Oshineye, where the motivation and determination of the aspiring craftsman are truly tested.

While I feel lucky to be actively interested and continuously challenged by my current work, I am sure that my luck will run out at some time in the future. I will be presented with a project that I find tedious, frustrating, and maybe even exhausting. I am confident in my ability to remain focused and motivated on working towards the end goal of becoming a craftsman, however. I feel that as Hoover and Oshineye mention, if I ever begin to have doubts they will easily be overcome by a need to continue earning money or the desire to maintain a reputation as a technologist. These motivators should keep me in the craft until my situation improves and passion returns as my primary motivating factor.

How to Effectively Discuss Software Testing

It is not easy to come up with a definition that truly encompasses all that the discipline of software testing entails. From writing test cases to performing automated testing, what a particular software tester does can vary greatly. It is not surprising then, that there often misconceptions surrounding discussions of software testing. Reading a post titled “Six Things That Go Wrong With Discussions About Testing” by James Bach on his blog gave me insight into some of the things that I should avoid when talking about testing.

The first point that Bach brings up is that the number of test cases that you have written does not matter. To anyone who has ever written a test case, this is a pretty obvious one. You could write a million test cases that all do the same thing, but if you’re not exercising the code in unique and possibly unexpected way, then you are wasting your time. Any tester who brags about the number of test cases that he or she has written is clearly missing some critical understanding of the purpose of testing software.

Secondly, Bach states that each test should be thought of as an event rather than as an object. Whether it is done automatically or manually, tests must be performed, they do not simply exist. This is why software testers will never be replaced by computers or algorithms. Each time a tester performs a test, it produces a unique and meaningful result. This ties in with Bach’s fourth point, which is that even in the case of automated testing, humans are responsible for the successes or failures of the tests being run. Computers are unable to think critically about problems like humans can, and they can only go so far as to check simple facts, not effectively test software.

Backtracking to Bach’s third point, testers should always be able to describe their testing strategy, even as it evolves over the course of testing. Understanding how and why a given test is being performed allows testers to think about things such as how to improve the test, what tests need to be developed next, and how to develop better tests more quickly in the future.

The fifth topic that Bach discusses is how people “talk as if there is only one kind of test coverage”. As a student currently learning about the types of testing coverage, this one came as a bit of a surprise to me. I imagine that testers who fall victim to this fallacy of testing never received formal education in software testing or have become so set in a single way of testing that they are failing to see the bigger picture.

Lastly, Bach discusses testing as an exploratory learning task rather than as some scripted, monotonous procedure. Again, I think that my current enrollment in a software testing course leaves me a bit biased on this point. Nearly every test that I write is a learning experience for me, and I certainly do not feel that testing is a static task.

While I can certainly see where Bach is coming from with all six of his “Things That Go Wrong With Discussions About Testing,” I am pleased to know that the my understanding of software testing does not fall into any of his categories for the most part. I feel that many of these things apply to testers who may have been self-taught or had minimal theoretical training. I think that my education certainly helps me to see the big picture of why software testing is so essential, rather than just going through the motions of writing test cases for the sake of it.

Practical Uses for Design Patterns

Sometimes completing assignments can become monotonous. I think that I find this mainly happens when I cannot seem to think of a practical use for what I am currently working on. While I understand that many of the example implementations of design patterns are intentionally left abstract so as to highlight the importance of the pattern rather than the complexities of the underlying system, this bores me. My approach to programming is often utilitarian in the sense that I want to know how what I am currently working on is going to make someone’s life easier.

(Image source:

This week I listened to Episode 30 of the Coding Blocks podcast, from July 26, 2015. In the episode, Allen, Joe, and Michael discuss the Adapter, Facade, and Memento design patterns. The first pattern that was discussed was the Adapter pattern. I paid particularly close attention to this pattern, as I will be researching and compiling an informative piece on the Adapter pattern in the coming weeks. The podcast provided a link to an excellent tutorial on TutorialsPoint, which I will most definitely be using as a reference for my project research. The real-life example used to describe the Adapter design pattern was that of the SD-card adapter, which takes the SD card and adapts, through the use of an interface, to a USB cable that the computer can recognize and use. The Adapter design pattern implemented in software provides a very similar function by taking two otherwise incompatible interfaces and acting as a bridge between them so that they may seamlessly interact with one another.

In the discussion of the Facade design pattern, I saw some parallels to the Adapter pattern but there were certainly also observable differences. The Facade patterns aims to hide the complexities of some underlying system by providing a simplified interface through which the user can gain access and use the resources provided by the system. The example that the three discuss that I found very interesting was transactional payment processing systems such as PayPal. The goal of applying Facade in this case would be to hide multiple repeated calls to APIs that must be completed each time a user would like to perform a task such as setting up a secure connection, passing a token, storing a token, etc. before actually accomplishing the desired task.

The final pattern that is discussed is the Memento design pattern. While the three seem to have mixed feelings about the usefulness of the Memento pattern, I thought that the discussions regarding Megaman and System Restore’s implementation of this pattern were extremely useful and interesting examples. The pattern, in a basic sense, aims to save a complete copy of the state of the object at any given time. This state object is accessed and maintained by two classes – a caretaker and an originator.

What I like most about the examples and explanations that the three give for their respective design patterns is how practical they seem. While the ultimate goal of applying a design pattern to a particular problem is to simplify the overall implementation, it is certainly not always a simple task to apply a pattern. Understanding some of the motivation behind why applying the design patterns makes an implementation cleaner and more effective satisfies my utilitarian inclinations. I am looking forward to exploring the complexities of the Adapter pattern more thoroughly in the near future.