Manoratra kaody mora ampiasaina amin'ny fampiasana SOLID

Manoratra kaody mora ampiasaina amin'ny fampiasana SOLID

Avy amin'ny mpandika teny: navoaka ho anao lahatsoratra nataon'i Severin Perez momba ny fampiasana fitsipika SOLID amin'ny fandaharana. Ny fampahalalana avy amin'ny lahatsoratra dia ho ilaina ho an'ireo vao manomboka sy programmer za-draharaha.

Raha eo amin'ny fampandrosoana ianao, dia azo inoana fa nandre momba ny fitsipika SOLID ianao. Izy ireo dia ahafahan'ny mpandrindra manoratra kaody madio, voarafitra tsara ary mora karakaraina. Tsara ny manamarika fa amin'ny fandaharana dia misy fomba maro ahafahana manao asa manokana. Samy manana ny hevitra sy ny fahatakarana ny "lalana marina" ny manam-pahaizana samihafa; miankina amin'ny traikefan'ny tsirairay izany. Na izany aza, ny hevitra ambara amin'ny SOLID dia saika eken'ny solontenan'ny vondrom-piarahamonina IT. Izy ireo no toerana niaingan'ny firongatry sy ny fampivoarana fomba fitantanana tsara maro.

Andeha hojerentsika hoe inona ny fitsipika SOLID sy ny fomba anampiany antsika.

Skillbox dia manoro hevitra: Mazava ho azy "Mobile Developer PRO".

Mampahatsiahy izahay: ho an'ny mpamaky rehetra ny "Habr" - fihenam-bidy 10 roubles rehefa misoratra anarana amin'ny taranja Skillbox rehetra mampiasa ny code promotional "Habr".

Inona no atao hoe SOLID?

Ity teny ity dia fanafohezana, ny litera tsirairay amin'ny teny dia fiandohan'ny anaran'ny fitsipika iray manokana:

  • Single Principe Responsibility. Ny mΓ΄dely iray dia mety manana antony iray ary iray ihany ho an'ny fanovana.
  • The Openina/Fitsipika mihidy (fitsipika misokatra / mihidy). Ny kilasy sy ny singa hafa dia tokony misokatra ho an'ny fanitarana, fa mikatona ho an'ny fanovana.
  • β€ŠThe LFitsipika fanoloana iskov (Fitsipika fanoloana Liskov). Ny fiasa mampiasa karazana fototra dia tokony ho afaka mampiasa zana-karazana amin'ny karazana fototra nefa tsy fantany.
  • The IFitsipika fanavakavahana amin'ny interfaceβ€Š (fitsipika fisarahana amin'ny interface). Tsy tokony hiankin-doha amin'ny fomba tsy ampiasainy ny sampan'ny rindrambaiko.
  • The DEpendency Inversion Principle (fitsipika momba ny fiankinan-doha). Ny modules amin'ny ambaratonga ambony dia tsy tokony hiankina amin'ny modules amin'ny ambaratonga ambany.

Fitsipiky ny andraikitra tokana

β€Š
Ny fitsipiky ny andraikitra tokana (SRP) dia milaza fa ny kilasy na mody tsirairay ao amin'ny programa dia tokony ho tompon'andraikitra amin'ny ampahany iray amin'ny fiasan'ny programa. Fanampin'izany, ireo singa amin'io andraikitra io dia tokony homena ny kilasiny manokana, fa tsy hiparitaka amin'ny kilasy tsy misy ifandraisany. Robert S. Martin, mpamorona sy lehiben'ny evanjelistra SRP, dia mamaritra ny fandraisana andraikitra ho anton'ny fiovana. Tany am-boalohany dia nanolotra ity teny ity ho iray amin'ireo singa amin'ny sanganasany izy "Principles of Object-Oriented Design". Ny foto-kevitra dia mampiditra ny ankamaroan'ny lamina fifandraisana izay nofaritan'i Tom DeMarco teo aloha.

Ny foto-kevitra ihany koa dia nahitana hevitra maromaro noforonin'i David Parnas. Ny roa lehibe dia ny encapsulation sy ny fanafenana vaovao. Nanamafy i Parnas fa tsy tokony hiorina amin'ny famakafakana ny kisary sakana na ny fizotran'ny famonoana ny fizarana rafitra iray ho maody misaraka. Ny iray amin'ireo maody dia tsy maintsy misy vahaolana manokana izay manome fampahalalana kely indrindra ho an'ny mpanjifa.

Teny an-dalana, nanome ohatra mahaliana i Martin miaraka amin'ireo mpitantana ambony amin'ny orinasa iray (COO, CTO, CFO), izay samy mampiasa rindrambaiko fandraharahana manokana ho an'ny tanjona samihafa. Vokatr'izany, na iza na iza amin'izy ireo dia afaka manatanteraka fanovana amin'ny rindrambaiko tsy misy fiantraikany amin'ny tombontsoan'ny mpitantana hafa.

Zavatra masina

Toy ny mahazatra, ny fomba tsara indrindra hianarana SRP dia ny fahitana azy amin'ny asa. Andeha hojerentsika ny fizarana iray amin'ny programa izay TSY manaraka ny fitsipiky ny andraikitra tokana. Ity dia kaody Ruby izay mamaritra ny fihetsika sy ny toetran'ny tobin'ny habakabaka.

Avereno jerena ilay ohatra ary andramo hamaritana ireto manaraka ireto:
Ny andraikitr'ireo zavatra voalaza ao amin'ny kilasy SpaceStation.
Ireo izay mety ho liana amin'ny fampandehanana ny tobin'ny habakabaka.

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

Raha ny marina, tsy miasa ny tobim-piaramanidina misy antsika (heveriko fa tsy hahazo antso avy amin'ny NASA aho ato ho ato), fa misy zavatra hodinihina eto.

Noho izany, manana andraikitra (na asa) samihafa ny kilasy SpaceStation. Izy rehetra dia azo zaraina ho karazany:

  • sensor;
  • fitaovana (consumables);
  • solika;
  • accelerators.

Na dia tsy misy na iray aza amin'ireo mpiasan'ny tobim-piantsonana nomena kilasy, dia azontsika an-tsaina mora foana hoe iza no tompon'andraikitra amin'ny inona. Azo inoana fa ny mpahay siansa no mifehy ny sensor, ny logisticien no tompon'andraikitra amin'ny famatsiana loharanon-karena, ny injeniera no tompon'andraikitra amin'ny famatsiana solika, ary ny mpanamory no mifehy ny boosters.

Afaka milaza ve isika fa tsy mifanaraka amin'ny SRP ity programa ity? Eny, azo antoka. Fa ny kilasy SpaceStation dia "zavatra andriamanitra" mahazatra izay mahafantatra ny zava-drehetra ary manao ny zava-drehetra. Ity dia anti-pattern lehibe amin'ny fandaharana mifototra amin'ny zavatra. Ho an'ny vao manomboka, ny zavatra toy izany dia tena sarotra ny fikojakojana. Hatreto dia tena tsotra ny fandaharana, eny, fa alaivo sary an-tsaina izay hitranga raha manampy endri-javatra vaovao isika. Angamba mila toeram-pitsaboana na efitrano fivoriana ny tobim-pitsaboana misy antsika. Ary arakaraky ny fiasan'izy ireo no hitomboan'ny SpaceStation. Eny, satria hifandray amin'ny hafa io trano io, dia ho sarotra kokoa ny fanompoana ny complexe manontolo. Vokatr'izany dia afaka manakorontana ny fiasan'ny, ohatra, ny accelerators. Raha misy mpikaroka mangataka fanovana amin'ny sensor, dia mety hisy fiantraikany tsara amin'ny rafi-pifandraisan'ny toby izany.

Ny fanitsakitsahana ny fitsipiky ny SRP dia mety hanome fandresena amin'ny tetika fohy, fa amin'ny farany dia "ho resy amin'ny ady" isika, ary ho lasa sarotra be ny mitazona biby goavam-be toy izany amin'ny ho avy. Ny tsara indrindra dia ny mizara ny programa ho fizarana kaody samihafa, izay samy tompon'andraikitra amin'ny fanatanterahana asa manokana. Raha takatsika izany, andao hanova ny kilasy SpaceStation.

Andao hizara andraikitra

Etsy ambony dia namaritra karazana asa efatra izay fehezin'ny kilasy SpaceStation. Hotadidintsika izy ireo rehefa refactoring. Ny kaody nohavaozina dia mifanandrify kokoa amin'ny 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

Betsaka ny fiovana, azo antoka fa tsara kokoa izao ny fandaharana. Ankehitriny ny kilasin'ny SpaceStation dia lasa kaontenera kokoa izay anombohana ny asa ho an'ny ampahany miankina, ao anatin'izany ny andiana sensor, rafitra famatsiana azo ampiasaina, tankina solika ary booster.

Ho an'ny iray amin'ireo variables dia misy kilasy mifanaraka amin'izany: Sensors; SupplyHold; FuelTank; Thrusters.

Misy fiovana lehibe maromaro amin'ity dikan-kaody ity. Ny tiana holazaina dia ny hoe ny asan'ny tsirairay dia tsy voarakitra ao amin'ny kilasiny ihany, fa voalamina amin'ny fomba azo vinavinaina sy tsy miovaova. Manangona singa manana fiasa mitovy izahay mba hanaraka ny fitsipiky ny firindrana. Ankehitriny, raha mila manova ny fomba fiasan'ny rafitra isika, miala amin'ny rafitra hash mankany amin'ny array, ampiasao fotsiny ny kilasy SupplyHold; tsy mila mikitika modules hafa isika. Amin'izany fomba izany, raha manova zavatra ao amin'ny fizarana misy azy ny tompon'andraikitra ara-pitaovana, dia hijanona ho tsy misy dikany ny sisa amin'ny gara. Amin'ity tranga ity, ny kilasy SpaceStation dia tsy hahafantatra akory ny fiovana.

Faly angamba ireo manamboninahitra miasa ao amin’ny habakabaka noho ny fiovana satria afaka mangataka izay ilainy izy ireo. Mariho fa ny code dia manana fomba toy ny report_supplies sy report_fuel voarakitra ao amin'ny kilasy SupplyHold sy FuelTank. Inona no hitranga raha mangataka ny hanova ny fomba fitantarany ny Tany? Ny kilasy roa, SupplyHold sy FuelTank, dia mila ovaina. Ahoana raha mila manova ny fomba fanaterana solika sy kojakoja ilaina ianao? Mety tsy maintsy hanova ireo kilasy mitovy rehetra indray ianao. Ary efa fanitsakitsahana ny foto-kevitry ny SRP izany. Aleo amboary ity.

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.

Amin'ity dikan-teny farany amin'ny fandaharana ity, nozaraina ho kilasy roa vaovao ny andraikitra, dia ny FuelReporter sy ny SupplyReporter. Samy zanaky ny kilasy Reporter izy ireo. Ho fanampin'izay, nampidirinay ny fari-piadidiana ohatra amin'ny kilasy SpaceStation mba ho azo atomboka ny zana-kilasy tiana raha ilaina. Ankehitriny, raha manapa-kevitra ny hanova zavatra hafa ny Tany, dia hanao fanovana amin'ny sokajy ambany isika, fa tsy amin'ny kilasy fototra.

Mazava ho azy fa mbola mifampiankina ny kilasintsika sasany. Noho izany, miankina amin'ny SupplyHold ny zavatra SupplyReporter, ary miankina amin'ny FuelTank ny FuelReporter. Mazava ho azy, ny boosters dia tsy maintsy mifandray amin'ny fitoeran-tsolika. Saingy eto ny zava-drehetra dia efa mirindra tsara, ary ny fanovana dia tsy ho sarotra indrindra - ny fanovana ny code amin'ny zavatra iray dia tsy hisy fiantraikany amin'ny hafa.

Noho izany, namorona code modular izay voafaritra mazava tsara ny andraikitry ny tsirairay amin'ireo zavatra/kilasy. Ny miasa miaraka amin'ny code toy izany dia tsy olana, ny fitazonana azy dia ho asa tsotra. Nanova ny β€œzavatra masina” manontolo ho SRP isika.

Skillbox dia manoro hevitra:

Source: www.habr.com

Add a comment