public boolean uploadResult(Lecturer lecturer, Student student, String result) throws NullPointerException {
Schedule currentSchedule = scheduleService.findCurrentSchedule();
if (currentSchedule.getWeek() != 12) {
throw new IllegalArgumentException("Cannot upload result until the end of the semester.");
}
Student stu = studentService.findOne(student);
List<Enrolment> enrolments = stu.getPerformance();
Enrolment enrolment = null;
for (Enrolment e : enrolments) {
CourseOffering offering = e.getOffering();
if (offering.getLecturer().equals(lecturer) && offering.getSchedule().equals(currentSchedule)) {
enrolment = e;
break;
}
}
if (enrolment == null) {
throw new NullPointerException("There is no such student in the lecturer's course");
}
enrolment.setResult(result);
studentService.save(student);
return true;
}
我试图理解上面的代码,以便在序列图中说明它,但我在理解其中一些代码时遇到一些困难,特别是这部分:
List<Enrolment> enrolments = stu.getPerformance();
Enrolment enrolment = null;
for (Enrolment e : enrolments) {
CourseOffering offering = e.getOffering();
if (offering.getLecturer().equals(lecturer) &&
offering.getSchedule().equals(currentSchedule)) {
enrolment = e;
break;
我可能来晚了一点,但我会尽力回答你的问题,希望能帮助其他人处理类似的问题。我认为主要问题不在于处理 SD 中对象的列表或聚合的说明,但也许更重要的事实是,您很难理解代码的实际用途。在我看来,仅仅查看序列图并没有多大帮助。我生成了两个 PlantUML 文件,使用您的代码为您提供代码的静态和动态视图。之后我们将看一个示例来理解您提供的代码行。
正如 @muszeo 正确指出的那样,您有时很难找到调用实际方法的正确目标(例如 getOffering 的目标是 Type Enrolement 的对象,而不是 CourseOffering)。但不要害怕,绘制 SD 是一项相当具有挑战性的任务。让我们看一个简单的类图,我们只会看您业务域的对象(忽略服务):
如果您查看图表,您会发现学生可以参加多个注册,我猜是讲座的另一个词(例如“数值数学”、“计算机科学”等)。每个 Enrollment 对应一个 CourseOffering,而 CourseOffering 又具有一名讲师,即。 e.主持实际讲座(入学)的教授和时间表,我认为这是一种时间组成部分(例如“2023 年夏季”或“2021/2022 年冬季”)。该方法会更新给定讲师和给定学生的考试结果(两者都是该方法的参数)。
因此,假设我们有一个名为“John Doe”的学生,他有两个注册= {e1 = '计算机科学',e2 = '微积分'}。此外,我们有两名讲师 = {l1 = '教授。史密斯',l2 = '教授。 Walker'},两个 Schedules = {s1 = 'winter 2021/2022', s2 = 'summer 2022'},最后两个 CourseOfferings = {c1 = {l1, s1}, c2 = {l2, s2}},此外还有 e1连接到 c1,e2 连接到 c2。换句话说,John Doe 参加了 Smith 教授在“2021/2022 年冬季”开设的“计算机科学”课程,以及 Walker 教授在“2022 年夏季”开设的“微积分”课程。
让我们看一下对“updateResult('Prof. Walker', 'John Doe', 'A')”的方法调用。首先,该方法获取 currentSchedule(为了简单起见,假设其 s2)和正确的学生(可能来自持久数据存储)。接下来,它获取注册(在我们的例子中为“计算机科学”和“微积分”)并检查每个注册,如果其 CourseOffering 与讲师(作为方法的参数提供)和 currentSchedule 匹配。对于第一次注册的 e1 来说情况并非如此,因为 c1 (= e1.getOffering()) 的讲师是 Smith 教授。然而,对于第二次注册 e2,讲师和当前日程(在 c2 中)匹配。因此,在步骤 12 和 13 中(请查看我提供的序列图中的数字),该方法将 e2 分配给步骤 9 中的变量登记并跳出循环。之后我们将成绩设置为入学成绩,因此“John Doe”的微积分成绩为“A”。
简而言之:该方法首先根据学生和讲师(以及当前的时间表)确定入学情况,然后更新成绩。