Tusiaina o code fe'avea'i e fa'aaoga ai le SOLID

Tusiaina o code fe'avea'i e fa'aaoga ai le SOLID

Mai le faaliliu: lomia mo oe tusiga a Severin Perez e uiga i le faʻaaogaina o mataupu faavae SOLID i polokalame. O faʻamatalaga mai le tusiga o le a aoga i tagata amata ma le poto masani polokalame.

Afai e te alu i le atinaʻe, e foliga mai ua e faʻalogo i mataupu faavae SOLID. Latou te mafai ai e le tagata fai polokalame ona tusia le tulafono mama, fa'atulaga lelei ma faigofie ona tausia. E taua le maitauina o le polokalame o loʻo i ai le tele o auala i le auala e saʻo ai le faia o se galuega faapitoa. O tagata tomai faapitoa eseese e eseese manatu ma malamalama i le "ala sa'o"; e faalagolago uma lava i le poto masani o tagata taitoatasi. Ae ui i lea, o manatu na folafolaina ile SOLID e talia e toetoe lava o sui uma o le IT community. Na avea ma amataga mo le tula'i mai ma le atina'eina o le tele o faiga lelei tau pulega.

Sei o tatou malamalama po o le a le mataupu faavae SOLID ma pe faapefea ona fesoasoani ia i tatou.

Ua fautuaina e Skillbox: Kosi fa'ata'ita'i "Mobile Developer PRO".

Matou te faʻamanatu atu ia te oe: mo tagata faitau uma o le "Habr" - o se faʻaitiitiga o 10 rubles pe a lesitala i soʻo se vasega Skillbox e faʻaaoga ai le code promotional "Habr".

O le a le SOLID?

O lenei faaupuga o se faapuupuuga, o mataitusi taitasi o le faaupuga o le amataga lea o le igoa o se mataupu faavae patino:

  • SMataupu Faavae o le Tiutetauave. O se module e mafai ona tasi ma na'o le tasi le mafuaaga mo suiga.
  • le Openi / Mataupu Faavae Tapuni (tatala/tapuni mataupu faavae). Vasega ma isi elemene e tatau ona tatala mo le faʻaopoopoga, ae tapunia mo suiga.
  •  le Liskov Suiga Mataupu Faavae (Liskov suitulaga mataupu faavae). O galuega e fa'aogaina ai se ituaiga fa'avae e tatau ona mafai ona fa'aogaina subtypes o le ituaiga fa'avae e aunoa ma le iloaina.
  • le IFa'avae Fa'avae Va'aiga  (faiga faavae tuueseeseina). E le tatau ona fa'alagolago fa'alapotopotoga polokalame i metotia latou te le fa'aogaina.
  • le Dependency Inversion Principle (fa'avae o le fa'alagolago i suiga). Modules i tulaga maualuluga e le tatau ona faalagolago i modules i tulaga maualalo.

Mataupu Faavae o le Tiutetauave Tasi


O le Ta'iala Ta'itasi o Tiutetauave (SRP) o lo'o ta'u mai ai o vasega ta'itasi po'o vaega i totonu o se polokalame e tatau ona nafa ma na'o le tasi le vaega o le fa'atinoga o lena polokalama. E le gata i lea, o elemene o lenei matafaioi e tatau ona atofa atu ia latou lava vasega, nai lo le ta'ape i vasega e le fesootai. Ua faamatalaina e le faievagelia sili o le SRP, Robert S. Martin, le tali atu o le mafuaaga lea o suiga. Na ia muai faatuina lenei faaupuga o se tasi o elemene o lana galuega "Principles of Object-Oriented Design". O le manatu e aofia ai le tele o fesoʻotaʻiga mamanu na faʻamatalaina muamua e Tom DeMarco.

O le manatu na aofia ai foi le tele o manatu na faia e David Parnas. O mea autu e lua o le faʻapipiʻiina ma le natia o faʻamatalaga. Na finau Parnas e faapea o le vaevaeina o se faiga i ni vaega eseese e le tatau ona faavae i luga o auiliiliga o ata poloka po o tafega o faatinoga. So'o se modules e tatau ona i ai se fofo fa'apitoa e maua ai se fa'aitiitiga o fa'amatalaga i tagata fa'atau.

I le ala, na tuʻuina atu e Matini se faʻataʻitaʻiga mataʻina ma pule sinia o se kamupani (COO, CTO, CFO), e faʻaaogaina e i latou taʻitoʻatasi polokalama faʻapitoa pisinisi mo faamoemoega eseese. O le iʻuga, soʻo se tasi oi latou e mafai ona faʻatinoina suiga i le polokalama e aunoa ma le afaina o le fiafia o isi pule.

Faamoemoega paia

E pei lava o taimi uma, o le auala sili e aʻoaʻo ai le SRP o le vaʻai i le gaioiga. Sei o tatou tilotilo i se vaega o le polokalama e LE mulimuli i le Mataupu Faavae o Tiutetauave Tasi. Ole Ruby code lea e fa'amatala ai le amio ma uiga o le avanoa avanoa.

Toe iloilo le faataitaiga ma taumafai e fuafua mea nei:
Matafaioi o na mea o loʻo faʻaalia i le vasega SpaceStation.
O i latou atonu e fiafia i le faagaoioiga o le nofoaga avanoa.

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

O le mea moni, o le matou avanoa avanoa e le lelei (Ou te le manatu o le a ou mauaina se telefoni mai le NASA i se taimi lata mai), ae o loʻo i ai se mea e suʻesuʻe iinei.

O le mea lea, o le SpaceStation vasega e iai ni tiute eseese (po'o galuega). E mafai ona vaevaeina i latou uma i ituaiga:

  • fa'alogo;
  • sapalai (mea fa'aaoga);
  • suauu;
  • fa'avave.

E ui lava e leai se tasi o tagata faigaluega a le ofisa e tofia i se vasega, e faigofie lava ona tatou mafaufau po o ai e nafa ma le a. E foliga mai, e pulea e le saienitisi ia masini, o le logistician e nafa ma le tuʻuina atu o punaoa, o le inisinia e nafa ma sapalai suauu, ma o le pailate e pulea mea faʻamalosi.

E mafai ona tatou fai atu o lenei polokalame e le o tausisia le SRP? Ioe, mautinoa. Ae o le SpaceStation vasega o se "meafaitino atua" masani e iloa mea uma ma faia mea uma. O se fa'ata'ita'iga tele lea e fa'atatau i polokalame fa'atatau. Mo se tagata amata, o ia mea e matua faigata lava ona tausia. E oʻo mai i le taimi nei e matua faigofie lava le polokalame, ioe, ae mafaufau i le mea o le a tupu pe a tatou faʻaopoopoina foliga fou. Atonu o le a manaʻomia e lo tatou nofoaga avanoa se falemaʻi poʻo se potu fono. Ma o le tele o galuega o loʻo i ai, o le tele o SpaceStation o le a tupu. Ia, talu ai o lenei fale o le a fesoʻotaʻi atu i isi, o le tautuaina o le faʻalavelave atoa o le a sili atu ona faigata. O se taunuuga, e mafai ona tatou faʻalavelaveina le faʻaogaina o, mo se faʻataʻitaʻiga, accelerators. Afai e mana'omia e se tagata su'esu'e ni suiga i masini, e ono a'afia ai faiga feso'ota'iga a le nofoaga.

O le solia o le mataupu faavae a le SRP e mafai ona maua ai se manumalo i se taimi pupuu, ae i le faaiuga o le a tatou "toilalo le taua", ma o le a matua faigata lava ona tausia se sauʻai faapena i le lumanaʻi. E sili atu le vaevaeina o le polokalame i ni vaega eseese o le code, o ia mea taʻitasi e nafa ma le faʻatinoina o se gaioiga faʻapitoa. Malamalama i lenei mea, tatou sui le vasega SpaceStation.

Sei o tatou tufatufa atu le matafaioi

I luga na matou faʻamalamalamaina ituaiga faʻagaioʻiga e pulea e le vasega SpaceStation. O le a matou teuina i latou i le mafaufau pe a toe faʻaleleia. O le code fa'afouina e sili atu ona fetaui ma le 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

E tele suiga, e mautinoa lava ua sili atu le lelei o le polokalame i le taimi nei. O le taimi nei ua avea le matou vasega SpaceStation ma se atigipusa e amata ai galuega mo vaega faʻalagolago, e aofia ai se seti o masini, se faiga faʻaaogaina, se tane suauʻu, ma faʻamalosi.

Mo soʻo se fesuiaiga o loʻo i ai nei se vasega tutusa: Sensors; SapalaiUu; FuelTank; Tagata fa'aoso.

E tele suiga taua i lenei lomiga o le code. O le manatu e faapea o galuega a tagata taʻitoʻatasi e le gata o loʻo faʻapipiʻiina i totonu o latou lava vasega, e faʻatulagaina i se auala e mafai ai ona vaʻaia ma tumau. Matou te tu'ufa'atasia elemene e tutusa galuega e mulimuli ai i le mataupu faavae o le felagolagomai. I le taimi nei, afai tatou te manaʻomia le suia o le auala e galue ai le faiga, alu ese mai se fausaga o le hash i se laina, faʻaaoga le vasega SupplyHold; matou te le tau paʻi atu i isi modules. I le auala lea, afai e suia e le ofisa o loʻo faʻaogaina se mea i lana vaega, o le a tumau pea le isi vaega o le ofisa. I lenei tulaga, o le SpaceStation vasega o le a le iloa foi suiga.

O matou tagata ofisa o loʻo galulue i le avanoa avanoa e fiafia i suiga ona e mafai ona latou talosagaina mea latou te manaʻomia. Ia maitauina o lo'o i ai i le code auala e pei o le report_supplies ma le report_fuel o lo'o i totonu o vasega SupplyHold ma FuelTank. O le a le mea e tupu pe a fai e talosaga le Lalolagi e sui le auala e lipotia ai? O vasega uma e lua, SupplyHold ma FuelTank, e tatau ona suia. Ae fa'afefea pe a mana'omia ona sui le auala e avatu ai le suau'u ma mea fa'aaoga? Atonu e tatau ona e toe sui vasega tutusa uma. Ma o lea ua uma ona soli le mataupu faavae SRP. Sei o tatou faaleleia lea.

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.

I lenei lomiga lata mai o le polokalame, ua vaevaeina tiute i ni vasega fou se lua, FuelReporter ma SupplyReporter. O i la’ua uma o le fanau a le vasega Reporter. E le gata i lea, matou te faʻaopoopoina faʻataʻitaʻiga fesuiaiga i le SpaceStation vasega ina ia mafai ona amataina le subclass manaʻomia pe a manaʻomia. Ia, afai e filifili le Lalolagi e sui se isi mea, ona tatou faia lea o suiga i vasega laiti, ae le o le vasega autu.

Ioe, o nisi o a tatou vasega o loo faalagolago pea le tasi i le isi. O le mea lea, o le SupplyReporter mea e faʻalagolago ile SupplyHold, ma FuelReporter faʻalagolago ile FuelTank. O le mea moni, e tatau ona feso'ota'i le fa'aola i le tane suau'u. Ae o mea uma lava ua foliga mai e talafeagai, ma o le faia o suiga o le a le faigata tele - o le faʻasaʻoina o le code o le tasi mea o le a le afaina tele ai le isi.

O lea la, ua matou fatuina se code modular lea e faʻamalamalama saʻo ai matafaioi o mea taʻitasi / vasega. O le galue i sea code e le o se faʻafitauli, o le tausia o se galuega faigofie. Ua matou faaliliuina le "mea paia" atoa i le SRP.

Ua fautuaina e Skillbox:

puna: www.habr.com

Faaopoopo i ai se faamatalaga