Description
Question 1 [6 marks] Parnas advocates faking a rational design process as depicted in the figure below. The faked documentation follows these steps: Requirements (SRS) → Design (MG and MIS) → Application Implementation (code) → Verification and Validation (Unit Testing, Integration Testing, Review). How are the principles of a) abstraction and b) separation of concerns applied in a rational design process? In your answer you can refer to any aspects of the process, documentation, and/or Parnas’s principles.
[Fill in your answer below —SS]
- Abstraction The process of faking a rational design process is itself an abstraction. The abstraction, (information hiding), increases through application, S. Design Doc, Req. Doc. The Req. Doc is the most abstract document because it does not specify any implementation instruction, but only the requirement. The S. Design Doc (MIS, MG) is the second most abstract stage. Because in the level, some more instructions like the concept and the sytax and semantics are provided to programmer. The application is the the least abstract one, because it need to contain all code for the program to work.
- The MG also illustrates Abstraction. In an MG, there are some typical information hiding such as Hardware Hiding, Software Hiding, and Behave hiding. And also we hide secrets in our modules. All of these show the concept of abstraction, which is achieved by information hiding. MIS is also an abstraction case. In a MIS, we do not need to show the specific implementation of the module, instead we only provide sytax, semantics, and other specification to the programmer. The process and this document is actually an abstraction because it omits unnecessary implementation details.
- Separation of Concerns MG illustrates Separation of Concerns, by writing MG, we decompose the whole system to different module, which provides service and secret.
- The test process also illustrates Separation of Concerns, because instead of doing integration testing first, we use unit tests to verify the reliability of each method in a module. By doing this, we can find the flaw in a specific area.
- Abstraction is a special case of separation of concerns. Many different models of the same entity can be produced by abstraction
Consider the specification for two modules: SeqServices and SetOfInt.
Sequence Services Library
Module
SeqServicesLibrary
Uses
None
Syntax
Exported Constants
None
Exported Types
None
Exported Access Programs
| Routine name | In | Out | Exceptions |
| max val | seq of Z | N | ValueError |
| count | Z, seq of Z | N | ValueError |
| spices | seq of Z | seq of string | ValueError |
| new max val | seq of Z, Z → B | N | ValueError |
Semantics
State Variables
None
State Invariant
None
Assumptions
- All access programs will have inputs provided that match the types given in the specification.
Access Routine Semantics max val(s)
- output: out := |m| : N such that (m ∈ s) ∧ ∀(x : Z|x ∈ s : |m| ≥ |x|)
- exception: (|s| = 0 ⇒ ValueError)
count(t,s)
- output: out := +(x : Z|x ∈ s ∧ x = t : 1)
- exception: (|s| = 0 ⇒ ValueError)
spices(s)
- output: out := hx : Z|x ∈ s : (x ≤ 0 ⇒ “nutmeg”|True ⇒ “ginger”)i
- exception: (|s| = 0 ⇒ ValueError) new max val(s, f)
- output: out := max val(hx : Z|x ∈ s ∧ f(x) : xi)
- exception: (|s| = 0 ⇒ ValueError)
Set of Integers Abstract Data Type
Template Module
SetOfInt
Uses
None
Syntax
Exported Types SetOfInt = ?
Exported Constants
None
Exported Access Programs
| Routine name | In | Out | Exceptions |
| new SetOfInt | seq of Z | SetOfInt | |
| is member | Z | B | |
| to seq | seq of Z | ||
| union | SetOfInt | SetOfInt | |
| diff | SetOfInt | SetOfInt | |
| equals | SetOfInt | B |
Semantics
State Variables s: set of Z
State Invariant
None
Assumptions • The SetOfInt constructor is called for each object instance before any other access routine is called for that object. The constructor can only be called once. All access programs will have inputs provided that match the types given in the specification.
Access Routine Semantics
new SetOfInt(xs):
- transition: s := ∪(x : Z|x ∈ xs : {x})
- output: out := self
- exception: none is member(x):
- output: x ∈ s
- exception: none to seq():
- output: out := set to seq(s)
- exception: none
union(t):
- output: SetOfInt(set to seq(s)||to seq())
# in case it is clearer, an alternate version of output is: SetOfInt(set to seq(s ∪ {x : Z|x ∈ t.to seq() : x}))
- exception: none
diff(t):
- output: SetOfInt(set to seq(s ∩ complement(to seq())))
- exception: none
size():
- output: |s|
- exception: none empty():
- output: s = ∅
- exception: none
equals(t):
- output: ∀(x : Z|x ∈ Z : x ∈ to seq() ↔ x ∈ s) # this means: t.to seq() = s
- exception: none
Local Functions
set to seq : set of Z → seq of Z
set to seq(s) ≡ hx : Z|x ∈ s : xi # Return a seq of all of the elems in the set s, order does not matter
complement : seq of Z → set of Z complement(A) ≡ {x : Z|x 6∈ A : x}
Question 2 [15 marks]
[Complete Python code to match the above specification. —SS] The files you need to complete are: SeqServicesLibrary.py and SetOfInt.py. Two testing files are also provided: expt.py and test driver.py. The file expt.py is pre-populated with some simple experiments to help you see the interface in use, and do some initial test. You are free to add to this file to experiment with your work, but the file itself isn’t graded. The test driver.py is also not graded. However, you may want to create test cases to improve your confidence in your solution. The stubs of the necessary files are already available in your src folder. The code will automatically be imported into this document when the tex file is compiled. You should use the provided Makefile to test your code. You will NOT need to modify the Makefile. The given Makefile will work for make test, without errors, from the initial state of your repo. The make expt rule will also work, because all lines of code have been commented out. Uncomment lines as you complete work on each part of the modules relevant to those lines in expt.py file. The required imports are already given in the code. You should not make any modifications in the provided import statements. You should not delete the ones that are already there. Although you can solve the problem without adding any imports, if your solution requires additional imports, you can add them. As usual, the final test is whether the code runs on mills.
Any exceptions in the specification have names identical to the expected Python exceptions; your code should use exactly the exception names as given in the spec.
You do not need to worry about doxygen comments. However, you should include regular comments in the code where it would benefit from an explanation.
Remember, your code needs to implement the given specification so that the interface behaves as specified. This does NOT mean that the local functions need to all be implemented, or that the types used internally to the spec need to be implemented exactly as given. If you do implement any local functions, please make them private by preceding the name with double underscores.





