高级农民
- 积分
- 2117
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2012-7-13
- 最后登录
- 1970-1-1
|
上周工作比较忙,周末把周中的任务一起补上了。明天希望能恢复打卡。
7/20 Reading 5 Designing Specifications
Three dimensions when comparing specs:
1. deterministic
- rather than use non-deterministic (sometimes behave one way and other times behave another way, e.g. use random number, timing of concurrent process), use undetermined.
- undetermined spec could have deterministic implementation.
2. declarative
- properties of final outcome and how it relates to the input.
- declarative spec is preferable than operational spec, as the latter's audience is maintainer and the former's audience is client programmer. It is better to leave comment between codes for the maintainer.
3. strong
- weaker precondition & stronger postcondition => stronger spec
- it is safe to replace the old spec w/ stronger new spec
What is good spec?
- coherent
- usually define postcondition to say if the input is such, a certain exception is thrown. That is better to define a stronger precondtion, which cause client more trouble. The key factors are the cost of the check (writing & executing the code), e.g. private or public method.
7/21 Reading 6: Avoid Debugging
- Makes bugs impossible
- static checking
- dynamic checking
- immutability, e.g. String (immutable type), final (immutable reference)
- Localize bug
- checking precondition => defensive programming. e.g. assert (off r default), jvm argument + -ea. use assertion only in development and testing, never used in release. <= emm, not sure this is applicable in real case, we do valid input check all the time in day to day programming, and throw BadInputException as early as possible.
- incremental development
- unit testing, regression testing
- modularity, encapsulation (access control, variable scope - declare your variable when you need it, to avoid unnecessary larger scope)
7/22 Reading 7: Mutability and Immutability
- mutable variable usually created for the benefit of performance, like StringBuilder.
- However, it is general better to use immutable variable
- Date, mutable object, deprecated => ZonedDateTime
- defensive copying, advantage: client could do whatever, disadvantage: resources wasting, better to have immutable object
- root cause: multiple references, also called alias, to a mutable object
- It is important to include the side effects (e.g. mutation) on the spec of the method
7/23 Reading 8: Debugging
- reproduce the bug w/ a repeatable test case (which could be attended as a regression test)
- reduce the input to manageable input
- cut the input by half, e.g. binary search
- pick smaller module of the input
- use scientific method to find the bug
- study the data, e.g. stack trace from exception, small test case
- make hypothesis, e.g. modularize your program to localize the bug
- do a experiment, e.g. different test case, print statement/assertion, debugger
- repeat
- tips
- bug localization by binary search (finding bug is like a search process)
- prioritize your hypotheses, e.g. more recent code have higher possibility of leading to the bug
- swap components, but do not do this unless have good reason to suspect a component
- make sure your source code and object code r up to date
- get help, e.g. talk to your yellow duck :)
- sleep on it, trade latency for efficiency
- fix the bug thoughtfully, not slapdash
- identify the type of bug, e.g. is it a coding error, or a design error
- think if the bug has any relatives
7/24 Reading 9: Abstract Data Type
- a.k.a
- Abstraction
- Modularity
- Encapsulation
- Information hiding
- Separation of concerns
- a type is characterized by the operations you can perform on it, e.g. no need to worry about the data structure behind it
- operations of an abstract type:
- creators, create new objects of the type, e.g. constructor, factory method, valueOf(), new ArrayList()
- producers, create new objects from old objects of the type
- observers, .size()
- mutators, change objects, e.g. Set.add()
- design abstract data type
- few simple operation
- coherent, general?
- adequate, e.g. enough operations to extract the property of the object
- representation / implementation independent
- An ADT is tested by generating tests for each of its operations, but using the creators, producers, mutators, and observers together in the same tests.
7/25 Reading 10: Abstraction Functions and Rep Invariants
- preserve its own invariants, e.g. immutable
- representation exposure, defensive copy, e.g. should never store or return the direct reference to a mutable object, just use immutable type (immutable wrappers around mutable data types, e.g. Google Guava immutable set)
- abstract value & rep value, more like one to many relationship
- document rep invariant & abstraction functions & safety from rep exposure (access control & immutablity)? this is not usually seen in industry codes?
- Structure induction (proving invariant)
- established by creators & producers
- preserved by mutators and observers
- no representation exposure occurs
- ADT invariants replace preconditions
7/26 Reading 11: Interfaces
- list of method signatures
- subtype, the spec is stronger that of supertype
- advantages of interface
- documentation for both complier and human
- allowing performance trade off, e.g. different implementation for different scenarios for better performance
- optional methods, e.g. by omitting optional method in Java List interface to create immutable list
- methods w/ intentionally undetermined spec
- multiple views of one class
- more and less trustworthy implementations |
|