CSC/ECE 517 Spring 2020 - Project E2008. Refactor summary helper.rb: Difference between revisions
Line 185: | Line 185: | ||
:Refactored the method into 2 smaller methods namely ''calculate_avg_score_by_round'' and ''calculate_round_score'' where ''calculate_avg_score_by_round'' calls ''calculate_round_score'' to calculate average round score and ''calculate_avg_score_by_round'' rounds the round_score upto 2 decimal places. | :Refactored the method into 2 smaller methods namely ''calculate_avg_score_by_round'' and ''calculate_round_score'' where ''calculate_avg_score_by_round'' calls ''calculate_round_score'' to calculate average round score and ''calculate_avg_score_by_round'' rounds the round_score upto 2 decimal places. | ||
:[[ | :'''Before:''' | ||
<pre> | |||
def calculate_avg_score_by_round(avg_scores_by_criterion, criteria) | |||
round_score = 0.0 | |||
sum_weight = 0 | |||
criteria.each do |q| | |||
# include this score in the average round score if the weight is valid & q is criterion | |||
if !q.weight.nil? and q.weight > 0 and q.type.eql?("Criterion") | |||
round_score += avg_scores_by_criterion[q.txt] * q.weight | |||
sum_weight += q.weight | |||
end | |||
end | |||
round_score /= sum_weight if sum_weight > 0 and round_score > 0 | |||
round_score.round(2) | |||
end | |||
</pre> | |||
:'''After:''' | |||
<pre> | |||
def calculate_round_score(avg_scores_by_criterion, criteria) | |||
round_score = sum_weight = 0.0 | |||
criteria.each do |q| | |||
# include this score in the average round score if the weight is valid & q is criterion | |||
if !q.weight.nil? and q.weight > 0 and q.type.eql?("Criterion") | |||
round_score += avg_scores_by_criterion[q.txt] * q.weight | |||
sum_weight += q.weight | |||
end | |||
end | |||
round_score /= sum_weight if sum_weight > 0 and round_score > 0 | |||
round_score | |||
end | |||
def calculate_avg_score_by_round(avg_scores_by_criterion, criteria) | |||
round_score = calculate_round_score(avg_scores_by_criterion, criteria) | |||
round_score.round(2) | |||
end | |||
</pre> | |||
:'''Impact:''' | :'''Impact:''' |
Revision as of 13:41, 29 March 2020
About Expertiza
Expertiza is a web application developed using Ruby on Rails Framework whose creation and maintenance are taken care of by students as well as the faculty of NCSU. Its code is available on Github Expertiza on GitHub. Expertiza allows the instructor to create and edit new as well as existing assignments. This also includes creating a wide range of topics under each assignment that students can sign up for. They can also publish surveys and reviews, view statistical results, set deadlines for assignments and make announcements. It provides a platform for students to signup for topics, form teams, view and submit assignments and give peer reviews and feedback.
Problem Statement
Background: In Expertiza students can review each other’s projects and even each other as teammates. Students can view their project scores and instructors can view student's teammate review scores on the view scores page. This helper file aids in calculating these scores and rendering the results on the view scores section of an assignment. Summary helper is a helper module that consists of methods used to calculate scores for these reviews. This is for the use of instructors.
Requirement: E2008 is an Expertiza OSS project which deals basically with refactoring app/helpers/summary_helper.rb to reduce the code climate issues such as
- Assignment Branch Condition
- Cognitive Complexity
- Method/line too long
- Unused variables / access modifiers
A good method should have:
- Assignment Branch Condition size < 15
- Cognitive Complexity < 6
- No. of lines in a method < 25
Issues found
The following are issues which were found in the code:
Assignment Branch Condition
Method | ABC Size |
---|---|
summarize_reviews_by_reviewee | 44.61 |
summarize_reviews_by_criterion | 42.34 |
summarize_reviews_by_reviewees | 89.93 |
get_questions_by_assignment | 16.43 |
calculate_avg_score_by_round | 18.57 |
Cognitive Complexity
Method | Cognitive Complexity |
---|---|
summarize_reviews_by_criterion | 16 |
summarize_reviews_by_reviewees | 17 |
get_questions_by_assignment | 11 |
break_up_comments_to_sentences | 6 |
Method/line too long
Method/Line too long | Comments |
---|---|
Method: summarize_reviews_by_reviewees | Lines of Code:39 |
Method: summarize_reviews_by_criterion | Lines of Code:27 |
Line: 145 | self.avg_scores_by_round[reviewee.name][round] too long (162/160) |
Unused variables / access modifiers
Vaiable/Access Modifier | Comments |
---|---|
Variable: summary | Method: summarize_sentences |
Variable: included_question_counter | Method: summarize_reviews_by_reviewee |
Access Modifier: module_function | Class: Summary |
Solution Implemented
Refactor - summarize_reviews_by_reviewee
- This method is used to summarize reviews by a reviewer for each question.
- Changes Made:
- This method could be refactored into smaller methods namely summarize_reviews_by_reviewee and summarize_reviews_by_reviewee_assign where summarize_reviews_by_reviewee calls summarize_reviews_by_reviewee_assign to get average scores and summary for each question.
- Impact:
- Assignment Branch Condition size for summarize_reviews_by_reviewee is reduced from 44.61 to 20.64.
Refactor - summarize_reviews_by_criterion
- This method is used to summarize the review for each questions
- Changes Made:
- This method was refactored into 3 smaller methods namely summarize_reviews_by_criterion, summarize_reviews_by_criterion_questions and end_threads.
- The method summarize_reviews_by_criterion calls summarize_reviews_by_criterion_questions to get answers of each question in the rubric.
- The method summarize_reviews_by_criterion_questions starts many threads to process each question and closes it by calling the function end_threads.
- Impact:
- Assignment Branch Condition size for summarize_reviews_by_criterion is reduced from 42.34 to 17.2
- Cognitive complexity is reduced from 16 to 7
Refactor - summarize_reviews_by_reviewees
- This method is used to produce summaries for instructor and students. It sums up the feedback by criterion for each reviewer
- Changes Made:
- This method was refactored into 4 smaller methods namely summarize_reviews_by_reviewees, summarize_reviews_by_teams, summarize_by_rounds and end_threads.
- The method summarize_reviews_by_reviewees calls summarize_reviews_by_teams which inturn calls summarize_by_rounds to get answers of each reviewer by rubric.
- The method summarize_by_rounds starts many threads to create requests to summarize the comments and closes the threads by calling the function end_threads.
- Impact:
- Assignment Branch Condition size for summarize_reviews_by_reviewees is reduced from 89.93 to 16.64
- Cognitive Complexity is reduced from 17 to 7
Refactor - summarize_sentence
- This method calls web service to store each summary in a hashmap and use the question as the key.
- Changes Made:
- Removed variable summary
Refactor - break_up_comments_to_sentences
- This method adds the comment to an array to be converted as a json request.
- Changes Made:
- The method is broken down into 2 smaller methods namely break_up_comments_to_sentences and get_sentences where get_sentences is called by break_up_comments_to_sentences to get sentences in desired format.
- Impact:
- The Cognitive complexity of break_up_comments_to_sentences reduced from 6 to <5
Refactor - get_questions_by_assignment
- This method returns the rubric for given assignment
- Changes Made:
Refactor - calculate_avg_score_by_round
- This method is used to calculate average round score for each question.
- Changes Made:
- Refactored the method into 2 smaller methods namely calculate_avg_score_by_round and calculate_round_score where calculate_avg_score_by_round calls calculate_round_score to calculate average round score and calculate_avg_score_by_round rounds the round_score upto 2 decimal places.
- Before:
def calculate_avg_score_by_round(avg_scores_by_criterion, criteria) round_score = 0.0 sum_weight = 0 criteria.each do |q| # include this score in the average round score if the weight is valid & q is criterion if !q.weight.nil? and q.weight > 0 and q.type.eql?("Criterion") round_score += avg_scores_by_criterion[q.txt] * q.weight sum_weight += q.weight end end round_score /= sum_weight if sum_weight > 0 and round_score > 0 round_score.round(2) end
- After:
def calculate_round_score(avg_scores_by_criterion, criteria) round_score = sum_weight = 0.0 criteria.each do |q| # include this score in the average round score if the weight is valid & q is criterion if !q.weight.nil? and q.weight > 0 and q.type.eql?("Criterion") round_score += avg_scores_by_criterion[q.txt] * q.weight sum_weight += q.weight end end round_score /= sum_weight if sum_weight > 0 and round_score > 0 round_score end def calculate_avg_score_by_round(avg_scores_by_criterion, criteria) round_score = calculate_round_score(avg_scores_by_criterion, criteria) round_score.round(2) end
- Impact:
- Assignment Branch Condition size for calculate_avg_score_by_round is reduced from 18.57 to <15.
Future improvement
- Modularize summarize_by_rounds to even smaller modules so that Assignment Branch Condition size is reduced from 36.73 to 15.00.
- Create more test cases for the new modularized methods.