CSC/ECE 517 Spring 2022 - E2216: Refactor late policies controller

From Expertiza_Wiki
Revision as of 23:33, 9 April 2022 by Admin (talk | contribs) (→‎Test Plan)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Background

The later policies controller file manages the SCRUM from late policies. Chiefly, the file checks if new or updated late policies are valid policies, in that they do not have the same name as an already existing policy, does not have a late penatly per unit time that surpasses the max late penalty, and does not have a late penalty surpassing 100.

Team Members

  • Wyatt Plaga (wgplaga@ncsu.edu)
  • Sujith Tumma (stumma2@ncsu.edu)
  • Shawn Salekin (ssaleki@ncsu.edu)

Description about project

This wiki describes the work done to refactor late_policies_controller.rb. The main focus of the work went into removing code duplication, as well as simplifying the code for readability, for the create and update methods. This also includes adding code comments for understandibility.

Files Involved

File Modified:

  • app/controllers/late_policies_controller.rb
  • app/views/late_policies/new.html.erb
  • app/views/late_policies/_form.html.erb
  • spec/controllers/late_policies_controller_spec.rb
  • db/schema.rb

File Added:

  • db/migrate/20220321162332_add_private_to_late_policies.rb

Test Plan

This is a refactoring project, so performed manual tests to ensure the functionalities did not change. Here is how you can test it manually.

  • Navigate over to the late policies index page: http://152.7.98.82:9090/late_policies
  • Create a new policy. Try different input combinations, some valid or invalid. Keep an eye for the error messages
  • Try updating the policy
  • Try giving the same name to two different policies and see if you get proper error message
  • Delete policies.
  • Additionally, if you are able to log in as a different instructor, you should not see someone else's privately created

policies.

If all of these changes work as intended, we should be good.

Code Issues

1. All the late policies will show up on the index page, not just policies created by the current instructor. Need to create public & private late policies. Try to leverage code for private and public courses, assignments, and questionnaires.

2. create and update have some duplicate code. Fix that using a partial, _form.

3. Both create and update need comments and a better identifier naming.

4. Reduce code duplication. Find a way to make the code more DRY

5. Line 64: The if condition can be simplified.

6. Improve the variable name for same_policy_name. (Boolean variables can be named in a better way)

7. Add method comments

8. Find the use of instance variables in create and update method? Do we really need it? Can it be made local variables instead?

Code Changes

1. All the late policies will show up on the index page, not just policies created by the current instructor. Need to create public & private late policies. Try to leverage code for private and public courses, assignments, and questionnaires

Current code:

(No such code exists)

Modifications:

- add a column named 'private' on to the LatePolicy model
- In the controller#index method, filter the results by private != 0 or instructor_id = current_user_id

2. create and update have some duplicate code. Fix that using a partial, _form.

Filename: app/views/late_policies/new.html.erb

Current Code:

<%= form_for @late_policy, :url => { :action => "create" } do |f| %>
  <%= error_messages_for @late_policy %>

  <p>
  <label for="late_policy_name">Late policy name:</label><label style="color: #ff0000;">*</label><br/>
    <%= f.text_field 'policy_name' %>
  </p>
  <p>
  <label for="late_policy_penalty_points_per_unit">Penalty points per unit:</label><label style="color: #ff0000;">*</label><br/>
    <%= f.text_field 'penalty_per_unit' %>
  </p>
  <p>
  <label for="penalty_unit">Penalty unit:</label><label style="color: #ff0000;">*</label><br/>
    <!--select name=<='late_policy[:penalty_unit]'%>>
    <option value='Minute' selected>Minute</option>
    <option value='Hour' >Hour</option>
    <option value='Day' >Day</option>
    </select-->
    <% @units= %w[Minute Hour Day]%>
    <%= f.select "penalty_unit", @units %>
  </p>
  <p>
    <label for="late_policy_penalty_maximum">Maximum penalty:</label><label style="color: #ff0000;">*</label><br/>
    <%= f.text_field 'max_penalty' %>
  </p>

Modifications:

<%= form_for @penalty_policy, :url => { :action => "create" } do |f| %>
  <%= error_messages_for @penalty_policy %>
  <%= render partial: 'form', locals: { f: f } %>


3. Both create and update need comments and a better identifier naming.

Current identifiers names:

* invalid_penalty_per_unit (Problem with this is ,try to read "!invalid_penalty_per_unit". So, "valid_penalty" increases the readability. )
* policy_name_exists

Modifications:

Got rid of both identifier names and implemented functions that validate input and check the duplicity of late policy name
* valid_penalty
* duplicate_name_check

4. Reduce code duplication. Find a way to make the code more DRY

Extracted the validation done in both create and update into a seperate method. This reduced repition between the two methods. See part 5.

5. Line 64: The if condition can be simplified.

Origional Code:

invalid_penalty_per_unit = params[:late_policy][:max_penalty].to_i < params[:late_policy][:penalty_per_unit].to_i
    flash[:error] = 'The maximum penalty cannot be less than penalty per unit.' if invalid_penalty_per_unit
    same_policy_name = false
    # penalty name should be unique
    if same_policy_name != LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)
      flash[:error] = 'A policy with the same name already exists.'
      same_policy_name = true
    end
    # maximum penalty cannot be greater than equal to 100
    if params[:late_policy][:max_penalty].to_i >= 100
      flash[:error] = 'Maximum penalty cannot be greater than or equal to 100'
      invalid_max_penalty = true
    end

    if !invalid_penalty_per_unit && !same_policy_name && !invalid_max_penalty
      @late_policy = LatePolicy.new(late_policy_params)
      @late_policy.instructor_id = instructor_id
      begin
        @late_policy.save!
        flash[:notice] = 'The late policy was successfully created.'
        redirect_to action: 'index'
      rescue StandardError
        flash[:error] = 'The following error occurred while saving the late policy: '
        redirect_to action: 'new'
      end
    else
      redirect_to action: 'new'
    end

Modifications:

 def validate_input(is_update=false)
    # Validates input for create and update forms
    max_penalty = params[:late_policy][:max_penalty].to_i
    penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i

    valid_penalty, error_message = true, nil
    valid_penalty, error_message = duplicate_name_check(is_update)
    prefix = is_update ? "Cannot edit the policy. " : ""

    #This check validates the maximum penalty.
    if max_penalty < penalty_per_unit
      error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'
      valid_penalty = false
    end

    #This check validates the penalty per unit for a late policy.
    if penalty_per_unit < 0
      error_message = 'Penalty per unit cannot be negative.'
      valid_penalty = false
    end

    # This checks maximum penalty does not exceed 100.
    if max_penalty >= 100
      error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'
      valid_penalty = false
    end

    return valid_penalty, error_message
  end


6. Improve the variable name for same_policy_name. (Boolean variables can be named in a better way)

Current identifiers names:

same_policy_name

Modifications:

Got rid of this identifier by replacing it with a function named "duplicate_name_check"

7. Add method comments

No comments

Modifications:

Added comments for all the methods to increase the readability of the code.

GitHub links

Link to Expertiza repository: here

Link to the forked repository: here