-
Notifications
You must be signed in to change notification settings - Fork 303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Development
: Replace if-else chains with pattern matching
#9303
Development
: Replace if-else chains with pattern matching
#9303
Conversation
|
Nice. Is this the only place where the new style can be used? If not, can you convert other places as well? |
Good idea, I actually didn't check. I'll try to find other suitable places. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Files selected for processing (1)
- src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java (1 hunks)
Additional context used
Path-based instructions (1)
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/in/www1/artemis/service/exam/StudentExamService.java
Outdated
Show resolved
Hide resolved
There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions. |
this.student = null; | ||
this.team = null; | ||
} | ||
default -> throw new Error("Unknown participant type"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to seal the participant in order to remove the default case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I'm sick rn so I'm not too active on my computer hence the delay.
What exactly do you mean by "seal"? Do you mean the Java 17 sealed
keyword and that I should make Participant
a sealed
class so that we can remove the default
cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem at all. Yes, I mean "sealed". I think the pattern matching should detect that you have all cases. I'm not 100% sure whether the base is an interface, abstract class or normal class, but you have some possibilities with sealed here. See sample below :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, that looks really nice, thx for the suggestion.
I'll look more into sealed
. I've looked at it on Java 17 release, but haven't ever actually used it in a project since, so I just want to make sure that by adding this, I don't accidently "destroy" something else (be it compatibility, performance, etc.).
I'll push the changes tomorrow (if my research didn't reveal something bad).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem could be the package structure of Artemis here. Maybe that's something to discuss with @krusche from a programming perspective, it would be really good to use sealed here because it ensures that you'll find all places if another type of participant occurs. You are also welcome to contact me via Slack in this regard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the package structure is a problem.
I tried a few things, but we'd basically have to move de.tum.in.www1.artemis.domain.User.java
and de.tum.in.www1.artemis.domain.Team.java
into the de.tum.in.www1.artemis.domain.participation
folder, otherwise it complains about Class is not allowed to extend sealed class from another package
.
But yeah, in order to address that we'd definitely need to talk to @krusche to ensure we even can make such changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Errrr. I also just realized that since this PR had been created some time ago (but I couldn't work on it cause vacation, into retake preparation into sickness) the entire file structure changed.
Like, it's no longer de.tum.in.www1.artemis
, but now it's de.tum.cit.aet.artemis
.
So yeah... I guess I'll need to spend some time again to manually apply all the changes to the new files, cause I honestly have no idea how to automatically merge this, if it's even possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also means that the locations I said earlier, i.e.
we'd basically have to move
de.tum.in.www1.artemis.domain.User.java
andde.tum.in.www1.artemis.domain.Team.java
into thede.tum.in.www1.artemis.domain.participation
folder
should've said this:
we'd basically have to move
de.tum.cit.aet.artemis.core.domain.User.java
andde.tum.cit.aet.artemis.exercise.domain.Team.java
into thede.tum.cit.aet.artemis.exercise.domain.participation
folder
@@ -450,25 +450,14 @@ SELECT COUNT(DISTINCT s) | |||
* @return a new submission for the given type connected to the given participation | |||
*/ | |||
default Submission initializeSubmission(Participation participation, Exercise exercise, SubmissionType submissionType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here. you could think about sealing the submissions. this should remove the default case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually here we would need to seal the Exercise, not the Submission, but it wouldn't give us too much, because we would still need the null
case anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but not the default case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/assessment/web/ComplaintResource.java (2)
340-357
: Excellent refactoring using pattern matching and switch expression!The changes improve readability and adhere to the KISS principle. The early return for null
originalSubmission
simplifies the logic flow. However, consider extracting the switch expression into a separate method for better modularity and reusability.Consider extracting the switch expression into a separate method:
private Submission createSubmissionWithOnlyId(Submission originalSubmission) { return switch (originalSubmission) { case TextSubmission ignored -> new TextSubmission(); case ModelingSubmission ignored -> new ModelingSubmission(); case FileUploadSubmission ignored -> new FileUploadSubmission(); case ProgrammingSubmission ignored -> new ProgrammingSubmission(); default -> null; }; }Then, you can simplify the main method:
Submission submissionWithOnlyId = createSubmissionWithOnlyId(originalSubmission); if (submissionWithOnlyId == null) { return; }This change would improve modularity and make the code more reusable.
362-367
: Good use of switch statement for type checking and object creation!The refactoring improves readability and error handling. However, for consistency with the previous segment and to further improve readability, consider using a switch expression here as well.
Consider refactoring to use a switch expression:
Exercise exerciseWithOnlyTitle = switch (originalParticipation.getExercise()) { case TextExercise ignored -> new TextExercise(); case ModelingExercise ignored -> new ModelingExercise(); case FileUploadExercise ignored -> new FileUploadExercise(); case ProgrammingExercise ignored -> new ProgrammingExercise(); case null, default -> { log.error("Invalid exercise {} passed", originalParticipation.getExercise().getType()); yield new Exercise(); } };This change would make the code more consistent with the previous segment and potentially more readable.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
- src/main/java/de/tum/cit/aet/artemis/assessment/domain/Complaint.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/assessment/web/ComplaintResource.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/assessment/domain/Complaint.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/assessment/web/ComplaintResource.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/assessment/web/ComplaintResource.java (2)
Learnt from: julian-christl PR: ls1intum/Artemis#7829 File: src/main/java/de/tum/in/www1/artemis/web/rest/ComplaintResponseResource.java:0-0 Timestamp: 2024-10-08T15:35:42.972Z Learning: The user has fixed the issue regarding the redundant wildcard import in `ComplaintResponseResource.java` by removing it in commit 7e392e0.
Learnt from: julian-christl PR: ls1intum/Artemis#7829 File: src/main/java/de/tum/in/www1/artemis/web/rest/ComplaintResponseResource.java:0-0 Timestamp: 2024-01-08T18:32:55.982Z Learning: The user has fixed the issue regarding the redundant wildcard import in `ComplaintResponseResource.java` by removing it in commit 7e392e0.
🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/assessment/web/ComplaintResource.java (1)
369-369
: Good addition of whitespace for improved readability.The empty line after the switch statement helps to separate logical blocks of code, enhancing overall readability and structure.
this.student = null; | ||
this.team = null; | ||
} | ||
default -> throw new Error("Unknown participant type"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throw an appropriate exception instead of 'Error' in the default case
Throwing an Error
is generally reserved for serious system failures and is not recommended for handling unexpected input or states. Instead, use a more appropriate unchecked exception like IllegalArgumentException
to indicate that the participant type is not recognized.
Apply this diff to fix the issue:
default -> throw new Error("Unknown participant type");
+ default -> throw new IllegalArgumentException("Unknown participant type");
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
default -> throw new Error("Unknown participant type"); | |
default -> throw new IllegalArgumentException("Unknown participant type"); |
throw new Error("Unknown participant type"); | ||
switch (participant) { | ||
case User user -> this.student = user; | ||
case Team team1 -> this.team = team1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use consistent variable naming in switch-case patterns
In the switch statement, the variable team1
is used in case Team team1 -> this.team = team1;
. For consistency and clarity, consider renaming team1
to team
, aligning it with the field name this.team
and improving readability.
Apply this diff to rename the variable:
switch (participant) {
case User user -> this.student = user;
- case Team team1 -> this.team = team1;
+ case Team team -> this.team = team;
case null -> {
this.student = null;
this.team = null;
}
default -> throw new Error("Unknown participant type");
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
case Team team1 -> this.team = team1; | |
case Team team -> this.team = team; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code lgtm. I assume I integrating the "sealed" classes didn't work because of our package structure?
There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions. |
Checklist
General
Server
Motivation and Context
If-else chains aren't pleasant to read, nor are they particularly efficient, and since Java 21 we have pattern matching, so let's use that.
Switch-statements may be optimized to run in
O(1)
, whereas if-else chains will typically lead toO(n)
runtime complexity, however this isn't guaranteed as it depends on the respective Java implementation.Either way, the benefit in terms of performance will probably be negligible, however the readability improvement alone justifies this change.
Description
Changed if-else-instanceof-chains to utilize pattern matching (introduced by Java 21) instead. No logic was changed.
Steps for Testing
Since this doesn't affect any logic, there are no observable changes.
Only ways to test are code review and running the server tests, which do all pass for me locally, except for 8 unrelated tests.
Review Progress
Code Review
Summary by CodeRabbit
New Features
Bug Fixes
Refactor