ื›ืชื™ื‘ืช ืงื•ื“ ื’ืžื™ืฉ ื‘ืืžืฆืขื•ืช SOLID

ื›ืชื™ื‘ืช ืงื•ื“ ื’ืžื™ืฉ ื‘ืืžืฆืขื•ืช SOLID

ืžื”ืžืชืจื’ื: ืคื•ืจืกื ืขื‘ื•ืจืš ืžืืžืจ ืžืืช Severin Perez ืขืœ ืฉื™ืžื•ืฉ ื‘ืขืงืจื•ื ื•ืช SOLID ื‘ืชื›ื ื•ืช. ื”ืžื™ื“ืข ืžื”ืžืืžืจ ื™ื”ื™ื” ืฉื™ืžื•ืฉื™ ื”ืŸ ืœืžืชื›ื ืชื™ื ืžืชื—ื™ืœื™ื ื•ื”ืŸ ืœืžืชื›ื ืชื™ื ืžื ื•ืกื™ื.

ืื ืืชื” ื‘ืคื™ืชื•ื—, ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉืฉืžืขืช ืขืœ ืขืงืจื•ื ื•ืช SOLID. ื”ื ืžืืคืฉืจื™ื ืœืžืชื›ื ืช ืœื›ืชื•ื‘ ืงื•ื“ ื ืงื™, ืžื•ื‘ื ื” ื”ื™ื˜ื‘ ื•ื ื™ืชืŸ ืœืชื—ื–ื•ืงื” ื‘ืงืœื•ืช. ืจืื•ื™ ืœืฆื™ื™ืŸ ืฉื‘ืชื›ื ื•ืช ื™ืฉื ืŸ ืžืกืคืจ ื’ื™ืฉื•ืช ื›ื™ืฆื“ ืœื‘ืฆืข ื›ื”ืœื›ื” ืขื‘ื•ื“ื” ืžืกื•ื™ืžืช. ืœืžื•ืžื—ื™ื ืฉื•ื ื™ื ื™ืฉ ืจืขื™ื•ื ื•ืช ื•ื”ื‘ื ื” ืฉื•ื ื™ื ืœื’ื‘ื™ "ื”ื“ืจืš ื”ื ื›ื•ื ื”"; ื”ื›ืœ ืชืœื•ื™ ื‘ื ื™ืกื™ื•ืŸ ืฉืœ ื›ืœ ืื“ื. ืขื ื–ืืช, ื”ืจืขื™ื•ื ื•ืช ืฉื”ื•ื›ืจื–ื• ื‘-SOLID ืžืชืงื‘ืœื™ื ืขืœ ื™ื“ื™ ื›ืžืขื˜ ื›ืœ ื ืฆื™ื’ื™ ืงื”ื™ืœืช ื”-IT. ื”ื ื”ืคื›ื• ืœื ืงื•ื“ืช ื”ืžื•ืฆื ืœื”ื•ืคืขืชื ื•ืœืคื™ืชื•ื— ืฉืœ ืฉื™ื˜ื•ืช ื ื™ื”ื•ืœ ืจื‘ื•ืช ื•ื˜ื•ื‘ื•ืช ืฉืœ ืคื™ืชื•ื—.

ื‘ื•ืื• ื ื‘ื™ืŸ ืžื” ื”ื ืขืงืจื•ื ื•ืช SOLID ื•ื›ื™ืฆื“ ื”ื ืขื•ื–ืจื™ื ืœื ื•.

Skillbox ืžืžืœื™ืฆื”: ืงื•ืจืก ืžืขืฉื™ "Mobile Developer PRO".

ืื ื• ืžื–ื›ื™ืจื™ื: ืœื›ืœ ืงื•ืจืื™ Habr - ื”ื ื—ื” ืฉืœ 10 ืจื•ื‘ืœ ื‘ืขืช ื”ืจืฉืžื” ืœื›ืœ ืงื•ืจืก Skillbox ื‘ืืžืฆืขื•ืช ืงื•ื“ ื”ื”ื˜ื‘ื” ืฉืœ Habr.

ืžื” ื–ื” SOLID?

ืžื•ื ื— ื–ื” ื”ื•ื ืงื™ืฆื•ืจ, ื›ืœ ืื•ืช ื‘ืžื•ื ื— ื”ื™ื ืชื—ื™ืœืช ื”ืฉื ืฉืœ ืขื™ืงืจื•ืŸ ืกืคืฆื™ืคื™:

  • Sืขื™ืงืจื•ืŸ ืื—ืจื™ื•ืช ืื—ื“. ืœืžื•ื“ื•ืœ ื™ื›ื•ืœื” ืœื”ื™ื•ืช ืกื™ื‘ื” ืื—ืช ื•ื™ื—ื™ื“ื” ืœืฉื™ื ื•ื™.
  • ื”ืฉืžื™ื™ื Oืขื˜/ืขื™ืงืจื•ืŸ ืกื’ื•ืจ (ืขืงืจื•ืŸ ืคืชื•ื—/ืกื’ื•ืจ). ืฉื™ืขื•ืจื™ื ื•ืืœืžื ื˜ื™ื ืื—ืจื™ื ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ืคืชื•ื—ื™ื ืœื”ืืจื›ื”, ืืš ืกื’ื•ืจื™ื ืœืฉื™ื ื•ื™ื™ื.
  • โ€Šื”ืฉืžื™ื™ื Lืขืงืจื•ืŸ ื”ื”ื—ืœืคื” ืฉืœ iskov (ืขืงืจื•ืŸ ื”ื—ืœืคืช ืœื™ืกืงื•ื‘). ืคื•ื ืงืฆื™ื•ืช ื”ืžืฉืชืžืฉื•ืช ื‘ืกื•ื’ ื‘ืกื™ืก ืฆืจื™ื›ื•ืช ืœื”ื™ื•ืช ืžืกื•ื’ืœื•ืช ืœื”ืฉืชืžืฉ ื‘ืชืชื™ ืกื•ื’ื™ื ืฉืœ ืกื•ื’ ื”ื‘ืกื™ืก ืžื‘ืœื™ ืœื“ืขืช ื–ืืช.
  • ื”ืฉืžื™ื™ื Iืขืงืจื•ืŸ ื”ืคืจื“ืช ืžืžืฉืงโ€Š (ืขืงืจื•ืŸ ื”ืคืจื“ืช ืžืžืฉืง). ื™ืฉื•ื™ื•ืช ืชื•ื›ื ื” ืœื ืืžื•ืจื•ืช ืœื”ื™ื•ืช ืชืœื•ื™ื•ืช ื‘ืฉื™ื˜ื•ืช ืฉืื™ื ืŸ ืžืฉืชืžืฉื•ืช ื‘ื”ืŸ.
  • ื”ืฉืžื™ื™ื Dืขืงืจื•ืŸ ื”ื™ืคื•ืš ืชืœื•ื™ื•ืช (ืขืงืจื•ืŸ ื”ื™ืคื•ืš ืชืœื•ืช). ืžื•ื“ื•ืœื™ื ื‘ืจืžื•ืช ื’ื‘ื•ื”ื•ืช ื™ื•ืชืจ ืœื ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ืชืœื•ื™ื™ื ื‘ืžื•ื“ื•ืœื™ื ื‘ืจืžื•ืช ื ืžื•ื›ื•ืช ื™ื•ืชืจ.

ืขื™ืงืจื•ืŸ ืื—ืจื™ื•ืช ื™ื—ื™ื“ื”

โ€Š
ืขื™ืงืจื•ืŸ ื”ืื—ืจื™ื•ืช ื”ื™ื—ื™ื“ื” (SRP) ืงื•ื‘ืข ืฉื›ืœ ืžื—ืœืงื” ืื• ืžื•ื“ื•ืœ ื‘ืชื•ื›ื ื™ืช ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ืื—ืจืื™ื ืจืง ืœื—ืœืง ืื—ื“ ืžื”ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืฉืœ ืื•ืชื” ืชื•ื›ื ื™ืช. ื‘ื ื•ืกืฃ, ื™ืฉ ืœื”ืงืฆื•ืช ืืœืžื ื˜ื™ื ืฉืœ ืื—ืจื™ื•ืช ื–ื• ืœื›ื™ืชื” ืžืฉืœื”ื, ื‘ืžืงื•ื ืœืคื–ืจ ืื•ืชื ื‘ื™ืŸ ื›ื™ืชื•ืช ืœื ืงืฉื•ืจื•ืช. ื”ืžืคืชื— ื•ื”ืื•ื•ื ื’ืœื™ืกื˜ ื”ืจืืฉื™ ืฉืœ SRP, ืจื•ื‘ืจื˜ ืก. ืžืจื˜ื™ืŸ, ืžืชืืจ ืื—ืจื™ื•ืช ื›ืกื™ื‘ื” ืœืฉื™ื ื•ื™. ื”ื•ื ื”ืฆื™ืข ื‘ืžืงื•ืจ ืืช ื”ืžื•ื ื— ื”ื–ื” ื›ืื—ื“ ื”ืžืจื›ื™ื‘ื™ื ืฉืœ ืขื‘ื•ื“ืชื• "ืขืงืจื•ื ื•ืช ืขื™ืฆื•ื‘ ืžื•ื ื—ื” ืขืฆืžื™ื". ื”ืจืขื™ื•ืŸ ืžืฉืœื‘ ื—ืœืง ื’ื“ื•ืœ ืžื“ืคื•ืก ื”ืงื™ืฉื•ืจื™ื•ืช ืฉื”ื•ื’ื“ืจ ื‘ืขื‘ืจ ืขืœ ื™ื“ื™ ื˜ื•ื ื“ื”ืžืจืงื•.

ื”ืžื•ืฉื’ ื›ืœืœ ื’ื ื›ืžื” ืžื•ืฉื’ื™ื ืฉื’ื™ื‘ืฉ ื“ื•ื“ ืคืจื ืก. ืฉื ื™ ื”ืขื™ืงืจื™ื™ื ืฉื‘ื”ื ื”ื ืื ืงืคืกื•ืœืฆื™ื” ื•ื”ืกืชืจืช ืžื™ื“ืข. ืคืจื ืก ื˜ืขืŸ ื›ื™ ื—ืœื•ืงืช ืžืขืจื›ืช ืœืžื•ื“ื•ืœื™ื ื ืคืจื“ื™ื ืื™ื ื” ืฆืจื™ื›ื” ืœื”ืชื‘ืกืก ืขืœ ื ื™ืชื•ื— ืฉืœ ื“ื™ืื’ืจืžื•ืช ื‘ืœื•ืงื™ื ืื• ื–ืจื™ืžื•ืช ื‘ื™ืฆื•ืข. ื›ืœ ืื—ื“ ืžื”ืžื•ื“ื•ืœื™ื ื—ื™ื™ื‘ ืœื”ื›ื™ืœ ืคืชืจื•ืŸ ืกืคืฆื™ืคื™ ื”ืžืกืคืง ืžื™ื ื™ืžื•ื ืฉืœ ืžื™ื“ืข ืœืœืงื•ื—ื•ืช.

ืื’ื‘, ืžืจื˜ื™ืŸ ื ืชืŸ ื“ื•ื’ืžื” ืžืขื ื™ื™ื ืช ืขื ืžื ื”ืœื™ื ื‘ื›ื™ืจื™ื ืฉืœ ื—ื‘ืจื” (COO, CTO, CFO), ืฉื›ืœ ืื—ื“ ืžื”ื ืžืฉืชืžืฉ ื‘ืชื•ื›ื ื” ืขืกืงื™ืช ืกืคืฆื™ืคื™ืช ืœืžื˜ืจื•ืช ืฉื•ื ื•ืช. ื›ืชื•ืฆืื” ืžื›ืš, ื›ืœ ืื—ื“ ืžื”ื ื™ื›ื•ืœ ืœื™ื™ืฉื ืฉื™ื ื•ื™ื™ื ื‘ืชื•ื›ื ื” ืžื‘ืœื™ ืœื”ืฉืคื™ืข ืขืœ ื”ืื™ื ื˜ืจืกื™ื ืฉืœ ืžื ื”ืœื™ื ืื—ืจื™ื.

ื—ืคืฅ ืืœื•ื”ื™

ื›ืžื• ืชืžื™ื“, ื”ื“ืจืš ื”ื˜ื•ื‘ื” ื‘ื™ื•ืชืจ ืœืœืžื•ื“ SRP ื”ื™ื ืœืจืื•ืช ืื•ืชื• ื‘ืคืขื•ืœื”. ื”ื‘ื” ื ืกืชื›ืœ ืขืœ ืงื˜ืข ืฉืœ ื”ืชื•ื›ื ื™ืช ืฉืื™ื ื• ืขื•ืžื“ ื‘ืขืงืจื•ืŸ ื”ืื—ืจื™ื•ืช ื”ื™ื—ื™ื“ื”. ื–ื”ื• ืงื•ื“ ืจื•ื‘ื™ ืฉืžืชืืจ ืืช ื”ื”ืชื ื”ื’ื•ืช ื•ื”ืชื›ื•ื ื•ืช ืฉืœ ืชื—ื ืช ื”ื—ืœืœ.

ืขื™ื™ืŸ ื‘ื“ื•ื’ืžื” ื•ื ืกื” ืœืงื‘ื•ืข ืืช ื”ื“ื‘ืจื™ื ื”ื‘ืื™ื:
ืื—ืจื™ื•ืช ืฉืœ ืื•ืชื ืื•ื‘ื™ื™ืงื˜ื™ื ื”ืžื•ืฆื”ืจื™ื ื‘ืžื—ืœืงืช SpaceStation.
ืžื™ ืฉืขืฉื•ื™ ืœื”ืชืขื ื™ื™ืŸ ื‘ืชืคืขื•ืœ ืชื—ื ืช ื”ื—ืœืœ.

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

ืœืžืขืฉื”, ืชื—ื ืช ื”ื—ืœืœ ืฉืœื ื• ืœื ืžืชืคืงื“ืช (ืื ื™ ืœื ื—ื•ืฉื‘ ืฉืืงื‘ืœ ืฉื™ื—ื” ืžื ืืก"ื ื‘ืงืจื•ื‘), ืื‘ืœ ื™ืฉ ื›ืืŸ ืžื” ืœื ืชื—.

ืœืคื™ื›ืš, ืœืžื—ืœืงืช SpaceStation ื™ืฉ ื›ืžื” ืชื—ื•ืžื™ ืื—ืจื™ื•ืช (ืื• ืžืฉื™ืžื•ืช). ื ื™ืชืŸ ืœื—ืœืง ืืช ื›ื•ืœื ืœืกื•ื’ื™ื:

  • ื—ื™ื™ืฉื ื™ื;
  • ืืกืคืงื” โ€‹โ€‹(ื—ื•ืžืจื™ื ืžืชื›ืœื™ื);
  • ื“ืœืง;
  • ืžืื™ืฆื™ื.

ืœืžืจื•ืช ืฉืืฃ ืื—ื“ ืžืขื•ื‘ื“ื™ ื”ืชื—ื ื” ืœื ืžื•ืงืฆื” ื›ื™ืชื”, ืื ื—ื ื• ื™ื›ื•ืœื™ื ื‘ืงืœื•ืช ืœื“ืžื™ื™ืŸ ืžื™ ืื—ืจืื™ ืขืœ ืžื”. ื›ื›ืœ ื”ื ืจืื”, ื”ืžื“ืขืŸ ืฉื•ืœื˜ ื‘ื—ื™ื™ืฉื ื™ื, ื”ืœื•ื’ื™ืกื˜ื™ ืื—ืจืื™ ืขืœ ืืกืคืงืช ื”ืžืฉืื‘ื™ื, ื”ืžื”ื ื“ืก ืื—ืจืื™ ืขืœ ืืกืคืงืช ื”ื“ืœืง, ื•ื”ื˜ื™ื™ืก ืฉื•ืœื˜ ืขืœ ื”ืžืื™ืฆื™ื.

ื”ืื ื ื•ื›ืœ ืœื•ืžืจ ืฉืชื•ื›ื ื™ืช ื–ื• ืื™ื ื” ืชื•ืืžืช SRP? ื›ืŸ ื‘ื˜ื—. ืื‘ืœ ืžื—ืœืงืช SpaceStation ื”ื™ื "ืื•ื‘ื™ื™ืงื˜ ืืœื•ื”ื™ื" ื˜ื™ืคื•ืกื™ ืฉื™ื•ื“ืข ื”ื›ืœ ื•ืขื•ืฉื” ื”ื›ืœ. ื–ื”ื• ืื ื˜ื™-ื“ืคื•ืก ืžืจื›ื–ื™ ื‘ืชื›ื ื•ืช ืžื•ื ื—ื” ืขืฆืžื™ื. ืœืžืชื—ื™ืœื™ื, ื—ืคืฆื™ื ื›ืืœื” ืงืฉื™ื ืžืื•ื“ ืœืชื—ื–ื•ืงื”. ืขื“ ื›ื” ื”ืชื•ื›ื ื™ืช ืžืื•ื“ ืคืฉื•ื˜ื”, ื›ืŸ, ืื‘ืœ ืชืืจื• ืœืขืฆืžื›ื ืžื” ื™ืงืจื” ืื ื ื•ืกื™ืฃ ืชื›ื•ื ื•ืช ื—ื“ืฉื•ืช. ืื•ืœื™ ืชื—ื ืช ื”ื—ืœืœ ืฉืœื ื• ืชืฆื˜ืจืš ืชื—ื ื” ืจืคื•ืื™ืช ืื• ื—ื“ืจ ื™ืฉื™ื‘ื•ืช. ื•ื›ื›ืœ ืฉื™ื”ื™ื• ื™ื•ืชืจ ืคื•ื ืงืฆื™ื•ืช, ื›ืš SpaceStation ืชื’ื“ืœ. ื•ื‘ื›ืŸ, ืžื›ื™ื•ื•ืŸ ืฉื”ืžืชืงืŸ ื”ื–ื” ื™ื”ื™ื” ืžื—ื•ื‘ืจ ืœืื—ืจื™ื, ื”ืฉื™ืจื•ืช ื‘ืžืชื—ื ื›ื•ืœื• ื™ื”ืคื•ืš ืœืžื•ืจื›ื‘ ืขื•ื“ ื™ื•ืชืจ. ื›ืชื•ืฆืื” ืžื›ืš, ืื ื• ื™ื›ื•ืœื™ื ืœืฉื‘ืฉ ืืช ืคืขื•ืœืชื ืฉืœ, ืœืžืฉืœ, ืžืื™ืฆื™ื. ืื ื—ื•ืงืจ ื™ื‘ืงืฉ ืฉื™ื ื•ื™ื™ื ื‘ื—ื™ื™ืฉื ื™ื, ื”ื“ื‘ืจ ืขืœื•ืœ ืžืื•ื“ ืœื”ืฉืคื™ืข ืขืœ ืžืขืจื›ื•ืช ื”ืชืงืฉื•ืจืช ืฉืœ ื”ืชื—ื ื”.

ื”ืคืจื” ืฉืœ ืขืงืจื•ืŸ SRP ืขืฉื•ื™ื” ืœืชืช ื ื™ืฆื—ื•ืŸ ื˜ืงื˜ื™ ืœื˜ื•ื•ื— ืงืฆืจ, ืื‘ืœ ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ "ื ืคืกื™ื“ ื‘ืžืœื—ืžื”", ื•ื™ื”ื™ื” ืงืฉื” ืžืื•ื“ ืœืฉืžื•ืจ ืขืœ ืžืคืœืฆืช ื›ื–ื• ื‘ืขืชื™ื“. ืขื“ื™ืฃ ืœื—ืœืง ืืช ื”ืชื•ื›ื ื™ืช ืœืžืงื˜ืขื™ื ื ืคืจื“ื™ื ืฉืœ ืงื•ื“, ืฉื›ืœ ืื—ื“ ืžื”ื ืื—ืจืื™ ืขืœ ื‘ื™ืฆื•ืข ืคืขื•ืœื” ืžืกื•ื™ืžืช. ืื ื ื‘ื™ืŸ ื–ืืช, ื‘ื•ืื• ื ืฉื ื” ืืช ืžื—ืœืงื” ืฉืœ SpaceStation.

ื‘ื•ืื• ื ื—ืœืง ืื—ืจื™ื•ืช

ืœืžืขืœื” ื”ื’ื“ืจื ื• ืืจื‘ืขื” ืกื•ื’ื™ ืคืขื•ืœื•ืช ื”ื ืฉืœื˜ื•ืช ืขืœ ื™ื“ื™ ืžื—ืœืงืช SpaceStation. ืื ื• ื ื–ื›ื•ืจ ืื•ืชื ื‘ืขืช ืขื™ื‘ื•ื“ ืžื—ื“ืฉ. ื”ืงื•ื“ ื”ืžืขื•ื“ื›ืŸ ืžืชืื™ื ื™ื•ืชืจ ืœ-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

ื™ืฉ ื”ืจื‘ื” ืฉื™ื ื•ื™ื™ื, ื”ืชื•ื›ื ื™ืช ื‘ื”ื—ืœื˜ ื ืจืื™ืช ื˜ื•ื‘ ื™ื•ืชืจ ืขื›ืฉื™ื•. ื›ืขืช ืžื—ืœืงืช ื”-SpaceStation ืฉืœื ื• ื”ืคื›ื” ื™ื•ืชืจ ืœืžื›ื•ืœื” ืฉื‘ื” ืžืชื—ื™ืœื•ืช ืคืขื•ืœื•ืช ืขื‘ื•ืจ ื—ืœืงื™ื ืชืœื•ื™ื™ื, ื›ื•ืœืœ ืกื˜ ื—ื™ื™ืฉื ื™ื, ืžืขืจื›ืช ืืกืคืงื” โ€‹โ€‹ืžืชื›ืœื”, ืžื™ื›ืœ ื“ืœืง ื•ืžื’ื‘ืจื™ื.

ืขื‘ื•ืจ ื›ืœ ืื—ื“ ืžื”ืžืฉืชื ื™ื ื™ืฉ ื›ืขืช ืžื—ืœืงื” ืžืชืื™ืžื”: ื—ื™ื™ืฉื ื™ื; SupplyHold; ืžื™ื›ืœ ื“ืœืง; ื“ื—ืคื™ื.

ื™ืฉื ื ืžืกืคืจ ืฉื™ื ื•ื™ื™ื ื—ืฉื•ื‘ื™ื ื‘ื’ืจืกื” ื–ื• ืฉืœ ื”ืงื•ื“. ื”ื ืงื•ื“ื” ื”ื™ื ืฉืคื•ื ืงืฆื™ื•ืช ืื™ื ื“ื™ื‘ื™ื“ื•ืืœื™ื•ืช ืื™ื ืŸ ืจืง ืžื•ื‘ืœืขื•ืช ื‘ื›ื™ืชื•ืช ืฉืœื”ืŸ, ื”ืŸ ืžืื•ืจื’ื ื•ืช ื‘ืฆื•ืจื” ื›ื–ื• ืฉื”ืŸ ื ื™ืชื ื•ืช ืœื—ื™ื–ื•ื™ ื•ืขืงื‘ื™ื•ืช. ืื ื• ืžืงื‘ืฆื™ื ืืœืžื ื˜ื™ื ื‘ืขืœื™ ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ื“ื•ืžื” ื‘ื”ืชืื ืœืขืงืจื•ืŸ ื”ืงื•ื”ืจื ื˜ื™ื•ืช. ืขื›ืฉื™ื•, ืื ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืฉื ื•ืช ืืช ืื•ืคืŸ ืคืขื•ืœืช ื”ืžืขืจื›ืช, ืœืขื‘ื•ืจ ืžืžื‘ื ื” hash ืœืžืขืจืš, ืคืฉื•ื˜ ื”ืฉืชืžืฉ ื‘ืžื—ืœืงื” SupplyHold; ืื ื—ื ื• ืœื ืฆืจื™ื›ื™ื ืœื’ืขืช ื‘ืžื•ื“ื•ืœื™ื ืื—ืจื™ื. ื›ืš, ืื ืงืฆื™ืŸ ื”ืœื•ื’ื™ืกื˜ื™ืงื” ื™ืฉื ื” ืžืฉื”ื• ื‘ืžื“ื•ืจ ืฉืœื•, ืฉืืจ ื”ืชื—ื ื” ืชื™ืฉืืจ ืฉืœืžื”. ื‘ืžืงืจื” ื–ื”, ื›ื™ืชืช SpaceStation ืืคื™ืœื• ืœื ืชื”ื™ื” ืžื•ื“ืขืช ืœืฉื™ื ื•ื™ื™ื.

ื”ืงืฆื™ื ื™ื ืฉืœื ื• ืฉืขื•ื‘ื“ื™ื ื‘ืชื—ื ืช ื”ื—ืœืœ ื›ื ืจืื” ืฉืžื—ื™ื ืขืœ ื”ืฉื™ื ื•ื™ื™ื ื›ื™ ื”ื ื™ื›ื•ืœื™ื ืœื‘ืงืฉ ืืช ืืœื” ืฉื”ื ืฆืจื™ื›ื™ื. ืฉื™ืžื• ืœื‘ ืฉืœืงื•ื“ ื™ืฉ ืฉื™ื˜ื•ืช ื›ื’ื•ืŸ report_supplies ื•-report_fuel ื”ื›ืœื•ืœื•ืช ื‘ืžื—ืœืงื•ืช SupplyHold ื•-FuelTank. ืžื” ื™ืงืจื” ืื ื›ื“ื•ืจ ื”ืืจืฅ ื™ื‘ืงืฉ ืœืฉื ื•ืช ืืช ืื•ืคืŸ ื”ื“ื™ื•ื•ื— ืฉืœื•? ื™ื”ื™ื” ืฆื•ืจืš ืœืฉื ื•ืช ืืช ืฉื ื™ ื”ืžื—ืœืงื•ืช, SupplyHold ื•-FuelTank. ืžื” ืื ืืชื” ืฆืจื™ืš ืœืฉื ื•ืช ืืช ืื•ืคืŸ ืืกืคืงืช ื”ื“ืœืง ื•ื”ื—ื•ืžืจื™ื ื”ืžืชื›ืœื™ื? ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉืชืฆื˜ืจืš ืœืฉื ื•ืช ืฉื•ื‘ ืืช ื›ืœ ืื•ืชื ืžื—ืœืงื•ืช. ื•ื–ื• ื›ื‘ืจ ื”ืคืจื” ืฉืœ ืขืงืจื•ืŸ 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. ืฉื ื™ื”ื ื™ืœื“ื™ ื›ื™ืชืช ื›ืชื‘. ื‘ื ื•ืกืฃ, ื”ื•ืกืคื ื• ืžืฉืชื ื™ ืžื•ืคืข ืœืžื—ืœืงื” ืฉืœ SpaceStation ื›ืš ืฉื ื™ืชืŸ ื™ื”ื™ื” ืœืืชื—ืœ ืืช ืชืช ื”ืžื—ืœืงื” ื”ืจืฆื•ื™ื” ื‘ืžื™ื“ืช ื”ืฆื•ืจืš. ืขื›ืฉื™ื•, ืื ื›ื“ื•ืจ ื”ืืจืฅ ื™ื—ืœื™ื˜ ืœืฉื ื•ืช ืžืฉื”ื• ืื—ืจ, ืื– ื ืขืฉื” ืฉื™ื ื•ื™ื™ื ื‘ืชืช ื”ืžื—ืœืงื•ืช, ื•ืœื ื‘ืžื—ืœืงื” ื”ืจืืฉื™ืช.

ื›ืžื•ื‘ืŸ, ื—ืœืง ืžื”ืฉื™ืขื•ืจื™ื ืฉืœื ื• ืขื“ื™ื™ืŸ ืชืœื•ื™ื™ื ื–ื” ื‘ื–ื”. ืœืคื™ื›ืš, ื”ืื•ื‘ื™ื™ืงื˜ SupplyReporter ืชืœื•ื™ ื‘-SupplyHold, ื•-FuelReporter ืชืœื•ื™ ื‘-FuelTank. ื›ืžื•ื‘ืŸ ืฉื”ื‘ื•ืกื˜ืจื™ื ื—ื™ื™ื‘ื™ื ืœื”ื™ื•ืช ืžื—ื•ื‘ืจื™ื ืœืžื™ื›ืœ ื”ื“ืœืง. ืื‘ืœ ื›ืืŸ ื”ื›ืœ ื›ื‘ืจ ื ืจืื” ื”ื’ื™ื•ื ื™, ื•ื‘ื™ืฆื•ืข ืฉื™ื ื•ื™ื™ื ืœื ื™ื”ื™ื” ืงืฉื” ื‘ืžื™ื•ื—ื“ - ืขืจื™ื›ืช ื”ืงื•ื“ ืฉืœ ืื•ื‘ื™ื™ืงื˜ ืื—ื“ ืœื ืชืฉืคื™ืข ืžืื•ื“ ืขืœ ืื—ืจ.

ืœืคื™ื›ืš, ื™ืฆืจื ื• ืงื•ื“ ืžื•ื“ื•ืœืจื™ ืฉื‘ื• ื”ืื—ืจื™ื•ืช ืฉืœ ื›ืœ ืื—ื“ ืžื”ืื•ื‘ื™ื™ืงื˜ื™ื/ืžื—ืœืงื•ืช ืžื•ื’ื“ืจื•ืช ื‘ืžื“ื•ื™ืง. ืขื‘ื•ื“ื” ืขื ืงื•ื“ ื›ื–ื” ืื™ื ื” ื‘ืขื™ื”, ืœืฉืžื•ืจ ืขืœื™ื• ืชื”ื™ื” ืžืฉื™ืžื” ืคืฉื•ื˜ื”. ื”ืžืจื ื• ืืช ื›ืœ "ื”ืื•ื‘ื™ื™ืงื˜ ื”ืืœื•ื”ื™" ืœ-SRP.

Skillbox ืžืžืœื™ืฆื”:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”