Kulemba khodi yosinthika pogwiritsa ntchito SOLID

Kulemba khodi yosinthika pogwiritsa ntchito SOLID

Kuchokera kwa womasulira: zosindikizidwa kwa inu wolemba Severin Perez za kugwiritsa ntchito mfundo za SOLID pamapulogalamu. Zomwe zili m'nkhaniyi zidzakhala zothandiza kwa oyamba kumene komanso odziwa mapulogalamu.

Ngati muli pachitukuko, mwina mudamvapo za mfundo za SOLID. Amathandizira wopanga mapulogalamu kuti alembe ma code oyera, opangidwa bwino komanso osungika mosavuta. Ndikoyenera kudziwa kuti pamapulogalamu pali njira zingapo zochitira bwino ntchito inayake. Akatswiri osiyanasiyana ali ndi malingaliro osiyanasiyana komanso kumvetsetsa kwa "njira yolondola"; zonse zimatengera zomwe munthu aliyense wakumana nazo. Komabe, malingaliro omwe amalengezedwa mu SOLID amavomerezedwa ndi pafupifupi onse oimira gulu la IT. Zinakhala chiyambi cha kuwonekera ndi chitukuko cha machitidwe ambiri abwino oyendetsera chitukuko.

Tiyeni timvetsetse kuti mfundo za SOLID ndi chiyani komanso momwe zimatithandizira.

Skillbox imalimbikitsa: Njira yothandiza "Mobile Developer PRO".

Tikukukumbutsani: kwa owerenga onse a Habr - kuchotsera ma ruble 10 polembetsa maphunziro aliwonse a Skillbox pogwiritsa ntchito nambala yotsatsira ya Habr.

Kodi SOLID ndi chiyani?

Mawuwa ndi chidule, chilembo chilichonse cha mawuwa ndi chiyambi cha dzina la mfundo inayake:

  • SMfundo Yofunika Kwambiri. Module ikhoza kukhala ndi chifukwa chimodzi chokha chosinthira.
  • The Ocholembera/Mfundo Yotseka (mfundo yotseguka/yotseka). Makalasi ndi zinthu zina ziyenera kutsegulidwa kuti ziwonjezedwe, koma zotsekedwa kuti zisinthidwe.
  • β€ŠThe Liskov Substitution Principle (Liskov m'malo mfundo). Ntchito zomwe zimagwiritsa ntchito mtundu woyambira ziyenera kugwiritsa ntchito ma subtypes amtundu woyambira popanda kudziwa.
  • The IMfundo Yolekanitsa Chiyankhuloβ€Š (mfundo yolekanitsa mawonekedwe). Mabungwe apulogalamu sayenera kudalira njira zomwe sagwiritsa ntchito.
  • The DEpendency Inversion Principle (mfundo ya kudalira inversion). Ma module apamwamba sayenera kudalira ma modules otsika kwambiri.

Mfundo ya Udindo Umodzi

β€Š
Mfundo ya Single Responsibility Principle (SRP) imanena kuti kalasi iliyonse kapena gawo lililonse mu pulogalamu liyenera kukhala ndi gawo limodzi lokha la magwiridwe antchito a pulogalamuyi. Kuphatikiza apo, zinthu zaudindozi ziyenera kuperekedwa kwa kalasi yawo, m'malo momwazika m'makalasi osagwirizana. Woyambitsa SRP ndi mlaliki wamkulu, Robert S. Martin, akufotokoza kuyankha ngati chifukwa cha kusintha. Poyambirira adapereka mawuwa ngati chimodzi mwazinthu zantchito yake "Mfundo Zopangira Zinthu Zogwirizana ndi Zinthu". Lingaliroli limaphatikizapo njira zambiri zolumikizirana zomwe zidafotokozedwa kale ndi Tom DeMarco.

Lingaliroli linaphatikizaponso malingaliro angapo opangidwa ndi David Parnas. Ziwiri zazikuluzikulu ndikubisa ndi kubisala chidziwitso. Parnas adanena kuti kugawa dongosolo kukhala magawo osiyana sikuyenera kutengera kusanthula kwazithunzi za block kapena mayendedwe akupha. Ma module aliwonse ayenera kukhala ndi yankho lapadera lomwe limapereka chidziwitso chochepa kwa makasitomala.

Mwa njira, Martin anapereka chitsanzo chochititsa chidwi ndi oyang'anira akuluakulu a kampani (COO, CTO, CFO), omwe aliyense amagwiritsa ntchito mapulogalamu apadera a bizinesi pazinthu zosiyanasiyana. Chotsatira chake, aliyense wa iwo akhoza kukhazikitsa kusintha kwa mapulogalamu popanda kukhudza zofuna za oyang'anira ena.

Chinthu chaumulungu

Monga nthawi zonse, njira yabwino yophunzirira SRP ndikuyiwona ikugwira ntchito. Tiyeni tiwone gawo la pulogalamuyi lomwe silimatsatira Mfundo ya Udindo Umodzi. Iyi ndi kachidindo ka Ruby yomwe imafotokoza machitidwe ndi mawonekedwe a malo okwerera mlengalenga.

Onaninso chitsanzocho ndipo yesani kudziwa zotsatirazi:
Udindo wa zinthu zomwe zalengezedwa mu kalasi ya SpaceStation.
Amene angakhale ndi chidwi ndi ntchito ya malo okwerera mlengalenga.

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

M'malo mwake, malo athu apamlengalenga sakugwira ntchito (sindikuganiza kuti ndilandila foni kuchokera ku NASA posachedwa), koma pali china choti muwunike apa.

Chifukwa chake, kalasi ya SpaceStation ili ndi maudindo angapo (kapena ntchito). Onse a iwo akhoza kugawidwa mu mitundu:

  • masensa;
  • zinthu (zowonjezera);
  • mafuta;
  • ma accelerator.

Ngakhale palibe wogwira ntchito pasiteshoniyo amapatsidwa kalasi, titha kuganiza kuti ndani ali ndi udindo pa chiyani. Nthawi zambiri, wasayansi amawongolera masensa, woyang'anira mayendedwe ndi omwe ali ndi udindo wopereka zinthu, injiniya ndi amene amayang'anira mafuta, ndipo woyendetsa ndegeyo amawongolera zowonjezera.

Kodi tinganene kuti pulogalamuyi sikugwirizana ndi SRP? Inde, zedi. Koma kalasi ya SpaceStation ndi "chinthu chamulungu" chomwe chimadziwa zonse ndikuchita chilichonse. Ichi ndi chotsutsana chachikulu pakupanga mapulogalamu opangidwa ndi zinthu. Kwa oyamba kumene, zinthu zoterezi zimakhala zovuta kwambiri kuzisamalira. Pakadali pano pulogalamuyi ndi yophweka, inde, koma taganizirani zomwe zidzachitike ngati tiwonjezera zatsopano. Mwina malo athu apamlengalenga adzafuna malo azachipatala kapena chipinda chochitira misonkhano. Ndipo ntchito zikachuluka, SpaceStation imakula. Chabwino, popeza malowa adzalumikizidwa ndi ena, kugwiritsa ntchito zovuta zonse kumakhala kovuta kwambiri. Zotsatira zake, tikhoza kusokoneza ntchito, mwachitsanzo, ma accelerator. Ngati wofufuza apempha kusintha kwa masensa, izi zitha kukhudza kwambiri njira zoyankhulirana za station.

Kuphwanya mfundo ya SRP kungapereke chigonjetso chachifupi, koma pamapeto pake "tidzataya nkhondo", ndipo zidzakhala zovuta kwambiri kusunga chilombo choterocho m'tsogolomu. Ndi bwino kugawa pulogalamuyo m'magawo osiyana a code, yomwe ili ndi udindo wochita ntchito inayake. Pomvetsetsa izi, tiyeni tisinthe kalasi ya SpaceStation.

Tiyeni tigawane udindo

Pamwambapa tafotokoza mitundu inayi ya ntchito zomwe zimayendetsedwa ndi gulu la SpaceStation. Tidzawakumbukira pamene refactoring. Khodi yosinthidwa imagwirizana bwino ndi 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

Pali zosintha zambiri, pulogalamuyo ikuwoneka bwino tsopano. Tsopano kalasi yathu ya SpaceStation yakhala ngati chidebe chomwe chimayambira magawo odalira, kuphatikiza ma sensa, makina ogwiritsira ntchito, tanki yamafuta, ndi zowonjezera.

Pazosintha zilizonse pano pali gulu lofananira: Zomverera; SupplyHold; Mafuta a Tank; Othandizira.

Pali zosintha zingapo zofunika mu mtundu uwu wa code. Mfundo ndi yakuti ntchito zapayekha sizimangophatikizidwa m'makalasi awo okha, zimakonzedwa m'njira yoti zidziwike bwino komanso zogwirizana. Timagawa zinthu zomwe zili ndi ntchito zofanana kuti titsatire mfundo yogwirizana. Tsopano, ngati tikufuna kusintha momwe dongosolo limagwirira ntchito, kusuntha kuchokera ku hashi kupita ku gulu, ingogwiritsani ntchito gulu la SupplyHold; sitiyenera kukhudza ma module ena. Mwanjira iyi, ngati woyang'anira mayendedwe asintha china chake m'gawo lake, malo ena onsewo azikhalabe. Pankhaniyi, gulu la SpaceStation silidziwa ngakhale kusintha.

Akuluakulu athu ogwira ntchito pamalo okwerera mlengalenga mwina ali okondwa ndi zosinthazi chifukwa amatha kupempha zomwe akufuna. Zindikirani kuti code ili ndi njira monga report_supplies ndi report_fuel zomwe zili m'makalasi a SupplyHold ndi FuelTank. Kodi chingachitike n’chiyani ngati Dziko Lapansi likanati lisinthe mmene limanenera? Makalasi onsewa, SupplyHold ndi FuelTank, adzafunika kusinthidwa. Nanga bwanji ngati mukufuna kusintha momwe mafuta ndi zinthu zina zimaperekera? Muyenera kusintha makalasi onse omwewo kachiwiri. Ndipo izi ndizophwanya kale mfundo ya SRP. Tiyeni tikonze izi.

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.

Mu pulogalamu yaposachedwa iyi, maudindowa adagawidwa m'magulu awiri atsopano, FuelReporter ndi SupplyReporter. Onse ndi ana a kalasi ya Reporter. Kuphatikiza apo, tidawonjeza zosinthika ku kalasi ya SpaceStation kuti gawo lomwe mukufuna likhazikitsidwe ngati kuli kofunikira. Tsopano, ngati Dziko Lapansi lisankha kusintha china chake, ndiye kuti tidzasintha ku subclasses, osati ku kalasi yayikulu.

Inde, ena mwa makalasi athu amadalirabe wina ndi mnzake. Chifukwa chake, chinthu cha SupplyReporter chimadalira SupplyHold, ndipo FuelReporter imadalira FuelTank. Zachidziwikire, zowonjezera ziyenera kulumikizidwa ndi thanki yamafuta. Koma apa zonse zikuwoneka zomveka, ndipo kusintha sikudzakhala kovuta kwambiri - kusintha ndondomeko ya chinthu chimodzi sikudzakhudza kwambiri wina.

Chifukwa chake, tapanga code yokhazikika pomwe maudindo a chinthu chilichonse/makalasi amafotokozedwa ndendende. Kugwira ntchito ndi code yotere si vuto, kusunga izo kudzakhala ntchito yosavuta. Tasintha "chinthu chaumulungu" chonse kukhala SRP.

Skillbox imalimbikitsa:

Source: www.habr.com

Kuwonjezera ndemanga