James Course - Hoare Logic Flashcards
What it means for a program to be wrong?
A program is wrong if the reasoning for why it should be correct is flawed.
When we talk about programs, we speak at one of three levels. What are these three levels?
Level 1: Runtime. The runtime level deals with specific values and a specific environment from a single execution of the program. A lot of debugging is done at Level 1.
Level 2: Code. At the level of code, we think about what the current implementation could do when given arbitrary inputs and an arbitrary environment. Behaviors that cannot happen are not considered, even if it requires global reasoning to rule them out. A lot of implementation work is done at Level 2.
Level 3: Design/Logic: At the level of logic, we consider the abstract specification of each unit of a program. When using other units, we only consider the guarantees made by the spec, and assume they may be replaced at any time with a different implementation. Many programs which are correct when viewed at Level 2 are not correct when viewed at Level 3, because they rely on behavior which is not guaranteed to hold in all future versions. Most software design is done at Level 3.
Isn’t our goal to deliver working software to customers, and so Level 2 correctness is all that’s important?
No, our goal is to be able to continue to deliver working software far into the future. Level 3 is all about how modular are the interactions between the components of your software, and that’s important if you care at all about having different versions of those components, like, say, if you wanted to rewrite one of them tomorrow.
What is the lesson we can learn from the SimCity use after free error?
This is why it’s important to make your APIs conform as strictly to the spec as possible, at least in Debug mode.
This all could have been avoided if DOS’s free were to deliberately zero-out the memory.
Hyrum’s Law
Reminder: The most important parts of our craft deal not with code, but with the logic underneath
Software Design only exists at the level of logic.
List Level 2 elements
The object of study of Level 2 is the code. Any statement that can be phrased in terms of the code, but not a specific trace or state, is a Level 2 statement.
The corresponding manner of reasoning is first-order logic. This means we can write down formulas that say “for all inputs X, does this property hold?” or “does there exist an input Y, such that this function crashes?” What we can’t do is quantify over other functions.
List Level 3 elements
The object of study of Level 3 is the specification. There are many, many ways of writing specifications, but a popular one is the Hoare triple: preconditions and postconditions.
At Level 3, we can ask questions about all possible implementations of malloc, like “does this program have a memory error?”
The corresponding manner of reasoning is higher-order logic. Higher-order logic is like first-order logic, but we can now quantify over functions.
Can you retrieve design information from the code?
The information of a program’s design is largely not present in its code. There are many designs that correspond to the exact same code, and so recovering all the design information is actually impossible.
Why self documenting code is not possible?
Because the information of a program’s design is largely not present in its code. There are many designs that correspond to the exact same code.
Why TDD is not a substitute for design?
Test too much and be too specific. Is it part of the design that postProfileUpdateToServer must call appState.saveCurrentState twice, and it chooses to do so once by calling logger.logUpdateEvent?
The code should not follow the tests, nor the tests the code. They should both follow the design.
Why TDD is not a substitute for design?
Test too much and be too specific. Is it part of the design that postProfileUpdateToServer must call appState.saveCurrentState twice, and it chooses to do so once by calling logger.logUpdateEvent?
The code should not follow the tests, nor the tests the code. They should both follow the design.
What is the purpose of a documentation?
The purpose of documentation is not just to describe how the system works today, but also how it will work in the future and across many versions
What are the benefits of a spec in Joel eyes?
When you design your product in a human language, it only takes a few minutes to try thinking about several possibilities, revising, and improving your design.
Giant reason number two is to save time communicating. When you write a spec, you only have to communicate how the program is supposed to work once. Everybody on the team can just read the spec.
What does “code knowledge” means
Code A knows about code B when B is referenced in the proof of correctness of A.
What smell do you identify when you search for some behavior very deep in the code?
When you have to read a ton of things to make sure a thing can happen or not you are probably searching for unstable guarantees, that is, implementation guarantees, instead of design guarantees. You shouldn’t have to dig deep, use the specification.