Exercise 9

Moderatoren: pmueller, SE - Design and Construction

Ben Kohr
Windoof-User
Windoof-User
Beiträge: 34
Registriert: 14. Apr 2015 17:41

Exercise 9

Beitrag von Ben Kohr » 8. Jul 2018 11:54

Hi,

regarding Exercise 9:

- Task 1: What exactly is meant with the "Note:" in Task 1? I understood that an e.g., SimpleTask is "consumed" by a Dependet/BillableTask should not "exist" anymore afterwards, is has become the new/wrapped Task. But what exactly is meant with "not reference the wrapped tasks in otder to not lose the added state"? Don't we have to have a reference to not lose the state of the inner, e.g., Simple Task?

- Task 3: (note) The printed example are not completely as described, the Priority is missing in the CSV format and the order of tasks is different in both examples (when implementing the processing straight-forward).

- Task 1/2/3: Is it possible in this setting that classes fulfill both an abstract and a concrete role in a pattern? Should we use both or only the abstract/concrete annotation in such cases?

- Task 1/2/3: If we annotate a class, should we annotate a corresponding object, too?

- Task 1/2/3: Are we supposed to find all the patterns (Visitor, Bridge, Decorator, Builder) in the code?
(I have difficulties with finding a specifc one... :) )

Best,
Ben

pmueller
Moderator
Moderator
Beiträge: 87
Registriert: 25. Jan 2018 11:14

Re: Exercise 9

Beitrag von pmueller » 9. Jul 2018 08:50

Hi,
Ben Kohr hat geschrieben:
8. Jul 2018 11:54
- Task 1: What exactly is meant with the "Note:" in Task 1? I understood that an e.g., SimpleTask is "consumed" by a Dependet/BillableTask should not "exist" anymore afterwards, is has become the new/wrapped Task. But what exactly is meant with "not reference the wrapped tasks in otder to not lose the added state"? Don't we have to have a reference to not lose the state of the inner, e.g., Simple Task?
You obviously need a reference in the wrapping object. But there should not be one outside of it.
Ben Kohr hat geschrieben:
8. Jul 2018 11:54
- Task 3: (note) The printed example are not completely as described, the Priority is missing in the CSV format and the order of tasks is different in both examples (when implementing the processing straight-forward).
That the formats do not encode all features is intentional. The order is not important.
Ben Kohr hat geschrieben:
8. Jul 2018 11:54
- Task 1/2/3: Is it possible in this setting that classes fulfill both an abstract and a concrete role in a pattern? Should we use both or only the abstract/concrete annotation in such cases?
If you think this is the case, use both annotations.
Ben Kohr hat geschrieben:
8. Jul 2018 11:54
- Task 1/2/3: Are we supposed to find all the patterns (Visitor, Bridge, Decorator, Builder) in the code?
(I have difficulties with finding a specifc one... )
Yes.

Best,
Patrick

Jan.K
Neuling
Neuling
Beiträge: 3
Registriert: 9. Jul 2018 12:48

Re: Exercise 9

Beitrag von Jan.K » 9. Jul 2018 12:59

pmueller hat geschrieben:
9. Jul 2018 08:50
Ben Kohr hat geschrieben:
8. Jul 2018 11:54
- Task 3: (note) The printed example are not completely as described, the Priority is missing in the CSV format and the order of tasks is different in both examples (when implementing the processing straight-forward).
That the formats do not encode all features is intentional. The order is not important.
However, also to my understanding, the provided outputs do not fully comply to the described task and main method.
1. The task asks to print the priority in the CSV output, and "Priority" is also printed in the output schema headline, but the priority values are missing in the tasks.
2. The outputs list task 5 to 1, then task 6. But in the main method, the list containg task 5 - 1 is reversed, hence having the order 1 - 5.

Benutzeravatar
5seconds
Endlosschleifenbastler
Endlosschleifenbastler
Beiträge: 155
Registriert: 27. Apr 2013 10:44

Re: Exercise 9

Beitrag von 5seconds » 11. Jul 2018 11:16

Hi,

I have one question regarding InvoiceVisitor: In which unit of time does the billing work? E.g. if a task has a duration of half an hour, does the invoice hold half the hourly rate or nothing?

pmueller
Moderator
Moderator
Beiträge: 87
Registriert: 25. Jan 2018 11:14

Re: Exercise 9

Beitrag von pmueller » 11. Jul 2018 11:23

Hi,

I've updated the Sheet.
The main method in my solution was missing the .reverse call. I'm sorry about this, it should not affect you scores.
In addition my solution was missing the priority in the CSV output.
CSV output omits the Project, whereas the Todo txt ouput omits the duration.
5seconds hat geschrieben:
11. Jul 2018 11:16
Hi,

I have one question regarding InvoiceVisitor: In which unit of time does the billing work? E.g. if a task has a duration of half an hour, does the invoice hold half the hourly rate or nothing?
You can calculate this using minutes or seconds.


Best,
Patrick

topracer
Mausschubser
Mausschubser
Beiträge: 53
Registriert: 10. Jan 2014 19:14

Re: Exercise 9

Beitrag von topracer » 11. Jul 2018 13:46

Hello,
I have another two questions regarding the exercise:

1.) If I understand correctly, Project (which is also a Visitable) should just call the accept(...) methods of all contained tasks in its own accept(...) method. In the Visitor pattern as introduced in the lecture, however, the ConcreteElements all only call v.visit(this) on the Visitor v. So, is this exception from the "standard" visitor handling procedure still a "valid" implementation of the "pure" Visitor pattern?

2.) If a concrete visitor such as InvoiceVisitor does only care about one particular dynamic type (in this case BillableTask), is it fine if the visit(...) methods corresponding to the other types do nothing and just return Unit?

EDIT: Another small question: What means to "check this property transitively" in task 2?

pmueller
Moderator
Moderator
Beiträge: 87
Registriert: 25. Jan 2018 11:14

Re: Exercise 9

Beitrag von pmueller » 11. Jul 2018 14:13

Hi,
topracer hat geschrieben:
11. Jul 2018 13:46
1.) If I understand correctly, Project (which is also a Visitable) should just call the accept(...) methods of all contained tasks in its own accept(...) method. In the Visitor pattern as introduced in the lecture, however, the ConcreteElements all only call v.visit(this) on the Visitor v. So, is this exception from the "standard" visitor handling procedure still a "valid" implementation of the "pure" Visitor pattern?
This is similar to the example of the slides (slide 33), both visitAdd and visitMult call accept on the left and right hand side of the Expression. The visit method of a aggregate element defines the iteration order on the sub elements in this case.
topracer hat geschrieben:
11. Jul 2018 13:46
2.) If a concrete visitor such as InvoiceVisitor does only care about one particular dynamic type (in this case BillableTask), is it fine if the visit(...) methods corresponding to the other types do nothing and just return Unit?

The visitor in this design should only return Unit on all accept methods, whereas the Visitor in the lecture is parametrized over the return type. Only the fields of the concrete visitors should be set (so that getInvoice, getNextDeadline and isConsistent) return the correct value. In the case of the InvoiceVisitor that does not visit a BillableTask, this should just be a Invoice without any items and a total of 0.
In addition, it can be the case that a DependentTask wraps around a BillableTask.
topracer hat geschrieben:
11. Jul 2018 13:46
EDIT: Another small question: What means to "check this property transitively" in task 2?
The Task a DependentTask depends on can be DependentTask itself and so on...

Best,
Patrick

topracer
Mausschubser
Mausschubser
Beiträge: 53
Registriert: 10. Jan 2014 19:14

Re: Exercise 9

Beitrag von topracer » 11. Jul 2018 15:08

Okay, thank you for the answer!
pmueller hat geschrieben:
11. Jul 2018 14:13
The visit method of a aggregate element defines the iteration order on the sub elements in this case.
You mean the accept(...) method in this case, right?
pmueller hat geschrieben:
11. Jul 2018 14:13
In addition, it can be the case that a DependentTask wraps around a BillableTask.
Ok, at this point there is something else which is unclear to me: If a visitable task wraps another task, what should the accept(...) method do in this case? It can either just call the visitor's visit(...) method on this particular task instance or forward the access to its component by calling component.accept(...) (in which case, however, we will lose the information about the added behaviour/state). Or, as a third approach, do both successively.
But in the latter case we may get wrong results depending on the semantics of the used visitor (e.g. if the visitor only expects one object and methods like duration() are called redundantly).
Or is it okay / desired that all nested components are visited, and it is just the ConcreteVisitor's responsibility to ensure that an operation is performed on the right objects, e.g. only for SimpleTasks (as the last element in the nesting hierarchy)?

Best regards,
Frederic

pmueller
Moderator
Moderator
Beiträge: 87
Registriert: 25. Jan 2018 11:14

Re: Exercise 9

Beitrag von pmueller » 11. Jul 2018 15:24

topracer hat geschrieben:
11. Jul 2018 15:08
You mean the accept(...) method in this case, right?
No. The implementation of the visit calls the accept methods of the contained elements. Maybe my wording was not precise enough here:
pmueller hat geschrieben: The visit method of a aggregate element [...]
With this I meant the visit method of a visitor that handles the aggregate element - called by the accept method.
topracer hat geschrieben:
11. Jul 2018 15:08
Or is it okay / desired that all nested components are visited, and it is just the ConcreteVisitor's responsibility to ensure that an operation is performed e.g. only for SimpleTasks (as the last element in the nesting hierarchy)?
Yes. This can be quite problematic if you have to modify the behaviour if a Task is both Billable and Dependent. Which is one reason why the order of the two possible additional fields in the CSV output does not matter.
In general this is one area where you have to make design decisions for the Visitor pattern.

Best,
Patrick

topracer
Mausschubser
Mausschubser
Beiträge: 53
Registriert: 10. Jan 2014 19:14

Re: Exercise 9

Beitrag von topracer » 11. Jul 2018 16:39

Okay, thank you very much, I think I've got it now! :)
pmueller hat geschrieben:
11. Jul 2018 15:24
No. The implementation of the visit calls the accept methods of the contained elements. Maybe my wording was not precise enough here:
Ah okay. So, what we achieve by doing this (instead of calling the accept() methods in Project's accept() directly) is a higher decoupling between the ConcreteElement classes (in this case Project) and the visitors (because we don't have Project in a visit signature), which simplifies later modifications to the ConcreteClasses, right?

pmueller
Moderator
Moderator
Beiträge: 87
Registriert: 25. Jan 2018 11:14

Re: Exercise 9

Beitrag von pmueller » 11. Jul 2018 17:28

Hi,
topracer hat geschrieben:
11. Jul 2018 16:39
Ah okay. So, what we achieve by doing this (instead of calling the accept() methods in Project's accept() directly) is a higher decoupling between the ConcreteElement classes (in this case Project) and the visitors (because we don't have Project in a visit signature), which simplifies later modifications to the ConcreteClasses, right?
I'll stay with the example from slides (the scala example at the end)
The accept methods are just there to achieve the correct dispatch and in the case of this example destructuring. Nothing else. In the case of the Add, we call visitAdd with the left and right expressions. Therefore the visitors "knows" that it operates on an Add. The visitMult with the same signature handles the left and right sides of a Multiplication.
Another design could be (I've not checked whether this is syntactically correct):

Code: Alles auswählen

trait Visitor[T] {
def visitAdd(add:Add):T
def visitMult(mult:Mult):T
}
class concreteVisitor extends Visitor[Double] {
def visitAdd(add:Add):Double = 
	add.l.accept(this) + add.r.accept(this)
}
class Add extends Expression {
	def accept[T](visitor: Visitor[T]):T = {
		visitor.visitAdd(this)
	}
}
We even could omit the Add/Mult part of the visit methods and just call them both visit, at least in most OO languages.
Again, the accept methods only make sure that the visitor handles the correct type.

For the Task at Hand: The Visitors should be able to visit a Project as you can see in the Main method.

Best,
Patrick

topracer
Mausschubser
Mausschubser
Beiträge: 53
Registriert: 10. Jan 2014 19:14

Re: Exercise 9

Beitrag von topracer » 12. Jul 2018 15:47

Okay, thank you for the explanations.

Antworten

Zurück zu „Software Engineering - Design and Construction“