SOLID ಬಳಸಿಕೊಂಡು ಹೊಂದಿಕೊಳ್ಳುವ ಕೋಡ್ ಬರೆಯುವುದು

SOLID ಬಳಸಿಕೊಂಡು ಹೊಂದಿಕೊಳ್ಳುವ ಕೋಡ್ ಬರೆಯುವುದು

ಅನುವಾದಕರಿಂದ: ನಿಮಗಾಗಿ ಪ್ರಕಟಿಸಲಾಗಿದೆ ಸೆವೆರಿನ್ ಪೆರೆಜ್ ಅವರ ಲೇಖನ ಪ್ರೋಗ್ರಾಮಿಂಗ್‌ನಲ್ಲಿ SOLID ತತ್ವಗಳನ್ನು ಬಳಸುವ ಬಗ್ಗೆ. ಲೇಖನದ ಮಾಹಿತಿಯು ಆರಂಭಿಕರಿಗಾಗಿ ಮತ್ತು ಅನುಭವಿ ಪ್ರೋಗ್ರಾಮರ್ಗಳಿಗೆ ಉಪಯುಕ್ತವಾಗಿರುತ್ತದೆ.

ನೀವು ಅಭಿವೃದ್ಧಿಯಲ್ಲಿದ್ದರೆ, ನೀವು SOLID ತತ್ವಗಳ ಬಗ್ಗೆ ಹೆಚ್ಚಾಗಿ ಕೇಳಿದ್ದೀರಿ. ಅವರು ಪ್ರೋಗ್ರಾಮರ್ ಅನ್ನು ಕ್ಲೀನ್, ಉತ್ತಮವಾಗಿ-ರಚನಾತ್ಮಕ ಮತ್ತು ಸುಲಭವಾಗಿ ನಿರ್ವಹಿಸಬಹುದಾದ ಕೋಡ್ ಬರೆಯಲು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತಾರೆ. ಪ್ರೋಗ್ರಾಮಿಂಗ್‌ನಲ್ಲಿ ನಿರ್ದಿಷ್ಟ ಕೆಲಸವನ್ನು ಹೇಗೆ ಸರಿಯಾಗಿ ನಿರ್ವಹಿಸಬೇಕು ಎಂಬುದಕ್ಕೆ ಹಲವಾರು ವಿಧಾನಗಳಿವೆ ಎಂದು ಗಮನಿಸಬೇಕಾದ ಸಂಗತಿ. ವಿಭಿನ್ನ ತಜ್ಞರು "ಸರಿಯಾದ ಮಾರ್ಗ" ದ ವಿಭಿನ್ನ ಆಲೋಚನೆಗಳು ಮತ್ತು ತಿಳುವಳಿಕೆಯನ್ನು ಹೊಂದಿದ್ದಾರೆ; ಇದು ಪ್ರತಿಯೊಬ್ಬ ವ್ಯಕ್ತಿಯ ಅನುಭವವನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ. ಆದಾಗ್ಯೂ, SOLID ನಲ್ಲಿ ಘೋಷಿಸಲಾದ ವಿಚಾರಗಳನ್ನು IT ಸಮುದಾಯದ ಬಹುತೇಕ ಎಲ್ಲಾ ಪ್ರತಿನಿಧಿಗಳು ಒಪ್ಪಿಕೊಂಡಿದ್ದಾರೆ. ಅವರು ಅನೇಕ ಉತ್ತಮ ಅಭಿವೃದ್ಧಿ ನಿರ್ವಹಣಾ ಅಭ್ಯಾಸಗಳ ಹೊರಹೊಮ್ಮುವಿಕೆ ಮತ್ತು ಅಭಿವೃದ್ಧಿಗೆ ಆರಂಭಿಕ ಹಂತವಾಯಿತು.

SOLID ತತ್ವಗಳು ಯಾವುವು ಮತ್ತು ಅವು ನಮಗೆ ಹೇಗೆ ಸಹಾಯ ಮಾಡುತ್ತವೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳೋಣ.

ಸ್ಕಿಲ್‌ಬಾಕ್ಸ್ ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ: ಪ್ರಾಯೋಗಿಕ ಕೋರ್ಸ್ "ಮೊಬೈಲ್ ಡೆವಲಪರ್ ಪ್ರೊ".

ನಾವು ನೆನಪಿಸುತ್ತೇವೆ: ಎಲ್ಲಾ Habr ಓದುಗರಿಗೆ - Habr ಪ್ರೊಮೊ ಕೋಡ್ ಬಳಸಿಕೊಂಡು ಯಾವುದೇ ಸ್ಕಿಲ್‌ಬಾಕ್ಸ್ ಕೋರ್ಸ್‌ಗೆ ದಾಖಲಾಗುವಾಗ 10 ರೂಬಲ್ ರಿಯಾಯಿತಿ.

SOLID ಎಂದರೇನು?

ಈ ಪದವು ಒಂದು ಸಂಕ್ಷೇಪಣವಾಗಿದೆ, ಪದದ ಪ್ರತಿಯೊಂದು ಅಕ್ಷರವು ನಿರ್ದಿಷ್ಟ ತತ್ವದ ಹೆಸರಿನ ಆರಂಭವಾಗಿದೆ:

  • Sಏಕ ಜವಾಬ್ದಾರಿ ತತ್ವ. ಮಾಡ್ಯೂಲ್ ಬದಲಾವಣೆಗೆ ಒಂದೇ ಒಂದು ಕಾರಣವನ್ನು ಹೊಂದಿರಬಹುದು.
  • ನಮ್ಮ Oಪೆನ್ / ಮುಚ್ಚಿದ ತತ್ವ (ಮುಕ್ತ/ಮುಚ್ಚಿದ ತತ್ವ). ತರಗತಿಗಳು ಮತ್ತು ಇತರ ಅಂಶಗಳು ವಿಸ್ತರಣೆಗಾಗಿ ತೆರೆದಿರಬೇಕು, ಆದರೆ ಮಾರ್ಪಾಡುಗಾಗಿ ಮುಚ್ಚಬೇಕು.
  •  ನಮ್ಮ Liskov ಪರ್ಯಾಯ ತತ್ವ (ಲಿಸ್ಕೋವ್ ಪರ್ಯಾಯ ತತ್ವ). ಬೇಸ್ ಪ್ರಕಾರವನ್ನು ಬಳಸುವ ಕಾರ್ಯಗಳು ಬೇಸ್ ಪ್ರಕಾರದ ಉಪ ಪ್ರಕಾರಗಳನ್ನು ತಿಳಿಯದೆ ಬಳಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ.
  • ನಮ್ಮ Iಇಂಟರ್ಫೇಸ್ ಪ್ರತ್ಯೇಕತೆಯ ತತ್ವ  (ಇಂಟರ್ಫೇಸ್ ಬೇರ್ಪಡಿಕೆ ತತ್ವ). ಸಾಫ್ಟ್‌ವೇರ್ ಘಟಕಗಳು ಅವರು ಬಳಸದ ವಿಧಾನಗಳನ್ನು ಅವಲಂಬಿಸಬಾರದು.
  • ನಮ್ಮ Dಅವಲಂಬನೆ ವಿಲೋಮ ತತ್ವ (ಅವಲಂಬಿತ ವಿಲೋಮ ತತ್ವ). ಉನ್ನತ ಮಟ್ಟದ ಮಾಡ್ಯೂಲ್‌ಗಳು ಕೆಳ ಹಂತದಲ್ಲಿರುವ ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ಅವಲಂಬಿಸಿರಬಾರದು.

ಏಕ ಜವಾಬ್ದಾರಿ ತತ್ವ


ಪ್ರೋಗ್ರಾಂನಲ್ಲಿನ ಪ್ರತಿಯೊಂದು ವರ್ಗ ಅಥವಾ ಮಾಡ್ಯೂಲ್ ಆ ಕಾರ್ಯಕ್ರಮದ ಕಾರ್ಯನಿರ್ವಹಣೆಯ ಒಂದು ಭಾಗಕ್ಕೆ ಮಾತ್ರ ಜವಾಬ್ದಾರರಾಗಿರಬೇಕು ಎಂದು ಸಿಂಗಲ್ ರೆಸ್ಪಾನ್ಸಿಬಿಲಿಟಿ ಪ್ರಿನ್ಸಿಪಲ್ (SRP) ಹೇಳುತ್ತದೆ. ಹೆಚ್ಚುವರಿಯಾಗಿ, ಈ ಜವಾಬ್ದಾರಿಯ ಅಂಶಗಳನ್ನು ಸಂಬಂಧವಿಲ್ಲದ ವರ್ಗಗಳಲ್ಲಿ ಹರಡುವ ಬದಲು ಅವರ ಸ್ವಂತ ವರ್ಗಕ್ಕೆ ನಿಯೋಜಿಸಬೇಕು. SRP ಯ ಡೆವಲಪರ್ ಮತ್ತು ಮುಖ್ಯ ಸುವಾರ್ತಾಬೋಧಕ, ರಾಬರ್ಟ್ S. ಮಾರ್ಟಿನ್, ಜವಾಬ್ದಾರಿಯನ್ನು ಬದಲಾವಣೆಗೆ ಕಾರಣವೆಂದು ವಿವರಿಸುತ್ತಾರೆ. ಅವರು ಮೂಲತಃ ಈ ಪದವನ್ನು ಅವರ "ಆಬ್ಜೆಕ್ಟ್-ಓರಿಯೆಂಟೆಡ್ ವಿನ್ಯಾಸದ ತತ್ವಗಳು" ಕೃತಿಯ ಅಂಶಗಳಲ್ಲಿ ಒಂದಾಗಿ ಪ್ರಸ್ತಾಪಿಸಿದರು. ಈ ಪರಿಕಲ್ಪನೆಯು ಟಾಮ್ ಡಿಮಾರ್ಕೊರಿಂದ ಹಿಂದೆ ವ್ಯಾಖ್ಯಾನಿಸಲಾದ ಹೆಚ್ಚಿನ ಸಂಪರ್ಕ ಮಾದರಿಯನ್ನು ಸಂಯೋಜಿಸುತ್ತದೆ.

ಈ ಪರಿಕಲ್ಪನೆಯು ಡೇವಿಡ್ ಪರ್ನಾಸ್ ರೂಪಿಸಿದ ಹಲವಾರು ಪರಿಕಲ್ಪನೆಗಳನ್ನು ಸಹ ಒಳಗೊಂಡಿದೆ. ಎರಡು ಮುಖ್ಯವಾದವುಗಳು ಎನ್ಕ್ಯಾಪ್ಸುಲೇಶನ್ ಮತ್ತು ಮಾಹಿತಿಯನ್ನು ಮರೆಮಾಡುವುದು. ಒಂದು ವ್ಯವಸ್ಥೆಯನ್ನು ಪ್ರತ್ಯೇಕ ಮಾಡ್ಯೂಲ್‌ಗಳಾಗಿ ವಿಭಜಿಸುವುದು ಬ್ಲಾಕ್ ರೇಖಾಚಿತ್ರಗಳು ಅಥವಾ ಎಕ್ಸಿಕ್ಯೂಶನ್ ಫ್ಲೋಗಳ ವಿಶ್ಲೇಷಣೆಯನ್ನು ಆಧರಿಸಿರಬಾರದು ಎಂದು ಪರ್ನಾಸ್ ವಾದಿಸಿದರು. ಯಾವುದೇ ಮಾಡ್ಯೂಲ್‌ಗಳು ಗ್ರಾಹಕರಿಗೆ ಕನಿಷ್ಠ ಮಾಹಿತಿಯನ್ನು ಒದಗಿಸುವ ನಿರ್ದಿಷ್ಟ ಪರಿಹಾರವನ್ನು ಹೊಂದಿರಬೇಕು.

ಮೂಲಕ, ಮಾರ್ಟಿನ್ ಕಂಪನಿಯ ಹಿರಿಯ ವ್ಯವಸ್ಥಾಪಕರೊಂದಿಗೆ (COO, CTO, CFO) ಆಸಕ್ತಿದಾಯಕ ಉದಾಹರಣೆಯನ್ನು ನೀಡಿದರು, ಪ್ರತಿಯೊಬ್ಬರೂ ವಿಭಿನ್ನ ಉದ್ದೇಶಗಳಿಗಾಗಿ ನಿರ್ದಿಷ್ಟ ವ್ಯಾಪಾರ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ಬಳಸುತ್ತಾರೆ. ಪರಿಣಾಮವಾಗಿ, ಅವರಲ್ಲಿ ಯಾರಾದರೂ ಇತರ ವ್ಯವಸ್ಥಾಪಕರ ಹಿತಾಸಕ್ತಿಗಳಿಗೆ ಧಕ್ಕೆಯಾಗದಂತೆ ಸಾಫ್ಟ್‌ವೇರ್‌ನಲ್ಲಿ ಬದಲಾವಣೆಗಳನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದು.

ದೈವಿಕ ವಸ್ತು

ಯಾವಾಗಲೂ ಹಾಗೆ, SRP ಕಲಿಯಲು ಉತ್ತಮ ಮಾರ್ಗವೆಂದರೆ ಅದನ್ನು ಕ್ರಿಯೆಯಲ್ಲಿ ನೋಡುವುದು. ಏಕ ಜವಾಬ್ದಾರಿ ತತ್ವವನ್ನು ಅನುಸರಿಸದ ಪ್ರೋಗ್ರಾಂನ ವಿಭಾಗವನ್ನು ನೋಡೋಣ. ಇದು ರೂಬಿ ಕೋಡ್ ಆಗಿದ್ದು ಅದು ಬಾಹ್ಯಾಕಾಶ ನಿಲ್ದಾಣದ ನಡವಳಿಕೆ ಮತ್ತು ಗುಣಲಕ್ಷಣಗಳನ್ನು ವಿವರಿಸುತ್ತದೆ.

ಉದಾಹರಣೆಯನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಕೆಳಗಿನದನ್ನು ನಿರ್ಧರಿಸಲು ಪ್ರಯತ್ನಿಸಿ:
ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗದಲ್ಲಿ ಘೋಷಿಸಲಾದ ಆ ವಸ್ತುಗಳ ಜವಾಬ್ದಾರಿಗಳು.
ಬಾಹ್ಯಾಕಾಶ ನಿಲ್ದಾಣದ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಆಸಕ್ತಿ ಹೊಂದಿರಬಹುದು.

class SpaceStation
  def initialize
    @supplies = {}
    @fuel = 0
  end
 
  def run_sensors
    puts "----- Sensor Action -----"
    puts "Running sensors!"
  end
 
  def load_supplies(type, quantity)
    puts "----- Supply Action -----"
    puts "Loading #{quantity} units of #{type} in the supply hold."
    
    if @supplies[type]
      @supplies[type] += quantity
    else
      @supplies[type] = quantity
    end
  end
 
  def use_supplies(type, quantity)
    puts "----- Supply Action -----"
    if @supplies[type] != nil && @supplies[type] > quantity
      puts "Using #{quantity} of #{type} from the supply hold."
      @supplies[type] -= quantity
    else
      puts "Supply Error: Insufficient #{type} in the supply hold."
    end
  end
 
  def report_supplies
    puts "----- Supply Report -----"
    if @supplies.keys.length > 0
      @supplies.each do |type, quantity|
        puts "#{type} avalilable: #{quantity} units"
      end
    else
      puts "Supply hold is empty."
    end
  end
 
  def load_fuel(quantity)
    puts "----- Fuel Action -----"
    puts "Loading #{quantity} units of fuel in the tank."
    @fuel += quantity
  end
 
  def report_fuel
    puts "----- Fuel Report -----"
    puts "#{@fuel} units of fuel available."
  end
 
  def activate_thrusters
    puts "----- Thruster Action -----"
    if @fuel >= 10
      puts "Thrusting action successful."
      @fuel -= 10
    else
      puts "Thruster Error: Insufficient fuel available."
    end
  end
end

ವಾಸ್ತವವಾಗಿ, ನಮ್ಮ ಬಾಹ್ಯಾಕಾಶ ನಿಲ್ದಾಣವು ನಿಷ್ಕ್ರಿಯವಾಗಿದೆ (ನನಗೆ ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ನಾಸಾದಿಂದ ಕರೆ ಬರಲಿದೆ ಎಂದು ನಾನು ಭಾವಿಸುವುದಿಲ್ಲ), ಆದರೆ ಇಲ್ಲಿ ವಿಶ್ಲೇಷಿಸಲು ಏನಾದರೂ ಇದೆ.

ಹೀಗಾಗಿ, ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗವು ಹಲವಾರು ವಿಭಿನ್ನ ಜವಾಬ್ದಾರಿಗಳನ್ನು ಹೊಂದಿದೆ (ಅಥವಾ ಕಾರ್ಯಗಳು). ಇವೆಲ್ಲವನ್ನೂ ವಿಧಗಳಾಗಿ ವಿಂಗಡಿಸಬಹುದು:

  • ಸಂವೇದಕಗಳು;
  • ಸರಬರಾಜು (ಉಪಭೋಗ್ಯ);
  • ಇಂಧನ;
  • ವೇಗವರ್ಧಕಗಳು.

ನಿಲ್ದಾಣದ ಯಾವುದೇ ಉದ್ಯೋಗಿಗಳಿಗೆ ವರ್ಗವನ್ನು ನಿಯೋಜಿಸದಿದ್ದರೂ, ಯಾರು ಏನು ಹೊಣೆಗಾರರಾಗಿದ್ದಾರೆ ಎಂಬುದನ್ನು ನಾವು ಸುಲಭವಾಗಿ ಊಹಿಸಬಹುದು. ಹೆಚ್ಚಾಗಿ, ವಿಜ್ಞಾನಿಗಳು ಸಂವೇದಕಗಳನ್ನು ನಿಯಂತ್ರಿಸುತ್ತಾರೆ, ಲಾಜಿಸ್ಟಿಷಿಯನ್ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಪೂರೈಸುವ ಜವಾಬ್ದಾರಿಯನ್ನು ಹೊಂದಿರುತ್ತಾರೆ, ಇಂಜಿನಿಯರ್ ಇಂಧನ ಸರಬರಾಜಿಗೆ ಜವಾಬ್ದಾರರಾಗಿರುತ್ತಾರೆ ಮತ್ತು ಪೈಲಟ್ ಬೂಸ್ಟರ್ಗಳನ್ನು ನಿಯಂತ್ರಿಸುತ್ತಾರೆ.

ಈ ಪ್ರೋಗ್ರಾಂ SRP ಕಂಪ್ಲೈಂಟ್ ಅಲ್ಲ ಎಂದು ನಾವು ಹೇಳಬಹುದೇ? ಖಂಡಿತವಾಗಿಯೂ. ಆದರೆ ಸ್ಪೇಸ್ ಸ್ಟೇಷನ್ ವರ್ಗವು ಎಲ್ಲವನ್ನೂ ತಿಳಿದಿರುವ ಮತ್ತು ಎಲ್ಲವನ್ನೂ ಮಾಡುವ ವಿಶಿಷ್ಟವಾದ "ದೇವರ ವಸ್ತು" ಆಗಿದೆ. ವಸ್ತು-ಆಧಾರಿತ ಪ್ರೋಗ್ರಾಮಿಂಗ್‌ನಲ್ಲಿ ಇದು ಪ್ರಮುಖ ವಿರೋಧಿ ಮಾದರಿಯಾಗಿದೆ. ಹರಿಕಾರರಿಗೆ, ಅಂತಹ ವಸ್ತುಗಳನ್ನು ನಿರ್ವಹಿಸಲು ತುಂಬಾ ಕಷ್ಟ. ಇಲ್ಲಿಯವರೆಗೆ ಪ್ರೋಗ್ರಾಂ ತುಂಬಾ ಸರಳವಾಗಿದೆ, ಹೌದು, ಆದರೆ ನಾವು ಹೊಸ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸೇರಿಸಿದರೆ ಏನಾಗುತ್ತದೆ ಎಂದು ಊಹಿಸಿ. ಬಹುಶಃ ನಮ್ಮ ಬಾಹ್ಯಾಕಾಶ ನಿಲ್ದಾಣಕ್ಕೆ ವೈದ್ಯಕೀಯ ಕೇಂದ್ರ ಅಥವಾ ಸಭೆಯ ಕೊಠಡಿ ಬೇಕಾಗಬಹುದು. ಮತ್ತು ಹೆಚ್ಚಿನ ಕಾರ್ಯಗಳು ಇವೆ, ಹೆಚ್ಚು ಸ್ಪೇಸ್ ಸ್ಟೇಷನ್ ಬೆಳೆಯುತ್ತದೆ. ಒಳ್ಳೆಯದು, ಈ ಸೌಲಭ್ಯವು ಇತರರಿಗೆ ಸಂಪರ್ಕಗೊಳ್ಳುವುದರಿಂದ, ಸಂಪೂರ್ಣ ಸಂಕೀರ್ಣಕ್ಕೆ ಸೇವೆ ಸಲ್ಲಿಸುವುದು ಇನ್ನಷ್ಟು ಕಷ್ಟಕರವಾಗುತ್ತದೆ. ಪರಿಣಾಮವಾಗಿ, ನಾವು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಅಡ್ಡಿಪಡಿಸಬಹುದು, ಉದಾಹರಣೆಗೆ, ವೇಗವರ್ಧಕಗಳು. ಸಂವೇದಕಗಳಿಗೆ ಬದಲಾವಣೆಗಳನ್ನು ಸಂಶೋಧಕರು ವಿನಂತಿಸಿದರೆ, ಇದು ನಿಲ್ದಾಣದ ಸಂವಹನ ವ್ಯವಸ್ಥೆಗಳ ಮೇಲೆ ಚೆನ್ನಾಗಿ ಪರಿಣಾಮ ಬೀರುತ್ತದೆ.

SRP ತತ್ವವನ್ನು ಉಲ್ಲಂಘಿಸುವುದು ಅಲ್ಪಾವಧಿಯ ಯುದ್ಧತಂತ್ರದ ವಿಜಯವನ್ನು ನೀಡಬಹುದು, ಆದರೆ ಕೊನೆಯಲ್ಲಿ ನಾವು "ಯುದ್ಧವನ್ನು ಕಳೆದುಕೊಳ್ಳುತ್ತೇವೆ", ಮತ್ತು ಭವಿಷ್ಯದಲ್ಲಿ ಅಂತಹ ದೈತ್ಯಾಕಾರದ ನಿರ್ವಹಿಸಲು ಇದು ತುಂಬಾ ಕಷ್ಟಕರವಾಗುತ್ತದೆ. ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಕೋಡ್ನ ಪ್ರತ್ಯೇಕ ವಿಭಾಗಗಳಾಗಿ ವಿಭಜಿಸುವುದು ಉತ್ತಮವಾಗಿದೆ, ಪ್ರತಿಯೊಂದೂ ನಿರ್ದಿಷ್ಟ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ನಿರ್ವಹಿಸಲು ಕಾರಣವಾಗಿದೆ. ಇದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಿ, ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗವನ್ನು ಬದಲಾಯಿಸೋಣ.

ಜವಾಬ್ದಾರಿಯನ್ನು ಹಂಚೋಣ

ಮೇಲೆ ನಾವು ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗದಿಂದ ನಿಯಂತ್ರಿಸಲ್ಪಡುವ ನಾಲ್ಕು ರೀತಿಯ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಿದ್ದೇವೆ. ರಿಫ್ಯಾಕ್ಟರಿಂಗ್ ಮಾಡುವಾಗ ನಾವು ಅವುಗಳನ್ನು ನೆನಪಿನಲ್ಲಿಟ್ಟುಕೊಳ್ಳುತ್ತೇವೆ. ನವೀಕರಿಸಿದ ಕೋಡ್ SRP ಗೆ ಉತ್ತಮವಾಗಿ ಹೊಂದಿಕೆಯಾಗುತ್ತದೆ.

class SpaceStation
  attr_reader :sensors, :supply_hold, :fuel_tank, :thrusters
 
  def initialize
    @supply_hold = SupplyHold.new
    @sensors = Sensors.new
    @fuel_tank = FuelTank.new
    @thrusters = Thrusters.new(@fuel_tank)
  end
end
 
class Sensors
  def run_sensors
    puts "----- Sensor Action -----"
    puts "Running sensors!"
  end
end
 
class SupplyHold
  attr_accessor :supplies
 
  def initialize
    @supplies = {}
  end
 
  def load_supplies(type, quantity)
    puts "----- Supply Action -----"
    puts "Loading #{quantity} units of #{type} in the supply hold."
    
    if @supplies[type]
      @supplies[type] += quantity
    else
      @supplies[type] = quantity
    end
  end
 
  def use_supplies(type, quantity)
    puts "----- Supply Action -----"
    if @supplies[type] != nil && @supplies[type] > quantity
      puts "Using #{quantity} of #{type} from the supply hold."
      @supplies[type] -= quantity
    else
      puts "Supply Error: Insufficient #{type} in the supply hold."
    end
  end
 
  def report_supplies
    puts "----- Supply Report -----"
    if @supplies.keys.length > 0
      @supplies.each do |type, quantity|
        puts "#{type} avalilable: #{quantity} units"
      end
    else
      puts "Supply hold is empty."
    end
  end
end
 
class FuelTank
  attr_accessor :fuel
 
  def initialize
    @fuel = 0
  end
 
  def get_fuel_levels
    @fuel
  end
 
  def load_fuel(quantity)
    puts "----- Fuel Action -----"
    puts "Loading #{quantity} units of fuel in the tank."
    @fuel += quantity
  end
 
  def use_fuel(quantity)
    puts "----- Fuel Action -----"
    puts "Using #{quantity} units of fuel from the tank."
    @fuel -= quantity
  end
 
  def report_fuel
    puts "----- Fuel Report -----"
    puts "#{@fuel} units of fuel available."
  end
end
 
class Thrusters
  def initialize(fuel_tank)
    @linked_fuel_tank = fuel_tank
  end
 
  def activate_thrusters
    puts "----- Thruster Action -----"
    if @linked_fuel_tank.get_fuel_levels >= 10
      puts "Thrusting action successful."
      @linked_fuel_tank.use_fuel(10)
    else
      puts "Thruster Error: Insufficient fuel available."
    end
  end
end

ಬಹಳಷ್ಟು ಬದಲಾವಣೆಗಳಿವೆ, ಪ್ರೋಗ್ರಾಂ ಖಂಡಿತವಾಗಿಯೂ ಈಗ ಉತ್ತಮವಾಗಿ ಕಾಣುತ್ತದೆ. ಈಗ ನಮ್ಮ ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗವು ಸಂವೇದಕಗಳ ಸೆಟ್, ಉಪಭೋಗ್ಯ ಪೂರೈಕೆ ವ್ಯವಸ್ಥೆ, ಇಂಧನ ಟ್ಯಾಂಕ್ ಮತ್ತು ಬೂಸ್ಟರ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ಅವಲಂಬಿತ ಭಾಗಗಳಿಗೆ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಪ್ರಾರಂಭಿಸುವ ಧಾರಕವಾಗಿದೆ.

ಯಾವುದೇ ಅಸ್ಥಿರಗಳಿಗೆ ಈಗ ಅನುಗುಣವಾದ ವರ್ಗವಿದೆ: ಸಂವೇದಕಗಳು; ಸಪ್ಲೈಹೋಲ್ಡ್; ಇಂಧನ ಟ್ಯಾಂಕ್; ಥ್ರಸ್ಟರ್ಸ್.

ಕೋಡ್‌ನ ಈ ಆವೃತ್ತಿಯಲ್ಲಿ ಹಲವಾರು ಪ್ರಮುಖ ಬದಲಾವಣೆಗಳಿವೆ. ಅಂಶವೆಂದರೆ ವೈಯಕ್ತಿಕ ಕಾರ್ಯಗಳು ತಮ್ಮದೇ ಆದ ವರ್ಗಗಳಲ್ಲಿ ಸುತ್ತುವರಿಯಲ್ಪಟ್ಟಿಲ್ಲ, ಅವುಗಳನ್ನು ಊಹಿಸಬಹುದಾದ ಮತ್ತು ಸ್ಥಿರವಾದ ರೀತಿಯಲ್ಲಿ ಆಯೋಜಿಸಲಾಗಿದೆ. ಸುಸಂಬದ್ಧತೆಯ ತತ್ವವನ್ನು ಅನುಸರಿಸಲು ನಾವು ಒಂದೇ ರೀತಿಯ ಕಾರ್ಯವನ್ನು ಹೊಂದಿರುವ ಅಂಶಗಳನ್ನು ಗುಂಪು ಮಾಡುತ್ತೇವೆ. ಈಗ, ನಾವು ಸಿಸ್ಟಮ್ ಕಾರ್ಯನಿರ್ವಹಿಸುವ ವಿಧಾನವನ್ನು ಬದಲಾಯಿಸಬೇಕಾದರೆ, ಹ್ಯಾಶ್ ರಚನೆಯಿಂದ ರಚನೆಗೆ ಚಲಿಸುವಾಗ, ಸಪ್ಲೈಹೋಲ್ಡ್ ವರ್ಗವನ್ನು ಬಳಸಿ; ನಾವು ಇತರ ಮಾಡ್ಯೂಲ್‌ಗಳನ್ನು ಸ್ಪರ್ಶಿಸಬೇಕಾಗಿಲ್ಲ. ಈ ರೀತಿಯಾಗಿ, ಲಾಜಿಸ್ಟಿಕ್ಸ್ ಅಧಿಕಾರಿ ತನ್ನ ವಿಭಾಗದಲ್ಲಿ ಏನನ್ನಾದರೂ ಬದಲಾಯಿಸಿದರೆ, ಉಳಿದ ನಿಲ್ದಾಣವು ಹಾಗೇ ಉಳಿಯುತ್ತದೆ. ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗವು ಬದಲಾವಣೆಗಳ ಬಗ್ಗೆ ತಿಳಿದಿರುವುದಿಲ್ಲ.

ಬಾಹ್ಯಾಕಾಶ ನಿಲ್ದಾಣದಲ್ಲಿ ಕೆಲಸ ಮಾಡುವ ನಮ್ಮ ಅಧಿಕಾರಿಗಳು ಬಹುಶಃ ಬದಲಾವಣೆಗಳ ಬಗ್ಗೆ ಸಂತೋಷಪಡುತ್ತಾರೆ ಏಕೆಂದರೆ ಅವರು ತಮಗೆ ಬೇಕಾದುದನ್ನು ವಿನಂತಿಸಬಹುದು. ಸಪ್ಲೈಹೋಲ್ಡ್ ಮತ್ತು ಫ್ಯೂಲ್‌ಟ್ಯಾಂಕ್ ತರಗತಿಗಳಲ್ಲಿ ಒಳಗೊಂಡಿರುವ ವರದಿ_ಸರಬರಾಜು ಮತ್ತು ವರದಿ_ಇಂಧನದಂತಹ ವಿಧಾನಗಳನ್ನು ಕೋಡ್ ಹೊಂದಿದೆ ಎಂಬುದನ್ನು ಗಮನಿಸಿ. ಭೂಮಿಯು ವರದಿ ಮಾಡುವ ವಿಧಾನವನ್ನು ಬದಲಾಯಿಸಲು ಕೇಳಿದರೆ ಏನಾಗುತ್ತದೆ? ಸಪ್ಲೈಹೋಲ್ಡ್ ಮತ್ತು ಫ್ಯೂಲ್‌ಟ್ಯಾಂಕ್ ಎರಡೂ ವರ್ಗಗಳನ್ನು ಬದಲಾಯಿಸಬೇಕಾಗುತ್ತದೆ. ಇಂಧನ ಮತ್ತು ಉಪಭೋಗ್ಯ ವಸ್ತುಗಳನ್ನು ವಿತರಿಸುವ ವಿಧಾನವನ್ನು ನೀವು ಬದಲಾಯಿಸಬೇಕಾದರೆ ಏನು ಮಾಡಬೇಕು? ನೀವು ಬಹುಶಃ ಅದೇ ತರಗತಿಗಳನ್ನು ಮತ್ತೆ ಬದಲಾಯಿಸಬೇಕಾಗುತ್ತದೆ. ಮತ್ತು ಇದು ಈಗಾಗಲೇ SRP ತತ್ವದ ಉಲ್ಲಂಘನೆಯಾಗಿದೆ. ಇದನ್ನು ಸರಿಪಡಿಸೋಣ.

class SpaceStation
  attr_reader :sensors, :supply_hold, :supply_reporter,
              :fuel_tank, :fuel_reporter, :thrusters
 
  def initialize
    @sensors = Sensors.new
    @supply_hold = SupplyHold.new
    @supply_reporter = SupplyReporter.new(@supply_hold)
    @fuel_tank = FuelTank.new
    @fuel_reporter = FuelReporter.new(@fuel_tank)
    @thrusters = Thrusters.new(@fuel_tank)
  end
end
 
class Sensors
  def run_sensors
    puts "----- Sensor Action -----"
    puts "Running sensors!"
  end
end
 
class SupplyHold
  attr_accessor :supplies
  attr_reader :reporter
 
  def initialize
    @supplies = {}
  end
 
  def get_supplies
    @supplies
  end
 
  def load_supplies(type, quantity)
    puts "----- Supply Action -----"
    puts "Loading #{quantity} units of #{type} in the supply hold."
    
    if @supplies[type]
      @supplies[type] += quantity
    else
      @supplies[type] = quantity
    end
  end
 
  def use_supplies(type, quantity)
    puts "----- Supply Action -----"
    if @supplies[type] != nil && @supplies[type] > quantity
      puts "Using #{quantity} of #{type} from the supply hold."
      @supplies[type] -= quantity
    else
      puts "Supply Error: Insufficient #{type} in the supply hold."
    end
  end
end
 
class FuelTank
  attr_accessor :fuel
  attr_reader :reporter
 
  def initialize
    @fuel = 0
  end
 
  def get_fuel_levels
    @fuel
  end
 
  def load_fuel(quantity)
    puts "----- Fuel Action -----"
    puts "Loading #{quantity} units of fuel in the tank."
    @fuel += quantity
  end
 
  def use_fuel(quantity)
    puts "----- Fuel Action -----"
    puts "Using #{quantity} units of fuel from the tank."
    @fuel -= quantity
  end
end
 
class Thrusters
  FUEL_PER_THRUST = 10
 
  def initialize(fuel_tank)
    @linked_fuel_tank = fuel_tank
  end
 
  def activate_thrusters
    puts "----- Thruster Action -----"
    
    if @linked_fuel_tank.get_fuel_levels >= FUEL_PER_THRUST
      puts "Thrusting action successful."
      @linked_fuel_tank.use_fuel(FUEL_PER_THRUST)
    else
      puts "Thruster Error: Insufficient fuel available."
    end
  end
end
 
class Reporter
  def initialize(item, type)
    @linked_item = item
    @type = type
  end
 
  def report
    puts "----- #{@type.capitalize} Report -----"
  end
end
 
class FuelReporter < Reporter
  def initialize(item)
    super(item, "fuel")
  end
 
  def report
    super
    puts "#{@linked_item.get_fuel_levels} units of fuel available."
  end
end
 
class SupplyReporter < Reporter
  def initialize(item)
    super(item, "supply")
  end
 
  def report
    super
    if @linked_item.get_supplies.keys.length > 0
      @linked_item.get_supplies.each do |type, quantity|
        puts "#{type} avalilable: #{quantity} units"
      end
    else
      puts "Supply hold is empty."
    end
  end
end
 
iss = SpaceStation.new
 
iss.sensors.run_sensors
  # ----- Sensor Action -----
  # Running sensors!
 
iss.supply_hold.use_supplies("parts", 2)
  # ----- Supply Action -----
  # Supply Error: Insufficient parts in the supply hold.
iss.supply_hold.load_supplies("parts", 10)
  # ----- Supply Action -----
  # Loading 10 units of parts in the supply hold.
iss.supply_hold.use_supplies("parts", 2)
  # ----- Supply Action -----
  # Using 2 of parts from the supply hold.
iss.supply_reporter.report
  # ----- Supply Report -----
  # parts avalilable: 8 units
 
iss.thrusters.activate_thrusters
  # ----- Thruster Action -----
  # Thruster Error: Insufficient fuel available.
iss.fuel_tank.load_fuel(100)
  # ----- Fuel Action -----
  # Loading 100 units of fuel in the tank.
iss.thrusters.activate_thrusters
  # ----- Thruster Action -----
  # Thrusting action successful.
  # ----- Fuel Action -----
  # Using 10 units of fuel from the tank.
iss.fuel_reporter.report
  # ----- Fuel Report -----
# 90 units of fuel available.

ಕಾರ್ಯಕ್ರಮದ ಈ ಇತ್ತೀಚಿನ ಆವೃತ್ತಿಯಲ್ಲಿ, ಜವಾಬ್ದಾರಿಗಳನ್ನು ಎರಡು ಹೊಸ ವರ್ಗಗಳಾಗಿ ವಿಂಗಡಿಸಲಾಗಿದೆ, FuelReporter ಮತ್ತು SupplyReporter. ಅವರಿಬ್ಬರೂ ವರದಿಗಾರ ವರ್ಗದ ಮಕ್ಕಳು. ಹೆಚ್ಚುವರಿಯಾಗಿ, ನಾವು ಸ್ಪೇಸ್‌ಸ್ಟೇಷನ್ ವರ್ಗಕ್ಕೆ ನಿದರ್ಶನ ವೇರಿಯೇಬಲ್‌ಗಳನ್ನು ಸೇರಿಸಿದ್ದೇವೆ ಇದರಿಂದ ಅಗತ್ಯವಿದ್ದರೆ ಬಯಸಿದ ಉಪವರ್ಗವನ್ನು ಪ್ರಾರಂಭಿಸಬಹುದು. ಈಗ, ಭೂಮಿಯು ಬೇರೆ ಯಾವುದನ್ನಾದರೂ ಬದಲಾಯಿಸಲು ನಿರ್ಧರಿಸಿದರೆ, ನಾವು ಉಪವರ್ಗಗಳಿಗೆ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡುತ್ತೇವೆ ಮತ್ತು ಮುಖ್ಯ ವರ್ಗಕ್ಕೆ ಅಲ್ಲ.

ಸಹಜವಾಗಿ, ನಮ್ಮ ಕೆಲವು ವರ್ಗಗಳು ಇನ್ನೂ ಪರಸ್ಪರ ಅವಲಂಬಿಸಿವೆ. ಹೀಗಾಗಿ, ಸಪ್ಲೈ ರಿಪೋರ್ಟರ್ ಆಬ್ಜೆಕ್ಟ್ ಸಪ್ಲೈಹೋಲ್ಡ್ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿದೆ ಮತ್ತು ಫ್ಯುಯೆಲ್ ರಿಪೋರ್ಟರ್ ಫ್ಯುಯಲ್ ಟ್ಯಾಂಕ್ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿದೆ. ಸಹಜವಾಗಿ, ಬೂಸ್ಟರ್ಗಳನ್ನು ಇಂಧನ ಟ್ಯಾಂಕ್ಗೆ ಸಂಪರ್ಕಿಸಬೇಕು. ಆದರೆ ಇಲ್ಲಿ ಎಲ್ಲವೂ ಈಗಾಗಲೇ ತಾರ್ಕಿಕವಾಗಿ ಕಾಣುತ್ತದೆ, ಮತ್ತು ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡುವುದು ವಿಶೇಷವಾಗಿ ಕಷ್ಟಕರವಾಗುವುದಿಲ್ಲ - ಒಂದು ವಸ್ತುವಿನ ಕೋಡ್ ಅನ್ನು ಸಂಪಾದಿಸುವುದು ಇನ್ನೊಂದಕ್ಕೆ ಹೆಚ್ಚು ಪರಿಣಾಮ ಬೀರುವುದಿಲ್ಲ.

ಹೀಗಾಗಿ, ನಾವು ಮಾಡ್ಯುಲರ್ ಕೋಡ್ ಅನ್ನು ರಚಿಸಿದ್ದೇವೆ, ಅಲ್ಲಿ ಪ್ರತಿಯೊಂದು ವಸ್ತುಗಳು/ವರ್ಗಗಳ ಜವಾಬ್ದಾರಿಗಳನ್ನು ನಿಖರವಾಗಿ ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ. ಅಂತಹ ಕೋಡ್ನೊಂದಿಗೆ ಕೆಲಸ ಮಾಡುವುದು ಸಮಸ್ಯೆಯಲ್ಲ, ಅದನ್ನು ನಿರ್ವಹಿಸುವುದು ಸರಳವಾದ ಕೆಲಸವಾಗಿರುತ್ತದೆ. ನಾವು ಸಂಪೂರ್ಣ "ದೈವಿಕ ವಸ್ತು" ವನ್ನು SRP ಆಗಿ ಪರಿವರ್ತಿಸಿದ್ದೇವೆ.

ಸ್ಕಿಲ್‌ಬಾಕ್ಸ್ ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ:

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ