Sie sind auf Seite 1von 21

System Design (1010/1039) / MSE Prof. P. Fromm / Prof. M.

Lipp
Exam System Design (1010/1039) / MSE
(Prüfungsleistung) WS2014/15 A (02.02.15)
Support Material  UML Reference List

Remarks  Please check immediately if all pages of the exam (21) + UML
reference list are available
 Duration: 180min
 Enter your name, Matr.-Number on the first page and sign it
 If you finish within the last 15min of the exam, please stay
seated to avoid disturbing your colleagues.

Name

Matr.-Number

Signature

Max. Points Achieved Points


1. Knowledge Corner 15
2. Extending the Navi System 30
3. Paper Towel Dispenser 30
3. Template Class 25

Total Points Exam 100


Additional Points from Lab 15
Total 115

Mark: ________

Page 1 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

1 Knowledge Corner (15)


For the following questions, only one answer is right or the best answer. Marking:
Correct answer: + points
No answer: 0 points
Wrong answer: - points

[3] You see a use case in a use case diagram that has no association with any of the actors…
This is not allowed.

This means that the use case is triggered by the system internally (e. g. by a timer).

X This is OK if the use case has a relationship to another use case.

[2] The difference between the keywords struct and class is…
… that struct may be used only in C

(X) … that struct is used in C to define classes while class is used in C++ to define
classes.
(X) … that struct can only be used to define classes without methods.
Some people have pointed out that it is formally possible to define a method in a struct in C++ (never seen this being
used, though), therefore either the second or third answer will be accepted.

[2] Mark the sentence describing a functional requirement.


The device must be available in three colors.

X The device is locked after entering a wrong PIN for three times.

The device mustn’t cost more than 300€.

[2] Sequence diagrams …


… are best used to describe the steps of an operation or function..

… are very useful to describe reactive systems,.

X … are mostly used to describe the interaction between objects.

Page 2 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

[2] If A and B are classes and class A has an attribute of type B*, then
X … their relationship is an association, aggregation or composition

… nothing can be said about their relationship.

… their relationship cannot be a composition.

[2] Testing …
… tries to proof software correctness.

… should not be done in parallel to software development.

X … is not debugging.

[2] System Tests focus on …


X … user and system requirements.

… performance and reliability requirements.

… detailed component requirements.

Page 3 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

2 Extending the navigation system (30)


In the lab we have designed a rather inelegant implementation of a route, by providing different
containers for the waypoints and the points of interest of the route. A better implementation is a
polymorph design:
- All waypoints and POI’s are stored in separate databases
- The route itself is stored in a single common container, which contains both the waypoints
and the POI’s in the order the driver would reach them (sketch below).
This design is already implemented in the class diagram below

x
o x

o
x
x
x – Waypoints
Route o – Points of Interest

2.1 Class relations / Screen class(10)


Until now we have implemented a hardcoded print method in the CRoute, CWaypoint and CPoi
class. A drawback of this implementation is the limitation to console output only. For a real life
system, we want to extend the design by providing different visualization classes i.e. a CRT
(console) class for debugging purposes and a GUI class for a graphical representation of the route.
For this, three classes CScreen, CCRTScreen and CGUIScreen are added to the system. In a first
design approach, you decide to
 keep the implementation of the print routines in the CPOI and CWaypoint class
 pass the information, which screen class will used, to the print function via CRoute by
providing an additional parameter (pointer to CScreen)
 and to use a dynamic casting operation in the CPOI and CWayoint class to determine
which screen is in use.
The casting operation in CPoi / CWaypoint look as follows:
void CPOI::print(int format, CScreen* screenType)
{
if (dynamic_cast<CGUIScreen*>(screenType))
{
//The code for “printing” a POI on a GUI screen
}
else if (dynamic_cast<CCRTScreen*>(screenType))
{
//The code for “printing” a POI on a CRT screen
}
}

Page 4 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

Add all missing class relations to the class diagram below. Do not forget multiplicities and possible
dependencies.

Page 5 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

2.2 Design review (10)


In a design review, you get the following feedback: “…the design needs to be improved, because it
does not follow the Model/View/Controller pattern1 and it violates the concept of loose coupling….”

Provide the code for the following 2 functions, fulfilling the following requirements (2)
 Check, if the screen is connected to a route
 If yes, call the route print routine using the current screen object as parameter
void CGUIScreen::drawRoute()
{
if (m_pRoute != 0)
{
m_pRoute->print(this);
}

}
void CCRTScreen::drawRoute()
{
if (m_pRoute != 0)
{
m_pRoute->print(this);
}
}
Considering your implementation, explain the review comment. (8)
 What does it mean?
 What problems can you expect during the implementation?
 How can the design be improved? Provide a sketch (conceptual class diagram, containing
the relevant classes, dependencies and methods).

The derived screen classes (CGUIScreen, CCRTScreen) only act a type provider, they do not
implement any real “view” functionality. Hard to implement, hard to test design due to the many
relations. Circular dependencies require forward declarations (normal includes will not work).
Improvement: Provide data of CWaypoint and CPoi via CRoute to Screen classes, implement the
drawing functionality up there.

1
Model–view–controller (MVC) is a software architectural pattern for implementing user interfaces. It divides
a given software application into three independent parts, separating the data structure (model) from the
processing (control) and presentation layer (view).
Page 6 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

2.3 Implementation of overloaded operators (10)


You want to be able to compare two different routes on equality. Two routes A and B are
considered to be equal, if
 all Waypoints and Poi’s of route A are also included in route B
AND
 all Waypoints and Poi’s of route B are also included in route A
Two compare the content of two routes, you can either compare the addresses of the contained
waypoints and Poi’s (solution 1) or the content of the objects (solution 2). Before starting with the
implementation, discuss the pro’s and con’s of both solutions.
2 Points
Solution Prerequisites Advantages Disadvantages
1 none fast Different addresses may
contain same objects (e.g. after
an object has been copied) 
wrong comparison result

2 Overloaded == operator Real content is Slower, complex casting


for objects required compared required in case POI’s are
compared with WP’s

You decide to implement both solutions and to use a preprocessor directive to either perform a
comparison by pointer or by value. Use the preprocessor defines below and provide the complete
and syntactically correct code.

#define BYPOINTER 1
#define BYVALUE 2

//By setting COMPARE to either BYVALUE or to BYPOINTER the corresponding


//comparison code will be used
Page 7 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

#define COMPARE BYVALUE

bool CRoute::operator ==(const CRoute& rop)


{
//Check size
//1 – alternatively, loops have to be doubled
if (m_pRoute.size() != rop.m_pRoute.size()) return false;

//Check content
//2
for (list<CWaypoint*>::const_iterator source=m_pRoute.begin();
source != m_pRoute.end(); ++source)
{
//1
bool elementFound = false;

//Compare with target list


//1
for (list<CWaypoint*>::const_iterator
dest=rop.m_pRoute.begin(); dest != rop.m_pRoute.end(); ++dest)
{
#if COMPARE == BYPOINTER
//1 if ((*dest) == (*source))
elementFound = true;
#elif COMPARE == BYVALUE
//1 if ((*(*dest)) == (*(*source))) //complex casting
elementFound = true;
#else
#error Wrong configuration of the compare directive
#endif
}

//1
if (!elementFound) return false;
}

return true;
}
Page 8 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3 Paper Towel Dispenser (30)


We want to design the controller for a Paper Towel Dispenser. We have the following description:
The dipenser has a sensor that sends an event (“hand detected”)
when a hand comes closer than 5cm and another event (“hand
removed”) when the hand is removed again.
When turned on, a motor within the dispenser moves the paper
forward and thus dispenses the towel. Coupled to the motor there is
another (internal) sensor that sends an event (“motor turn”) after
each turn of the motor. Due to the chosen gear reduction, one pulse
indicates that the paper has moved forward 2mm.
A third (again internal) sensor sends a constant signal (“paper
empty”) when the paper supply is exhausted.
Finally, a fourth internal sensor sends an event “dispenser opened”
when the dispenser is opened for maintenance and an event
“dispenser closed” when it is closed again.
The controller must implement the following behaviour: In response to receiving the “hand
detected” signal the motor is started. Usually, the motor stops again after 30cm of paper have been
ejected. If, however, the user has his hand still close to the external sensor after 30cm of paper
have been ejected, the dispenser keeps the motor running until the hand is removed or a
maximum of 60cm of paper have been ejected.
The paper supply sensor should be checked each time when a “motor turn” event is received. If the
supply is exhausted, the dispenser enters a stalled state and turns an error indicator (red led) on. It
leaves this state only when the paper supply has been refilled. After refilling, the dispenser waits
for a hand to come close to the sensor (it does not automatically resume paper output).

Page 9 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3.1 UML Activity Diagram (5)

Draw a UML activity diagram that describes the normal operation from waiting for a hand close to
the sensor until the towel is ejected. Assume that the hand is removed immediately after the motor
starts. Omit the special case of empty supply. Remember that the descriptions of activities must
include a verb. Observe the formal rules for UML activity diagrams.
Start with an activity “Check hand sensor”. Another activity that you should use somewhere in your
diagram is “Wait for motor turn event”. Granularity hint: you should have about 5 activities and 2
decision points.

0.5

1 (-0.5, -0.5)

0.5
0.5

0.5

0.5

0.5

1 (-0.5, -0.5)

Page 10 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3.2 Implementation

You are now to implement the controller for the paper towel dispenser. There is already an
interface class for the controller and some predefined actor and sensor classes.

The motor can be turned on and off by invoking the appropriate methods. The implementation of
the run() method is given as:
void CController::run()
{
while (true) {
handleEvent(m_evSrc->getEvent());
}
}

Page 11 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3.2.1 State Diagram (10)

Draw a state diagram for the controller. Use the event names and actions as can be derived from
the class diagram. Observe the formal rules for UML diagrams. Complexity hint: you should need
about 4 states.

1 0.5

0.5
0.5

1 1.5
0.5
0.5

0.5 0.5 0.5

1
0.5
0.5
0.5

Page 12 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3.2.2 Implementation class for CController (10)

Provide your own implementation of a controller class (both class definition and method
implementations). Use the “switch(state)” pattern from the lecture (not using the pattern results in 0
points).

enum State { Idle, Eject1, Eject2, WaitForRefill }; 0.5

class MyController: public CController


{
private:
State m_state;
int m_cnt; 0.5

public:
MyController(CMotor* motor, CLed* led, 0.5
CEventSource* evtSrc, CPaperSupplySwitch* paperSw);
void handleEvent(Event event);
};

MyController::MyController(CMotor* motor, CLed* led,


CEventSource* evtSrc, CPaperSupplySwitch* paperSw)
{
m_motor = motor;
m_led = led; 0.5
m_evSrc = evtSrc;
m_ps = paperSw;

m_state = Idle;
m_cnt = 0; 0.5
}

void MyController::handleEvent(Event event)


{
switch (m_state) {
case Idle:
if (event == HandDetected) { 0.5
m_motor-> on();
m_cnt = 0; 0.5
m_state = Eject1;
}
break;

case Eject1:
if (event == MotorTurn) { 0.5
if (m_ps->isEmpty()) {
m_motor->off(); 0.5
m_led->on();
m_state = WaitForRefill;
} else if (m_cnt < 300 && !m_ps->isEmpty()) {
m_cnt += 1; 0.5
} else {
m_motor->off(); 0.5
Page 13 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

m_state = Idle;
}
} else if (event == HandRemoved) 0.5
if (m_cnt < 150) {
m_state = Eject2; 0.5
} else {
m_motor->off();
m_state = Idle; 0.5
}
}
break;

case Eject2:
if (event == MotorTurn) { 0.5
if (m_ps->isEmpty()) {
m_motor->off(); 0.5
m_led->on();
m_state = WaitForRefill;
} else if (m_cnt < 150 && !m_ps->isEmpty()) {
m_cnt += 1; 0.5
} else {
m_motor->off(); 0.5
m_state = Idle;
}
break;

case WaitForRefill:
if (event == DispenserClosed) { 0.5
if (!m_ps->isEmpty()) {
m_led->off();
0.5
m_state = Idle;
}
}
}

Page 14 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

3.2.3 Operator overloading for CMotor (5)

Your colleague points out that it would be nice to turn the motor on and off by assigning true or
false to an object of type CMotor. Provide the implementation of the required operator
overloading.

CMotor& CMotor::operator =(bool onOff) 1 (or return bool)


{
if (onOff) { 1
on(); 1
} else {
off(); 1
}
return *this; 1 (or state)
}

Page 15 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4 Template - Moving Average Filter (25)


Very often, values which are e.g. received from a sensor need to be filtered. A very simple filter is a
so-called moving average filter. Such a filter is implemented as an array. The size of the array is
determined by the stages of the filter. The example below shows a moving average filter having 3
stages. As long as the filter is not completely filled up, the new data is added to the next free
position. All stored values are then accumulated and then divided by the number of stored
elements. Once the filter is completely filled, the new value overwrites the oldest value (concept of
a ringbuffer).

Initial state:
All array elements are initialized to zero. The average value in this case is 0.
0 0 0

Filter partly filled:


The data elements 1 and 2 have been added. The average value in this case is (1+2) / 2 = 1.5.
1 2 0

Filter completely filled:


The data element 3 is added. The average value in this case is (1+2+3) / 3 = 2.0.
1 2 3

Filter more than filled:


The data element 4 is added, overwriting the oldest element 1. The average value in this case is
(2+3+4) / 3 = 3.0.
4 2 3

The Moving Average filter is implemented as a template class, taking 3 template arguments:
DATA The type of the stored data element, e.g. int, float, double…
RESULT The type of the calculated result value e.g. float in case of int elements
SIZE The number of filter stages

Page 16 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4.1 Class Declaration (4)


Provide the declaration of the CMovAvg class as specified in the diagram above.
template <class DATA, class RESULT, unsigned int SIZE> //1
class CMovAvg
{
private:
DATA m_data[SIZE]; //1
unsigned int m_numSamples;
RESULT m_total; //1

public: //1 for the methods


CMovAvg();
void add(DATA data);
RESULT getAverage();

RESULT addAndGetAverage(DATA data);

void clear();

};

Page 17 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4.2 Constructor and clear Method (4)


Provide the code for the constructor and clear() method, which are both specified as
follows:
 The attribute m_numSamples is set to 0
 The attribute m_total is set to a value representing 0 for the templated type.
 All elements of m_data are set to a value, representing 0 for the templated type.

//3
template <class DATA, class RESULT, unsigned int SIZE>
void CMovAvg<DATA, RESULT, SIZE>::clear()
{
m_numSamples = 0;
m_total = RESULT(0);

//Set all values to the default constructor value of T


for (unsigned int i = 0; i < SIZE; i++)
{
m_data[i] = DATA(0);
}
}

//1
template <class DATA, class RESULT, unsigned int SIZE>
CMovAvg<DATA, RESULT, SIZE>::CMovAvg()
{
clear();
}

Page 18 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4.3 Add and getAverage Method (4)


Provide the code for the add() and getAverage() methods, which are specified as follows:
add():
 The parameter will be added to the next free position.
 If all elements are full the oldest element will be overwritten.
getAverage():
 All stored data elements are accumulated.
 The result is divided by the number of stored elements.
Note: Make sure to use casting operations as required. The attribute m_total is not required for
these methods.

//1
template <class DATA, class RESULT, unsigned int SIZE>
void CMovAvg<DATA, RESULT, SIZE>::add (DATA data)
{
m_data[(m_numSamples++) % SIZE] = data;
}

//3
template <class DATA, class RESULT, unsigned int SIZE>
RESULT CMovAvg<DATA, RESULT, SIZE>::getAverage()
{
if (m_numSamples == 0) return RESULT(0);

RESULT result = RESULT(0);

for (unsigned int i = 0; i < (m_numSamples<SIZE?m_numSamples:SIZE);


i++)
{
result += (RESULT)m_data[i];
}

return result / (m_numSamples<SIZE?m_numSamples:SIZE);


}

Page 19 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4.4 addAndGetAverageData Method – Design (5)


The disadvantage of the previous methods add() and getAverage() is the comparable long
computation time because for every average value, the complete array has to be iterated. A better
approach is the following:
 the calculated accumulated value is stored in an internal attribute m_total
 in case a new value is added to the filter, this value will simply be added to this attribute.
 in case an oldest value is deleted during this operation, the oldest value will be substracted
from the m_total value
 the average value is calculated by dividing the m_total value with the number of stored
elements
Draw an activity diagram (implementation level) describing this algorithm.

Page 20 / 21
System Design (1010 / MSE) Prof. P. Fromm / Prof. M. Lipp

4.5 addAndGetAverageData Method – Implementation (8)


Provide the code for the operation addAndGetAverage() method which will add a data element
to the filter and return the average value using the above described algorithm.

//1
template <class DATA, class RESULT, unsigned int SIZE>
RESULT CMovAvg<DATA, RESULT, SIZE>::addAndGetAverage(DATA data)
{
//3
if (m_numSamples >= SIZE)
{
//Delete oldest element, before adding new
m_total -= m_data[m_numSamples % SIZE];
}

//1
add(data);
//1
m_total += (RESULT)data;
//2
return m_total / (m_numSamples<SIZE?m_numSamples:SIZE);

Page 21 / 21

Das könnte Ihnen auch gefallen