Introduction and Lesson Overview

Hello once again! Today's lesson is centered around leveraging the principles of Object-Oriented Programming (OOP) — Encapsulation, Abstraction, Polymorphism, and Composition — to enhance code readability and structure. Buckle up for an exciting journey ahead!

Connection between OOP and Code Refactoring

OOP principles act as a scaffold for building readable, maintainable, and flexible code — these are the characteristics we seek while refactoring. By creating logical groupings of properties and behaviors in classes, we foster a codebase that's easier to comprehend and modify. Let's put this into perspective as we progress.

Applying Encapsulation for Better Code Organization

Encapsulation involves bundling related properties and methods within a class, thereby creating an organization that mirrors the real world.

Suppose we possess scattered student information within our program.

student_name = "Alice"
student_age = 20
student_grade = 3.9

def display_student_info
  puts "Student Name: #{student_name}"
  puts "Student Age: #{student_age}"
  puts "Student Grade: #{student_grade}"
end

def update_student_grade(new_grade)
  $student_grade = new_grade
end

Although functional, the code could cause potential confusion as the related attributes and behaviors aren't logically grouped. Let's encapsulate!

class Student
  def initialize(name, age, grade)
    @name = name
    @age = age
    @grade = grade
  end

  def display_student_info
    puts "Student Name: #{@name}"
    puts "Student Age: #{@age}"
    puts "Student Grade: #{@grade}"
  end

  def update_student_grade(new_grade)
    @grade = new_grade
  end
end

After refactoring, all student-related properties and methods are contained within the Student class, thereby enhancing readability and maintainability.

Utilizing Abstraction to Simplify Code Interaction

Next up is Abstraction. It is about exposing the relevant features and concealing the complexities.

Consider a code snippet calculating a student's grade point average (GPA) through complex operations:

def calculate_gpa(grades)
  total_points = 0
  grade_points = {'A' => 4, 'B' => 3, 'C' => 2, 'D' => 1, 'F' => 0}
  grades.each do |grade|
    total_points += grade_points[grade]
  end
  total_points / grades.size.to_f
end

We can encapsulate this within the calculate_gpa method of our Student class, thereby simplifying the interaction.

class Student
  attr_reader :gpa

  def initialize(name, grades)
    @name = name
    @grades = grades
    @gpa = calculate_gpa
  end

  def calculate_gpa
    total_points = 0
    grade_points = {'A' => 4, 'B' => 3, 'C' => 2, 'D' => 1, 'F' => 0}
    @grades.each do |grade|
      total_points += grade_points[grade]
    end
    total_points / @grades.size.to_f
  end
end

We can now access the gpa as an attribute of the student object, which is calculated behind the scenes.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal