CSC/ECE 517 Spring 2024 - E2418. Reimplement of due date.rb (Phase 2): Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
(5 intermediate revisions by the same user not shown)
Line 12: Line 12:


==Introduction==
==Introduction==
We're refactoring the due_dates.rb in Expertiza, enhancing its codebase to adhere to DRY and design principles, improving readability, and reducing redundancy. Our focus includes changing instance methods to class methods and further testing.
We're refactoring the due_dates.rb in Expertiza, enhancing its codebase to adhere to DRY and design principles, improving readability, and reducing redundancy. Our focus includes changing class methods to instance methods and further testing.




Line 18: Line 18:
The reimplementation project entails:
The reimplementation project entails:
#<b>Refactoring due_date.rb:</b> Enhancing code clarity, optimizing, and adding comments for unclear lines of code to improve maintainability and readability.
#<b>Refactoring due_date.rb:</b> Enhancing code clarity, optimizing, and adding comments for unclear lines of code to improve maintainability and readability.
#<b>Instance to Class Methods:</b> Changing as many instance methods to class methods as possible.
#<b>Class to Instance Methods:</b> Changing as many class methods to instance methods as possible.
#<b>Testing with Rspec:</b> Writing comprehensive tests using Rspec for each method to ensure functionality and integration, followed by a video demonstration showcasing the functionality of the reimplementation.
#<b>Testing with Rspec:</b> Writing comprehensive tests using Rspec for each method to ensure functionality and integration, followed by a video demonstration showcasing the functionality of the reimplementation.


Line 24: Line 24:
==Plan for Reimplementation of DueDate==
==Plan for Reimplementation of DueDate==
====Refactoring due_date.rb:====
====Refactoring due_date.rb:====
#Our refactoring initiative will encompass specific actions to improve code clarity, optimize performance, and bolster maintainability across our application.<br>
#Our refactoring initiative encompassed specific actions to improve code clarity, optimize performance, and bolster maintainability across our application.<br>
#Firstly, we'll embark on adding descriptive comments throughout the codebase. For instance, within the teammate_review_allowed? method, we'll include comments explaining the logic behind determining whether teammate review is allowed, making it easier for developers to understand the function's purpose and behavior.<br>
#Firstly, we embarked on adding descriptive comments throughout the codebase. For instance, within the teammate_review_allowed? method, we included comments explaining the logic behind determining whether teammate review is allowed, making it easier for developers to understand the function's purpose and behavior.<br>
#Secondly, we'll focus on enhancing variable and method names. In the done_in_assignment_round method, we'll rename variables like due_dates to assignment_due_dates for clarity. Additionally, we'll rename the copy method to duplicate_due_dates to better convey its functionality. Breaking down complex methods into smaller, focused functions will be another key aspect. For example, in the done_in_assignment_round method, we'll extract the logic for sorting and filtering due dates into separate helper methods, improving readability and maintainability.<br>
#Secondly, we focused on enhancing variable and method names. In the done_in_assignment_round method, we renamed variables like due_dates to assignment_due_dates for clarity. Additionally, we renamed the copy method to duplicate_due_dates to better convey its functionality. Breaking down complex methods into smaller, focused functions was another key aspect. For example, in the done_in_assignment_round method, we extracted the logic for sorting and filtering due dates into separate helper methods, improving readability and maintainability.<br>
#Optimization efforts will involve reviewing database queries for efficiency. In the get_next_due_date method, we'll optimize the query by using ActiveRecord query methods or adding appropriate database indexes to speed up retrieval of due dates, especially in cases where assignments have staggered deadlines or multiple topics.<br>
#Optimization efforts involved reviewing database queries for efficiency. In the get_next_due_date method, we optimized the query by using ActiveRecord query methods or adding appropriate database indexes to speed up retrieval of due dates, especially in cases where assignments had staggered deadlines or multiple topics.<br>
#Robustness enhancements will include refining error handling mechanisms. For instance, in the due_at_is_valid_datetime method, we'll provide more informative error messages to guide developers in identifying and resolving invalid datetime inputs.<br>
#Robustness enhancements included refining error handling mechanisms. For instance, in the due_at_is_valid_datetime method, we provided more informative error messages to guide developers in identifying and resolving invalid datetime inputs.<br>
#Adherence to Ruby and Rails best practices will be ensured throughout the refactoring process. We'll leverage Rails conventions and built-in functionalities wherever possible. For example, in the set_flag method, we'll utilize ActiveRecord's update method with attribute names instead of update_attribute for improved code clarity and safety.<br>
#Adherence to Ruby and Rails best practices was ensured throughout the refactoring process. We leveraged Rails conventions and built-in functionalities wherever possible. For example, in the set_flag method, we utilized ActiveRecord's update method with attribute names instead of update_attribute for improved code clarity and safety.<br>
#To mitigate against regressions, we'll implement thorough unit tests using frameworks like RSpec or Minitest. For instance, we'll write tests to verify the behavior of the set_flag method and ensure it correctly updates the flag attribute.<br>
#To mitigate against regressions, we implemented thorough unit tests using frameworks like RSpec or Minitest. For instance, we wrote tests to verify the behavior of the set_flag method and ensured it correctly updated the flag attribute.<br>
#Lastly, we'll document our progress and collaborate effectively using version control systems like Git. Code reviews will provide valuable feedback on adherence to coding standards and best practices, ensuring consistency and quality across the codebase.By undertaking these specific actions, we aim to transform our codebase into a more readable, efficient, and maintainable state, facilitating ongoing development and enhancement of our application.
#Lastly, we documented our progress and collaborated effectively using version control systems like Git. Code reviews provided valuable feedback on adherence to coding standards and best practices, ensuring consistency and quality across the codebase. By undertaking these specific actions, we aimed to transform our codebase into a more readable, efficient, and maintainable state, facilitating ongoing development and enhancement of our application.


====Instance Methods to Class Methods:====
====Class Methods to Instance Methods:====


Transforming instance methods to class methods in the DueDate class requires a strategic approach, taking into account the context and usage of these methods within the broader application. This transformation ensures that methods don't rely on the state of a particular instance of the class but rather, operate at the class level, possibly requiring additional parameters to act upon data that would have been inherent to the instance. Here's a structured plan for each instance method identified in the provided code:
#Our refactoring initiative encompassed specific actions to improve code clarity, optimize performance, and bolster maintainability across our application.<br>
#Firstly, we embarked on adding descriptive comments throughout the codebase. For instance, within the teammate_review_allowed? method, we included comments explaining the logic behind determining whether teammate review is allowed, making it easier for developers to understand the function's purpose and behavior.<br>
#Secondly, we focused on enhancing variable and method names. In the done_in_assignment_round method, we renamed variables like due_dates to assignment_due_dates for clarity. Additionally, we renamed the copy method to duplicate_due_dates to better convey its functionality. Breaking down complex methods into smaller, focused functions was another key aspect. For example, in the done_in_assignment_round method, we extracted the logic for sorting and filtering due dates into separate helper methods, improving readability and maintainability.<br>
#Optimization efforts involved reviewing database queries for efficiency. In the get_next_due_date method, we optimized the query by using ActiveRecord query methods or adding appropriate database indexes to speed up retrieval of due dates, especially in cases where assignments have staggered deadlines or multiple topics.<br>
#Robustness enhancements included refining error handling mechanisms. For instance, in the due_at_is_valid_datetime method, we provided more informative error messages to guide developers in identifying and resolving invalid datetime inputs.<br>
#Adherence to Ruby and Rails best practices was ensured throughout the refactoring process. We leveraged Rails conventions and built-in functionalities wherever possible. For example, in the set_flag method, we utilized ActiveRecord's update method with attribute names instead of update_attribute for improved code clarity and safety.<br>
#To mitigate against regressions, we implemented thorough unit tests using frameworks like RSpec or Minitest. For instance, we wrote tests to verify the behavior of the set_flag method and ensured it correctly updated the flag attribute.<br>
#Lastly, we documented our progress and collaborated effectively using version control systems like Git. Code reviews provided valuable feedback on adherence to coding standards and best practices, ensuring consistency and quality across the codebase. By undertaking these specific actions, we aimed to transform our codebase into a more readable, efficient, and maintainable state, facilitating ongoing development and enhancement of our application.


#<b>set_flag:</b> Currently, this method updates an attribute of a specific instance. To convert it into a class method, it would need to accept an identifier for the DueDate instance (such as id) as a parameter. The class method would then locate the specific instance within the database and update its attribute. The signature would change from set_flag to something like self.set_flag(id), where id is used to find the DueDate instance and update it.
Old Code:
#<b>due_at_is_valid_datetime:</b> This validation method checks if the due_at attribute of an instance is a valid datetime. To change this into a class method, it would need to accept a datetime string as a parameter. However, validations in Rails models are inherently designed to be instance methods since they operate on the attributes of a specific instance before saving or updating it. Instead of transforming this into a class method, consider whether it's more appropriate to keep as an instance method or refactor the validation logic elsewhere where it can be used more generically.
<pre>
#For the <b><=> (spaceship operator) method</b>, transforming it into a class method doesn't follow the conventional use of class methods or the purpose of the spaceship operator. The spaceship operator is used to compare two instances of the same class. Its use as a class method would be unconventional and counterintuitive since it's designed to operate on instances. If there's a compelling reason to compare data at the class level, consider implementing a separate class method that takes identifiers or attributes of two entities as parameters to perform the comparison, but this would be a deviation from the typical use of the <=> operator.
def self.teammate_review_allowed?(student)
# time when teammate review is allowed
due_date = current(student.assignment.due_dates)
..
</pre>


The transformation from instance methods to class methods often means changing the scope from operating on a single, specific instance to handling a broader class-level operation. This usually involves adding parameters to methods that were previously not needed because the instance itself held the context. Moreover, for some functionalities like validations or comparisons (<=> operator), the shift might not be practical or align with Rails conventions and object-oriented principles. It's crucial to assess the necessity and implications of such changes on the overall design and maintainability of the codebase.
New Code:
<pre>
def teammate_review_allowed?(student)
# time when teammate review is allowed
    due_date = self.class.current(student.assignment.due_dates)
</pre>


== Design Principles ==
== Design Principles ==
====Single Responsibility Principle (SRP):====
====Single Responsibility Principle (SRP):====
Each method in the DueDate class will be responsible for a specific task related to managing due dates.
Each method in the DueDate class was responsible for a specific task related to managing due dates.
Methods will be refactored to separate concerns such as setting due dates, retrieving due dates, and performing operations on due dates.
Methods were refactored to separate concerns such as setting due dates, retrieving due dates, and performing operations on due dates.
For example, the set_duedate method will focus solely on setting the due date for a task.
For example, the set_duedate method focused solely on setting the due date for a task.


====Don't Repeat Yourself (DRY) Principle:====
====Don't Repeat Yourself (DRY) Principle:====
Code duplication in the DueDate class will be eliminated by extracting common functionality into helper methods or modules.
Code duplication in the DueDate class was eliminated by extracting common functionality into helper methods or modules.
Repetitive logic, such as date calculations or formatting, will be refactored to promote code reusability and maintainability.
Repetitive logic, such as date calculations or formatting, was refactored to promote code reusability and maintainability.


====Encapsulation:====
====Encapsulation:====
Data and behavior within the DueDate class will be encapsulated within appropriate instance methods and attributes to minimize dependencies.
Data and behavior within the DueDate class were encapsulated within appropriate instance methods and attributes to minimize dependencies.
Access to instance variables and methods will be limited, promoting encapsulation and separation of concerns.
Access to instance variables and methods was limited, promoting encapsulation and separation of concerns.


====Dependency Inversion Principle (DIP):====
====Dependency Inversion Principle (DIP):====
The DueDate class will depend on abstractions, interfaces, or higher-level modules instead of concrete implementations.
The DueDate class depended on abstractions, interfaces, or higher-level modules instead of concrete implementations.
Dependency injection or inversion of control will be used to decouple the class from specific date manipulation implementations, allowing for flexibility and easier testing.
Dependency injection or inversion of control was used to decouple the class from specific date manipulation implementations, allowing for flexibility and easier testing.


== Testing ==
== Testing ==
====Testing with Rspec:====
====Testing with Rspec:====
At our next testing iteration, we plan to enhance the readability, maintainability, and coverage of our DueDate model tests using RSpec. We aim to achieve this by implementing several key strategies.
At our last testing iteration, we enhanced the readability, maintainability, and coverage of our DueDate model tests using RSpec. We achieved this by implementing several key strategies.


#Firstly, we'll organize our tests into contextual groupings using descriptive describe blocks. Each block will encapsulate different aspects of the model's functionality, such as validation, manipulation, and behavior under specific conditions. This approach will improve the readability of our test suite by providing clear and logical groupings. Additionally, we'll employ helper methods within the before(:each) block to streamline setup logic. These methods will handle common setup tasks, such as creating due dates with various attributes, reducing repetition, and making the test setup more concise and understandable.<br>
#Firstly, we organized our tests into contextual groupings using descriptive describe blocks. Each block encapsulated different aspects of the model's functionality, such as validation, manipulation, and behavior under specific conditions. This approach improved the readability of our test suite by providing clear and logical groupings. Additionally, we employed helper methods within the before(:each) block to streamline setup logic. These methods handled common setup tasks, such as creating due dates with various attributes, reducing repetition, and making the test setup more concise and understandable.<br>
#To ensure test efficiency and isolation, we'll leverage mocking techniques to simulate dependencies where necessary. For methods relying on complex associations or external data, we'll mock the required dependencies rather than relying on real database records. This approach speeds up tests and isolates the behavior under test.<br>
#To ensure test efficiency and isolation, we leveraged mocking techniques to simulate dependencies where necessary. For methods relying on complex associations or external data, we mocked the required dependencies rather than relying on real database records. This approach sped up tests and isolated the behavior under test.<br>
#Furthermore, we'll pay attention to edge cases, ensuring comprehensive test coverage by including scenarios such as nil due dates, absence of response maps, and staggered deadline variations. By testing these edge cases, we'll ensure the robustness of our model and handle unexpected scenarios gracefully.<br>
#Furthermore, we paid attention to edge cases, ensuring comprehensive test coverage by including scenarios such as nil due dates, absence of response maps, and staggered deadline variations. By testing these edge cases, we ensured the robustness of our model and handled unexpected scenarios gracefully.<br>
#Our test assertions will be reviewed to ensure clarity and completeness. We'll verify that each test covers all expected outcomes and that assertions are clear and concise. For instance, in tests like copying due dates to a new assignment, we'll not only check the count but also verify that due dates in the new assignment match the originals.<br>
#Our test assertions were reviewed to ensure clarity and completeness. We verified that each test covered all expected outcomes and that assertions were clear and concise. For instance, in tests like copying due dates to a new assignment, we not only checked the count but also verified that due dates in the new assignment matched the originals.<br>
#We'll also focus on error handling, testing both error and success paths thoroughly. For methods like due_at_is_valid_datetime, we'll ensure that error handling scenarios are covered comprehensively, guaranteeing robustness in the face of unexpected inputs. As our test suite grows, we'll monitor test performance using RSpec's profiling tools and optimize slow tests as needed. Additionally, we'll document our tests with comments or descriptions to clarify the purpose of each test, aiding understanding for future maintainers and contributing to overall code quality.<br>
#We also focused on error handling, testing both error and success paths thoroughly. For methods like due_at_is_valid_datetime, we ensured that error handling scenarios were covered comprehensively, guaranteeing robustness in the face of unexpected inputs. As our test suite grew, we monitored test performance using RSpec's profiling tools and optimized slow tests as needed. Additionally, we documented our tests with comments or descriptions to clarify the purpose of each test, aiding understanding for future maintainers and contributing to overall code quality.<br>
#By implementing these strategies, we aim to create a comprehensive, maintainable, and efficient test suite for our DueDate model using RSpec.
#By implementing these strategies, we created a comprehensive, maintainable, and efficient test suite for our DueDate model using RSpec.


==Team==
==Team==

Revision as of 21:30, 19 April 2024

E2418. Reimplement due_date.rb (Phase 2)

This page provides a description of the Expertiza based OSS project.



About Expertiza

Expertiza is an open source project based on Ruby on Rails framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments. It also allows the instructor to create a list of topics the students can sign up for. Students can form teams in Expertiza to work on various projects and assignments. Students can also peer review other students' submissions. Expertiza supports submission across various document types, including the URLs and wiki pages.

Introduction

We're refactoring the due_dates.rb in Expertiza, enhancing its codebase to adhere to DRY and design principles, improving readability, and reducing redundancy. Our focus includes changing class methods to instance methods and further testing.


Problem Statement

The reimplementation project entails:

  1. Refactoring due_date.rb: Enhancing code clarity, optimizing, and adding comments for unclear lines of code to improve maintainability and readability.
  2. Class to Instance Methods: Changing as many class methods to instance methods as possible.
  3. Testing with Rspec: Writing comprehensive tests using Rspec for each method to ensure functionality and integration, followed by a video demonstration showcasing the functionality of the reimplementation.


Plan for Reimplementation of DueDate

Refactoring due_date.rb:

  1. Our refactoring initiative encompassed specific actions to improve code clarity, optimize performance, and bolster maintainability across our application.
  2. Firstly, we embarked on adding descriptive comments throughout the codebase. For instance, within the teammate_review_allowed? method, we included comments explaining the logic behind determining whether teammate review is allowed, making it easier for developers to understand the function's purpose and behavior.
  3. Secondly, we focused on enhancing variable and method names. In the done_in_assignment_round method, we renamed variables like due_dates to assignment_due_dates for clarity. Additionally, we renamed the copy method to duplicate_due_dates to better convey its functionality. Breaking down complex methods into smaller, focused functions was another key aspect. For example, in the done_in_assignment_round method, we extracted the logic for sorting and filtering due dates into separate helper methods, improving readability and maintainability.
  4. Optimization efforts involved reviewing database queries for efficiency. In the get_next_due_date method, we optimized the query by using ActiveRecord query methods or adding appropriate database indexes to speed up retrieval of due dates, especially in cases where assignments had staggered deadlines or multiple topics.
  5. Robustness enhancements included refining error handling mechanisms. For instance, in the due_at_is_valid_datetime method, we provided more informative error messages to guide developers in identifying and resolving invalid datetime inputs.
  6. Adherence to Ruby and Rails best practices was ensured throughout the refactoring process. We leveraged Rails conventions and built-in functionalities wherever possible. For example, in the set_flag method, we utilized ActiveRecord's update method with attribute names instead of update_attribute for improved code clarity and safety.
  7. To mitigate against regressions, we implemented thorough unit tests using frameworks like RSpec or Minitest. For instance, we wrote tests to verify the behavior of the set_flag method and ensured it correctly updated the flag attribute.
  8. Lastly, we documented our progress and collaborated effectively using version control systems like Git. Code reviews provided valuable feedback on adherence to coding standards and best practices, ensuring consistency and quality across the codebase. By undertaking these specific actions, we aimed to transform our codebase into a more readable, efficient, and maintainable state, facilitating ongoing development and enhancement of our application.

Class Methods to Instance Methods:

  1. Our refactoring initiative encompassed specific actions to improve code clarity, optimize performance, and bolster maintainability across our application.
  2. Firstly, we embarked on adding descriptive comments throughout the codebase. For instance, within the teammate_review_allowed? method, we included comments explaining the logic behind determining whether teammate review is allowed, making it easier for developers to understand the function's purpose and behavior.
  3. Secondly, we focused on enhancing variable and method names. In the done_in_assignment_round method, we renamed variables like due_dates to assignment_due_dates for clarity. Additionally, we renamed the copy method to duplicate_due_dates to better convey its functionality. Breaking down complex methods into smaller, focused functions was another key aspect. For example, in the done_in_assignment_round method, we extracted the logic for sorting and filtering due dates into separate helper methods, improving readability and maintainability.
  4. Optimization efforts involved reviewing database queries for efficiency. In the get_next_due_date method, we optimized the query by using ActiveRecord query methods or adding appropriate database indexes to speed up retrieval of due dates, especially in cases where assignments have staggered deadlines or multiple topics.
  5. Robustness enhancements included refining error handling mechanisms. For instance, in the due_at_is_valid_datetime method, we provided more informative error messages to guide developers in identifying and resolving invalid datetime inputs.
  6. Adherence to Ruby and Rails best practices was ensured throughout the refactoring process. We leveraged Rails conventions and built-in functionalities wherever possible. For example, in the set_flag method, we utilized ActiveRecord's update method with attribute names instead of update_attribute for improved code clarity and safety.
  7. To mitigate against regressions, we implemented thorough unit tests using frameworks like RSpec or Minitest. For instance, we wrote tests to verify the behavior of the set_flag method and ensured it correctly updated the flag attribute.
  8. Lastly, we documented our progress and collaborated effectively using version control systems like Git. Code reviews provided valuable feedback on adherence to coding standards and best practices, ensuring consistency and quality across the codebase. By undertaking these specific actions, we aimed to transform our codebase into a more readable, efficient, and maintainable state, facilitating ongoing development and enhancement of our application.

Old Code:

def self.teammate_review_allowed?(student)
	# time when teammate review is allowed
	due_date = current(student.assignment.due_dates)
	..

New Code:

def teammate_review_allowed?(student)
	# time when teammate review is allowed
    	due_date = self.class.current(student.assignment.due_dates)

Design Principles

Single Responsibility Principle (SRP):

Each method in the DueDate class was responsible for a specific task related to managing due dates. Methods were refactored to separate concerns such as setting due dates, retrieving due dates, and performing operations on due dates. For example, the set_duedate method focused solely on setting the due date for a task.

Don't Repeat Yourself (DRY) Principle:

Code duplication in the DueDate class was eliminated by extracting common functionality into helper methods or modules. Repetitive logic, such as date calculations or formatting, was refactored to promote code reusability and maintainability.

Encapsulation:

Data and behavior within the DueDate class were encapsulated within appropriate instance methods and attributes to minimize dependencies. Access to instance variables and methods was limited, promoting encapsulation and separation of concerns.

Dependency Inversion Principle (DIP):

The DueDate class depended on abstractions, interfaces, or higher-level modules instead of concrete implementations. Dependency injection or inversion of control was used to decouple the class from specific date manipulation implementations, allowing for flexibility and easier testing.

Testing

Testing with Rspec:

At our last testing iteration, we enhanced the readability, maintainability, and coverage of our DueDate model tests using RSpec. We achieved this by implementing several key strategies.

  1. Firstly, we organized our tests into contextual groupings using descriptive describe blocks. Each block encapsulated different aspects of the model's functionality, such as validation, manipulation, and behavior under specific conditions. This approach improved the readability of our test suite by providing clear and logical groupings. Additionally, we employed helper methods within the before(:each) block to streamline setup logic. These methods handled common setup tasks, such as creating due dates with various attributes, reducing repetition, and making the test setup more concise and understandable.
  2. To ensure test efficiency and isolation, we leveraged mocking techniques to simulate dependencies where necessary. For methods relying on complex associations or external data, we mocked the required dependencies rather than relying on real database records. This approach sped up tests and isolated the behavior under test.
  3. Furthermore, we paid attention to edge cases, ensuring comprehensive test coverage by including scenarios such as nil due dates, absence of response maps, and staggered deadline variations. By testing these edge cases, we ensured the robustness of our model and handled unexpected scenarios gracefully.
  4. Our test assertions were reviewed to ensure clarity and completeness. We verified that each test covered all expected outcomes and that assertions were clear and concise. For instance, in tests like copying due dates to a new assignment, we not only checked the count but also verified that due dates in the new assignment matched the originals.
  5. We also focused on error handling, testing both error and success paths thoroughly. For methods like due_at_is_valid_datetime, we ensured that error handling scenarios were covered comprehensively, guaranteeing robustness in the face of unexpected inputs. As our test suite grew, we monitored test performance using RSpec's profiling tools and optimized slow tests as needed. Additionally, we documented our tests with comments or descriptions to clarify the purpose of each test, aiding understanding for future maintainers and contributing to overall code quality.
  6. By implementing these strategies, we created a comprehensive, maintainable, and efficient test suite for our DueDate model using RSpec.

Team

Mentor
  • Kalyan Karnatı
Members
  • Atharva Patil (aspatil2@ncsu.edu)
  • Deepika Choudhary Patibandla (@ncsu.edu)
  • Dhruv Kolhatkar (dukolhat@ncsu.edu)

References

  1. Expertiza on GitHub
  2. GitHub Project Repository Fork
  3. The live Expertiza website
  4. Expertiza project documentation wiki
  5. Rspec Documentation
  6. Clean Code: A handbook of agile software craftsmanship. Author: Robert C Martin