This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
So, I lied above obviously. Sometimes comments are actually necessary. | |
Name (and defend) some cases where you should add comments to your code. | |
1. Comments that are intended to be compiled into public API documentation; using | |
rDoc, for instance. | |
2. Rescue an exception that causes nothing to happen. A comment | |
is needed to explain why this is necessary, because it is expected | |
that something should happen when the exception is rescued. | |
Although this can be alleviated by creating a method that is called |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Take a break from the exercises for a bit. Explain why we say that 'comments lie'. | |
Comments often "lie" because the code they explain often changes down the road, either | |
through bug fixes, refactorings, or updates. The person making the changes | |
may either forget to update the comment, or neglect them because they aren't | |
a high priority. Either way, the comment doesn't adequately reflect what the code | |
does, and thus, "lies". | |
2. If we don't trust comments, how do we explain our code adequately to others? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Developers are a tricksey bunch. Name some reasons why you shouldn't just trust the person who wrote the code. | |
- All developers are human and make errors. | |
- Their interpretation of the requirements is only one possibility; there are many others that could even be better. | |
- Developers are inherently optimistic, and believe their solution is correct, when in fact they may have | |
overlooked ambiguities in requirements, or simply not recognized these ambiguities. | |
- Humans have cognitive biases that cause poor decisions. These include: | |
-- Confirmation bias: the tendency to search for information that confirms our beliefs instead of information | |
that points out we are wrong. | |
-- Framing bias: people can come to different conclusions on the same information depending on how the information |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Explain how the red / green / refactor cycle works, and how it creates better code over time. | |
The red / green / refactor cycle explains the process of Test-Driven Development. The Red part of the cycle denotes a failing test. This failing test is written before any code. After the test is written, it should be run. Since code hasn't yet been written, the test should fail. Then you move on to the next step in the cycle: green. | |
In the green step, the simplest code is written to make the test pass. Perfection is not the goal of this step; making the test pass is. Once the test passes, you can be confident the test is actually testing the code in question since it initially failed, and then passed. Then it is on to the final step: refactoring. | |
During this step, which is only performed when the code is green, the goal is to refactor the code to make it better. Some of the things to focus on include: ensuring there is no duplication in the system; making the code expresses your intent, clearly and concisely; a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. You've now written two types of tests. Name them, and explain the differences. | |
The two tests I have written thus far are unit and integration tests. Unit tests validate the functionality of individual methods, they are at a low level of the code. In contrast, integration tests are at a higher level, and test a particular feature or workflow of an application, such as going to the home page, logging in, and being redirected to a particular page. The integration tests exercises a series of actions on the application and validates the desired responses. Instead of testing individual methods, integration tests validate whether a number of methods, controllers, router, models and views work in combination in successfully performing the feature or workflow. | |
2. Name the other type of test that you haven't written yet, and write an example of one. | |
Functional Tests test the various actions of a single controller, such as: Was the web request successful? Was the user redirected to the right page? | |
An example of a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. First, tell me what a flapping test is. Then, explain some ways that flapping tests are more destructive than even failing or non-existent tests. | |
Flapping tests are those that are non-deterministically green. They may fail, then pass the next time you run them, hence, "flapping". | |
Flapping tests are more destructive than failing or non-existent tests because they force us to visit many more tests each time we modify our codebase, leading to decreased productivity. For a normal failing test, we actually expect the test to fail initially, and it is just a matter of writing working code to make the test pass. Furthermore, when you experience flapping tests, you lose confidence that your test is actually doing its job: verifying a specific part of the application is working properly. | |
2. Name some gotchas when writing tests that can cause them to become fragile, and how to fix those problems. | |
- The browser environment: Never assume the page has loaded; the markup you are asserting against exists; your AJAX r |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Name some cases where manual testing is preferable or necessary to verify code. | |
Manual testing is essential for usability testing. This should be performed with real users, under real environmental conditions. This form of testing looks at human factors: is the software easy to use? | |
2. Name some strategies for manually testing code that constrain the time cost of testing | |
To limit the amount of time spent manually testing, the tests should be performed frequently and as early as possible during each iteration. This pinpoints problems early, where they can be fixed more easily. If these tests are conducted at the end of a project, you may find problems that take a lot of time to fix, lead to many additional iterations, and thus tests--and time--in the future. Another technique to constrain the time spent on testing is to use Timeboxing, which enforces a set period of time on an activity, in this case, testing. Before starting, a time limit is agreed upon, and once reached, testing stops. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Explain the theory around 'writing the code you want to see'. | |
At it's essence, "writing the code you want to see" means forgoing starting at the class level, whatever that may be, and working at the high level. This will produce much simpler interfaces between classes. Once you get the interfaces of the classes built, can you delve lower into each one, writing the logic, algorithms and data structures that will eventually form the classes of your application. | |
Writing high level integration tests, and making them pass, leads to coding in this fashion. The tests will start you at a high level, and eventually tell you to delve deeper into the implementation of the application. This leads to a minimal implementation that consists of simple, expressive interfaces. | |
2. Create a short gist illustrating a place where violating this rule would cause you to write worse code. | |
Suppose I am creating a blog application. If I don't start with integration tests, I would likely start at the model level. Because I don' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Suppose we have a Rails model: Article | |
In the following tautological test, we aren't testing the the #camel_case_title method is actually doing anything: | |
describe Article, '#camel_case_title' do | |
it 'returns the title in camel case format' do | |
article = double(:article) | |
article.stub(:camel_case_title).and_return("The_Best_Article") | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Explain how "convention over configuration" allows us to be more productive as a group. | |
We need to recognize that our needs aren't unique, and must embrace our commonalities as a group. By pushing back against the impulse to create our own solutions to previously solved problems, we allow ourselves to become more productive as a group through shared solutions and tools. A good example of this is the layer of abstractions in our web application stack: assembly-level; C; OSX; POSIX; Ruby; Rack and Rails. By using these shared solutions, we save time by only building what's necessary, and leaving it to the community to build everything else we need. There is no need to recreate the abstraction layer that is OSX to build a web application. Instead, we spend our time experimenting at the top of the stack. | |
Shared solutions give us standards and allows a group to progress by building even more solutions at the top of the stack. At the core, we take shared problems that the community has, and create shared solutio |