Author Archives: funinfunction

Time Machine Antics

The podcast episode this post is written about can be found here.

This week I listened to a podcast in which the podcasters stage an argument between a 1990s “traditional” test manager and a modern test manager. I chose this podcast from about 4 I thought sounded interesting, because I wanted to know the current state of the industry and where we came from. It was enormously helpful in demonstrating the difference in how software gets tested these days compared with how it was done previously.

The one playing the role of the 90s manager explains how at his company, testing is kept largely separate from development. After software is implemented, it’s sent to software testers, whose job it is to find bugs. If they do find bugs, the project is sent back to the developers for them to fix. The second round of testing might reveal that the bug wasn’t fixed after all, and the result can be an endless game of ping-pong where the product doesn’t get released for ages.

Laid out in this way, it was clear how this inefficient setup led to the modern strategy of integrating software development and testing. The modern test manager explains that at his company, test specialists are embedded in the development team from the beginning, and the whole team is in charge of ensuring the quality of the product. The developers actually write most of the tests for their own code as they go along and end up finding most of the bugs. Test specialists may write more complex tests or write diagnostic tools, but mainly their job is to see the big picture and make sure that all the testing that needs to get done gets done. In fact, the modern manager says that most of the bugs that the team members who specialize in testing find don’t find them through writing typical tests or test automation, but through data analysis and looking at how customers use a product.

I gathered through listening to this conversation unfold that the basic idea of the modern setup is that catching bugs earlier makes them way less hassle to fix, so testing isn’t pushed to the end. Everybody in the team is capable of doing everything required for both implementation and testing, but they each specialize in a particular area. Going forward, I’ll make sure I don’t conceive of the testing process as entirely separate from the development process, but rather as something that goes along with code implementation in order to prevent headaches down the line.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-10-09 23:59:28

The blog post this is written about can be found here.

This blog post by a software engineer working at Facebook outlines several anti-patterns, including examples, why they’re bad, how to avoid them, and why it’s difficult to avoid them. I chose it to read because of the obvious connection to the course material, my continuing desire to avoid bad practices, and the fascinating connections the blogger makes to the cognitive biases that explain why we fall into these traps.

Some of the anti-patterns are time-wasters, like bikeshedding and analysis paralysis. Bikeshedding is described as the tendency to spend a disproportionate amount of time debating unimportant details. The blogger suggests flipping a coin or voting when you notice this problem arising. You can resolve to revisit the decision at a time when it’s more relevant, as long as you get the decision over with quickly and move onto more important ones.

Analysis paralysis is analyzing so much that it impedes progress. The blogger suggests that this anti-pattern crops up due to information bias and validity bias. Information bias is defined as the belief that you can make better decisions the more information you have, regardless of whether the information is relevant to the decision. Validity bias is overestimating how accurately you can predict an outcome based on a set of information, even if that information is unreliable or outdated. These can lead us to the belief that more analysis will be useful, even when it won’t. His solution to this anti-pattern is more iterations of code. If you go ahead and try something, you can see actual outcomes and modify your code accordingly, instead of endlessly speculating about outcomes.

I also took note of several class-related anti-patterns. These include the god class, a class that knows about and/or controls too many classes; fear of adding classes, the avoidance of adding classes due to a misconception that they will make designs more complicated; and the poltergeist class, a useless class that ought to be eliminated. The solutions for the first two seem to contradict the solution to the last one, but taking all three into account leads to a clear picture of how to properly use classes.

For the fear of adding classes, the blogger gives a useful example of a tangled ball of yarn to represent too few classes. Adding classes can instinctively feel like adding complexity, but simplifying your design with additional classes is akin to separating the yarn into individual strands. Similarly, the god class can be broken up according to the single-responsibility principle, giving classes only one clearly-defined responsibility. Poltergeist classes lack a clear responsibility; they often only call other classes or add a layer of abstraction that isn’t actually necessary. When you create a new class, you should make sure it actually has a valuable role and simplifies the design.

Hopefully, having read this, I will be able to recognize these anti-patterns in the future and apply their relevant solutions.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-10-09 21:37:45

The blog post this is written about can be found here.

I chose this blog post because it directly relates to the material we learned on equivalence class testing and our assignment based around it, and because it led me to a deeper understanding of what equivalence class testing is and the ways it can be applied more broadly. In it, the blog’s writer takes apart the Wikipedia article on equivalence class partitioning from a professional tester’s perspective.

The blogger defines an equivalence class as a set of things that have some quality in common that makes them more or less equally able to reveal a certain kind of bug, if it were present in the code. He writes that equivalence classes are not necessarily limited to classes of input data, even though common definitions of the concept characterize it that way. Instead, equivalence class partitioning can apply to anything you might be thinking of doing which has variations that could influence the outcome of a test.

The blogger takes issue with the Wikipedia article saying the technique is meant to reduce the number of test cases, since (as I learned earlier) the number of test cases tells you nothing. He writes that instead, equivalence class partitioning is a method that reduces test effort; and this is only a side effect of focusing test effort, which is accomplished by making educated guesses about where the bigger bugs are most likely to be. He stresses that the technique is based heavily on our mental model of a piece of software and that it’s a fallible method of testing.

I found it particularly useful when he used the real-life scenario of pushing against a door to try to open it as an example. If we push against one part of a door and it won’t move, we won’t try pushing every other spot on the door, because we intuitively understand that most places you can push on a door are more or less equivalent. Pushing once was enough discover it was jammed, and we feel confident in assuming that pushing elsewhere within the set of door spots you can push will have the same result. This thought process is the same as the one used in equivalence class testing.

Having read this post, I will make sure to have a good understanding how a piece of code is meant to work before I set about trying to determine the equivalence classes for it, and I’ll keep in mind that the concept of equivalence class partitioning can be used with things other than inputs.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-10-02 23:08:58

The podcast episode referenced in this blog post can be found here.

This podcast episode from CodingBlocks.NET discusses the SOLID design principles. I chose this episode because SOLID is a fairly early topic in the syllabus and appears to cover several important principles. The podcasters start by introducing SOLID as guidelines for well-designed code, defining “well-designed” as easy to change, easy to read, and easy to maintain. They suggest that you should usually code first and then refactor according to these design principles as the need arises, since following the principles can take a lot of work. Additionally, you probably can’t adhere to every single principle out there, so practicality comes first. Summarizing every principle discussed got long, so I’ll summarize the ones that affected me the most.

The Single-Responsibility Principle is fairly simple – it holds that a class should do one thing and do it well, i.e. objects should only have one reason to change. With this principle in mind, I will check my classes to see if I can think of two or more reasons I might need to modify them, and if I can, I’ll see if I can divide the responsibilities into multiple classes.

The Liskov Substitution Principle states that objects in a program should be replaceable with instances of their subtype. They talk about how making a square a subtype of a rectangle, while intuitive, would actually violate the Liskov Substitution Principle because of a square’s additional restrictions. You ought to be able to set a rectangle’s length and width to two different values, but this is impossible with a square. They conclude that if your subclass requires something a base class doesn’t, chances are you’ve violated this principle. This makes a lot of sense once spelled out, and in the future, I will make sure instances of my subclasses can be used whenever objects of the parent class are expected.

The Interface Segregation Principle holds that more specific interfaces are usually better than large, general interfaces. For instance, using a brake information interface where brakes are concerned would be more efficient than using an entire car interface. The podcasters say that according to this principle, if your interface requires a lot of methods in order to be implemented that often aren’t needed, your code smells. With this in mind, I will examine my interfaces for methods I’m not using most of the time and see if I can make smaller, more specific interfaces.

Additionally, the podcasters note that following the Single-Responsibility Principle and the Interface Segregation Principle make unit testing easier, so I’ll make sure to keep this in mind if I expect to do unit testing or pass my code on to a unit tester.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-09-25 23:51:24

The blog post this is written about can be found here.

This blog post explains some of the ways that conversations about software testing can go wrong, and in the process reveals some commonly held misconceptions about what software testing is and how it gets done. This was a good post to start off with because it discusses testing in general terms, not using much terminology I’m unaware of yet, and it lays a good foundation for understanding the software testing field as a whole. I chose it because I wanted to know about mistakes people make with regard to software testing right away, so that I can avoid them, and because it provides some good guidelines for how to approach and think about testing.

One of the misconceptions author talks about is believing that software testing is or can be made more automated than software development. To test something properly, you can’t use “automated testing.” There aren’t blanket solutions to the problems that might arise in your code. You need people who can form a testing strategy, use their judgment and intuition to fill in the blanks that templates for testing can’t, and adapt to surprising results or changing needs. Knowing this, I’ll be careful not to form assumptions that the thought that goes into testing a piece of code can be eliminated with an automated process.

Another mistake people make is focusing on the number of test cases you have instead of what your testing does, whether it’s useful, and how comprehensive it is. As the author states, this is as silly as caring about the number of files created or keystrokes made during the coding stage. With this in mind, I’ll remember to ask further questions about the test cases if I’m told the number of tests like it means something. Additionally, I won’t present the number of test cases I’ve created to someone else as a way of showing how thorough the testing is.

The final mistake I found interesting was conceiving of tests as objects instead of events. As the author writes, testing is something you do, not a physical thing. Although there can be physical things produced in the process of testing – such as data, code, and documentation – tests themselves are not objects, and thinking of them this way skips over the job of the tester. I’ll make sure to remember that software testing is a process, and that what matters is whether I’m performing the process well.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

The Common Code (Smells)

The blog post this is written about can be found here.

This short post from Coding Horror is an overview of common code smells, which the author wrote in response to being asked why he didn’t recommend a certain book on refactoring. He doesn’t think people ought to be relying on one set specific way of refactoring code in response to a particular smell, but that the important thing is to watch out for warning signs in the code you write.

I chose this post and this topic because I wanted to know right away what I shouldn’t be doing. I didn’t want to develop bad habits and then have to unlearn them later. Code smells were included as one of the topics in the syllabus, so I know we’ll be covering them at some point.

This post proved useful right away because of its commentary on comments. I know that my natural instinct would be to comment my code liberally for the sake of clarity, but knowing that too many comments can obscure has made me reconsider this approach. With this in mind, I’ll be more likely to ask myself whether I can make the code itself simpler to understand and limit my comments to useful ones – ones that explain why my code is written a certain way, not what’s going on.

Speculative Generality was also helpful to read about, because I know I’d want to try to anticipate what might be needed in the future instead of just solving the problem at hand. I hadn’t considered the drawbacks of this approach. It does make sense to limit yourself to addressing the problems that actually arise in the future, since over-planning might result in unnecessary code. I remember this being mentioned in class.

We also just today talked about how the strategy pattern can be used to avoid a mountain of conditional statements. The Conditional Complexity code smell mentions this, and it also recommends the patterns decorator and state. The decorator pattern sounds similar to the example of the strategy pattern we used in class today, only with behaviors being added to specific instances of a class instead of to subclasses. It’ll be good to know these approaches exist in the future, since in the past I’ve written some truly unwieldy nests of if statements in order to accomplish a task.

At the moment, the code smells that have to do with multiple classes are more theoretical for me than the intra-class code smells, but they’re good things to keep in mind for later (and I enjoyed some of the names).

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-09-11 00:03:22

This is the introductory post for CS-443.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.

CS@Worcester – Fun in Function 2017-09-10 23:56:32

This is the introductory post for CS-343.

From the blog CS@Worcester – Fun in Function by funinfunction and used with permission of the author. All other rights reserved by the author.