I collected responses from six groups to three questions: what are the most important things you have learned, in what areas do you want to get better, and what are the markers of software quality.
Four of the six groups mentioned the design recipe at or near the top of their lists:
Two groups put high priority on problem-solving skills; a third group had this skill as a lower priority:
Several groups felt they had gained important skills that relate to particular aspects of design recipes. First, data definitions and analysis:
Next, examples, especially functional examples:
check-expect
s first, to understand our functionsA couple of groups mentioned templates:
Toward the lower end of people’s lists of things learned, there is more diversity:
check-expect
to test every case: seriously test your codeWhen I look over the areas in which people want to get better, there is much more diversity. My commentary is in italics.
Identifying solution structure when reading a problem; seeing what template or structure a solution requires based on the task at hand2
Function templates for different types of self-referential data
Filling in templates
Making/using templates
Templates are essential and are a good thing to focus on.
Moving from templates and functional examples to code
This was the purpose of the “Templates and examples” assignment.
Writing slimmer and more efficient code
This is the purpose of the “Abstraction” assignment. The key here is to recognize that nobody writes slim and efficient code. Instead we write fat, ugly code, then simplify it. Making code run faster is a technique that is not taught until the third semester (COMP 40).
Coding fluidly
Code efficiently
Fluency and speed come only with practice. And every time you learn something new, it disrupts the fluidity with which you apply what you already know. Be patient and it will come.
Waiting before coding
Mindful waiting is one of the most effective things you can do, not only to produce better work, but to be more satisfied at work. “Think before you code” sounds simple, but is hard to put into practice. If you want to get better at this, study Buddhist techniques of mindfulness and meditation. The Cambridge Insight Meditation Center is a good local resource.
Break a problem down to its atomic parts
Getting started; jumping into problems
Recognizing what different data and problems call for
All of these similar goals require a leap of faith that if you set out to “define a function”, the parts of the problem will reveal themselves as you carry out the design process.3
Gaining a better understanding of big-bang
big-bang
If you want to write interactive graphics programs, then big-bang
is essential. Otherwise, it’s incidental. Either way, it may help to know that big-bang
is built on the principle that “functions are values, too.” This fact may give you a little more insight into big-bang
.
Writing data definitions and recognizing what’s important
Data analysis
These are essential techniques, and improving your skills is an excellent goal. COMP 15 will provide additional opportunities.
Following design recipe
Using helper functions, combining multiple parts
Self-referential data
Syntax (minority view)
If you need to improve on any of these skills, you might be a little bit behind. I recommend meeting with a member of the course staff.
Time management
I personally find time management difficult, but it’s an essential skill. The Tufts Academic Resource Center has an excellent consulting program.
You identified several different kinds of markers. I’ll begin with down-to-earth, technical properties that you can expect not only to be able to recognize, but to be able to build in.
You also identified some properties that are usually easy to recognize but can be quite hard to build in
You identified some more properties that are also solid and technical, but which can be difficult to recognize. For example, to tell if tests are “comprehensive,” you would have to have a deep understanding of all the relevant data definitions:
You also identified some properties that sound good, but that you can’t really check for yourself. These properties can be evaluated or recognized only by very expensive experiments that involve having an outside expert read the code. These properties are nice if you can get them, but because they are so expensive to evaluate, I wouldn’t aim for them—I would aim for properties you can recognize at reasonable cost.
You identified a few properties that I think are risky or misleading. You will have to decide for yourself. My commentary is in italics.
High-quality, varied check-expect
s
How do you tell high quality from low quality? What does “varied” really mean? I would be worried about pointless variation. Some ways to improve on this idea include:
check-expect
for every choice of every data definitioncheck-expect
s provide complete test coverageSolid data definitions such that no data falls through the cracks
By definition, the data definition contains everything you know about the data. I would say instead something like “all examples from the problem statement or the customer visit can be turned into data examples, each of which respects its corresponding data definition.”
Finally, you identified a few properties that I think are irrelevant, off, or downright wrong:
Acknowledged and analyzed failures and lacks in code
I’m not quite sure what was meant here. If the signatures and purpose statements are accurate, does that not constitute proper acknowledgement of all properties of the code, including its failures and lacks, if any?
It works efficiently
I both agree and disagree with this property. If a software product is conspicuously faster than its competitors, and if the customers notice, then they will be really happy, and this may be considered a mark of quality. (For example, Google got its start by delivering search results about ten times faster than the competition: 100 milliseconds instead of one second. That was really noticeable!.)
I also will claim that if code is gratuitously inefficient, then that’s a mark of poor quality. This is especially true of code that takes exponential time, like my implementation of Pascal’s triangle and like some students’ implementation of the fishes problem.
But most of the time, for most code, efficiency is irrelevant to quality.
The code works
This one is just wrong. Just because a piece of software does something doesn’t mean it’s any good. The first time you get stuck working with somebody else’s deployed, crappy software, you’ll learn for yourself.
You identified properties of low-quality software which are, unsurprisingly, related to the properties of high-quality software that you identified. Rather than provide a similar breakdown and analysis, I’m just listing the properties, followed by a little commentary.
check-expect
s are not comprehensivecheck-expect
scheck-expect
s?I find little to disagree with here, except possibly “extremely expensive operations” or “runs slowly.” Speed is not an absolute good, and slowness is not an absolute bad. It affects our perception of software quality only when software is not fast enough. Here’s a real-world example:
lzma
, was really slow: it took around half an hour to compress my backups! Should I be annoyed at its low quality?5Here are a few more followup points:
Why do tests matter? They clarify murky or vague purpose statements, and they provide protection as we improve, simplify, or evolve the code. And when we do break our own code, the tests help us find, isolate, and repair the faults.
Why does it matter if there are aren’t enough helper functions? Because a helper function has more than just code: it also has its own name, its own signature, its own purpose statement, and its own tests. These artifacts _communicate- to a reader, and they help keep the software from breaking as it evolves.
Why do long lines matter? Because of limitations of the human visual system. The most text we can take in easily is about 65 characters wide. If we allow for some white space on the left for indentation, we can push a reasonable limit up to around 80 or 90 characters. Reasonably narrow programs also benefit from being viewable side by side with documentation or interactions windows.
Someone has taken COMP 11.↩
Your instructor thinks this is an impossible path toward structure.↩
Exception made for designing interactive graphics programs with big-bang
; for that, refer to the Design Guidelines for big-bang
Programs.↩
Complexity is almost never necessary.↩
Hint: the size of the compressed backup was 840KB. In case you don’t usually sling around KBs and MBs, before compression, the backups needed around 880,000,000 bytes of storage, and after compression, they needed about 860,000 bytes of storage. What do you imagine I think about the quality of lzma
?↩