Rubutun m code ta amfani da SOLID

Rubutun m code ta amfani da SOLID

Daga mai fassara: buga muku labarin Severin Perez game da amfani da ka'idodin SOLID a cikin shirye-shirye. Bayanin daga labarin zai zama da amfani ga masu farawa da ƙwararrun masu shirye-shirye.

Idan kuna ci gaba, da alama kun ji labarin ƙa'idodin SOLID. Suna baiwa mai tsara shirye-shirye damar rubuta lamba mai tsafta, ingantaccen tsari da sauƙin kiyayewa. Yana da mahimmanci a lura cewa a cikin shirye-shiryen akwai hanyoyi da yawa don yadda ake aiwatar da takamaiman aiki daidai. Kwararru daban-daban suna da ra'ayoyi daban-daban da fahimtar "hanyar madaidaiciya"; duk ya dogara da kwarewar kowane mutum. Koyaya, ra'ayoyin da aka yi shelar a cikin SOLID kusan duk wakilan al'ummar IT sun yarda da su. Sun zama mafari na bullowa da bunƙasa yawancin kyawawan ayyukan gudanarwa na ci gaba.

Bari mu fahimci menene ka'idodin SOLID da yadda suke taimaka mana.

Skillbox yana ba da shawarar: Hakikanin hanya "Mobile Developer PRO".

Muna tunatarwa: ga duk masu karatu na "Habr" - rangwame na 10 rubles lokacin yin rajista a kowane kwas na Skillbox ta amfani da lambar talla "Habr".

Menene SOLID?

Wannan kalmar gajarta ce, kowane harafin kalmar shine farkon sunan ƙayyadaddun ƙa'ida:

  • SƘa'idar Nauyi na ingle. Module na iya samun dalili guda ɗaya kawai na canji.
  • The Oalkalami/Rufe Ka'ida (bude/rufe ka'ida). Ya kamata a buɗe azuzuwan da sauran abubuwa don ƙarawa, amma rufe don gyarawa.
  •  The LKa'idar Sauya Iskov (Ka'idar maye gurbin Liskov). Ayyukan da ke amfani da nau'in tushe yakamata su iya amfani da nau'ikan nau'ikan nau'ikan tushe ba tare da saninsa ba.
  • The IƘa'idar Rarraba Interface  (ka'idar rabuwa ta hanyar sadarwa). Abubuwan software bai kamata su dogara da hanyoyin da basa amfani da su ba.
  • The DƘa'idar Juyar da haƙƙin mallaka (ka'idar juyawar dogaro). Moduloli a manyan matakan bai kamata su dogara da kayayyaki a ƙananan matakan ba.

Ƙa'idar Nauyi ɗaya


Ƙa'idar Nauyi ɗaya (SRP) ta bayyana cewa kowane aji ko tsarin da ke cikin shirin ya kamata ya kasance da alhakin sashi ɗaya kawai na ayyukan wannan shirin. Bugu da ƙari, ya kamata a sanya abubuwan wannan alhakin zuwa nasu ajin, maimakon warwatse a cikin azuzuwan da ba su da alaƙa. Mawallafin SRP kuma babban limamin bishara, Robert S. Martin, ya bayyana lissafin a matsayin dalilin canji. Da farko ya ba da shawarar wannan kalma a matsayin ɗaya daga cikin abubuwan da ke cikin aikinsa "Ka'idodin Ƙira-Oriented Design". Manufar ta ƙunshi yawancin tsarin haɗin kai wanda Tom DeMarco ya ayyana a baya.

Har ila yau, ra'ayin ya ƙunshi ra'ayoyi da yawa waɗanda David Parnas ya tsara. Babban abu biyu shine ɓoyewa da ɓoye bayanai. Parnas ya bayar da hujjar cewa rarraba tsarin zuwa sassa daban-daban bai kamata ya dogara da nazarin zane-zane na toshe ko aiwatar da aiwatarwa ba. Duk wani tsarin dole ne ya ƙunshi takamaiman bayani wanda ke ba da ƙaramin bayani ga abokan ciniki.

Af, Martin ya ba da misali mai ban sha'awa tare da manyan manajoji na kamfani (COO, CTO, CFO), kowannensu yana amfani da takamaiman software na kasuwanci don dalilai daban-daban. A sakamakon haka, kowane ɗayansu na iya aiwatar da canje-canje a cikin software ba tare da shafar bukatun wasu manajoji ba.

Abun Allah

Kamar koyaushe, hanya mafi kyau don koyan SRP shine ganin ta a aikace. Mu kalli wani sashe na shirin wanda baya bin ka'idar Nauyi Daya. Wannan lambar Ruby ce wacce ke bayyana halaye da halayen tashar sararin samaniya.

Bincika misalin kuma gwada gano waɗannan abubuwan:
Nauyin waɗannan abubuwan da aka ayyana a cikin ajin SpaceStation.
Wadanda ke da sha'awar aikin tashar sararin samaniya.

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

A haƙiƙa, tashar sararin samaniyarmu ba ta da aiki (bana jin za a kira ni daga NASA nan ba da jimawa ba), amma akwai abin da za mu bincika anan.

Don haka, ajin SpaceStation yana da nauyi daban-daban (ko ayyuka). Ana iya raba dukkan su zuwa nau'ikan:

  • na'urori masu auna firikwensin;
  • kayayyaki (kayan amfani);
  • man fetur;
  • accelerators.

Duk da cewa babu wani daga cikin ma’aikatan tashar da aka sanya aji, za mu iya tunanin wanene ke da alhakin abin. Mafi mahimmanci, masanin kimiyya yana sarrafa na'urori masu auna firikwensin, mai kula da kayan aiki yana da alhakin samar da albarkatu, injiniyan ne ke da alhakin samar da man fetur, kuma matukin jirgi yana sarrafa abubuwan haɓakawa.

Za mu iya cewa wannan shirin bai dace da SRP ba? Ee, tabbas. Amma ajin SpaceStation wani “abin allah ne” wanda ya san komai kuma yana yin komai. Wannan babban ƙaƙƙarfan tsari ne a cikin shirye-shiryen da ya dace da abu. Don mafari, irin waɗannan abubuwa suna da matukar wahala a kiyaye su. Ya zuwa yanzu shirin yana da sauƙi, a, amma tunanin abin da zai faru idan muka ƙara sababbin abubuwa. Wataƙila tashar mu ta sararin samaniya za ta buƙaci tashar likita ko ɗakin taro. Kuma yawancin ayyuka da ake samu, ƙarin SpaceStation zai girma. To, tunda wannan wurin za a haɗa shi da wasu, yin hidima ga rukunin duka zai zama ma fi rikitarwa. A sakamakon haka, za mu iya rushe aiki na, misali, accelerators. Idan mai bincike ya bukaci canje-canje ga na'urori masu auna firikwensin, wannan zai iya tasiri sosai akan tsarin sadarwar tashar.

Cin zarafin ka'idar SRP na iya ba da nasara na gajeren lokaci na dabara, amma a ƙarshe za mu "rasa yakin", kuma zai zama da wuya a kula da irin wannan dodo a nan gaba. Zai fi kyau a raba shirin zuwa sassa daban-daban na lambar, kowannensu yana da alhakin yin wani aiki na musamman. Fahimtar wannan, bari mu canza ajin SpaceStation.

Mu rarraba alhakin

A sama mun ayyana nau'ikan ayyuka guda huɗu waɗanda ajin SpaceStation ke sarrafawa. Za mu tuna da su a lokacin da refactoring. Lambar da aka sabunta ta fi dacewa da 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

Akwai canje-canje da yawa, tabbas shirin ya fi kyau yanzu. Yanzu ajin SpaceStation ɗin mu ya zama babban akwati wanda a ciki ake ƙaddamar da ayyuka don sassa masu dogaro, gami da saitin na'urori masu auna firikwensin, tsarin samar da kayan abinci, tankin mai, da masu haɓakawa.

Ga kowane ɗayan masu canji yanzu akwai aji mai dacewa: Sensors; Rike Kayan Kaya; Tankin mai; Masu turawa.

Akwai canje-canje masu mahimmanci da yawa a cikin wannan sigar lambar. Ma'anar ita ce, ayyuka na ɗaiɗaikun ba kawai a cikin nasu azuzuwan ba ne, an tsara su ta yadda za su zama abin tsinkaya da daidaito. Muna tara abubuwa masu aiki iri ɗaya don bin ƙa'idar haɗin kai. Yanzu, idan muna buƙatar canza yadda tsarin ke aiki, yana motsawa daga tsarin zanta zuwa tsararru, kawai amfani da ajin SupplyHold; ba lallai ne mu taɓa wasu kayayyaki ba. Ta wannan hanyar, idan jami'in kayan aiki ya canza wani abu a sashinsa, sauran tashar za su ci gaba da kasancewa. A wannan yanayin, ajin SpaceStation ba zai ma san sauye-sauyen ba.

Jami'an mu da ke aiki a tashar sararin samaniya mai yiwuwa suna farin ciki da canje-canjen domin suna iya neman wanda suke bukata. Lura cewa lambar tana da hanyoyi kamar su report_supplies da report_fuel kunshe a cikin azuzuwan SupplyHold da FuelTank. Menene zai faru idan Duniya ta nemi ta canza yadda take ba da rahoto? Duk azuzuwan, SupplyHold da FuelTank, za a buƙaci a canza su. Idan kana buƙatar canza yadda ake isar da man fetur da kayan masarufi fa? Wataƙila za ku sake canza duk azuzuwan iri ɗaya. Kuma wannan ya riga ya saba wa ka'idar SRP. Mu gyara wannan.

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.

A cikin wannan sabon sigar shirin, an raba nauyin da aka rataya zuwa sabbin ajujuwa biyu, FuelReporter da SupplyReporter. Dukkansu ‘ya’yan ‘yan jarida ne. Ƙari ga haka, mun ƙara sauye-sauyen misali zuwa ajin SpaceStation domin a fara fara subclass ɗin da ake so idan ya cancanta. Yanzu, idan Duniya ta yanke shawarar canza wani abu dabam, to, za mu yi canje-canje ga ƙananan azuzuwan, ba ga babban aji ba.

Tabbas, wasu azuzuwan mu har yanzu suna dogara ga juna. Don haka, abu na SupplyReporter ya dogara da SupplyHold, kuma FuelReporter ya dogara da FuelTank. Tabbas, dole ne a haɗa masu haɓakawa zuwa tankin mai. Amma a nan duk abin da ya riga ya yi kama da ma'ana, kuma yin canje-canje ba zai zama da wahala ba musamman - gyara lambar wani abu ba zai shafi wani ba sosai.

Don haka, mun ƙirƙiri wani tsari na zamani inda aka ayyana nauyin kowane abu/ajujuwa daidai. Yin aiki tare da irin wannan lambar ba matsala ba ce, kiyaye shi zai zama aiki mai sauƙi. Mun mai da dukan "abun allahntaka" zuwa SRP.

Skillbox yana ba da shawarar:

source: www.habr.com

Add a comment