A’ sgrìobhadh còd sùbailte a’ cleachdadh SOLID

A’ sgrìobhadh còd sùbailte a’ cleachdadh SOLID

Bhon eadar-theangair: air fhoillseachadh dhuibh artaigil le Severin Perez mu bhith a’ cleachdadh phrionnsapalan SOLID ann am prògramadh. Bidh am fiosrachadh bhon artaigil feumail do luchd-tòiseachaidh agus luchd-prògramaidh eòlach.

Ma tha thu ann an leasachadh, tha e glè choltach gun cuala tu mu phrionnsapalan SOLID. Leigidh iad leis a’ phrògramadair còd glan, le deagh structar agus furasta a chumail suas a sgrìobhadh. Is fhiach a bhith mothachail gu bheil grunn dhòighean ann air mar a nì thu obair shònraichte gu ceart ann am prògramadh. Tha diofar bheachdan agus tuigse aig diofar eòlaichean air an “slighe cheart”; tha e uile an urra ri eòlas gach neach. Ach, tha cha mhòr a h-uile riochdaire bhon choimhearsnachd IT a’ gabhail ris na beachdan a chaidh ainmeachadh ann an SOLID. Thàinig iad gu bhith mar thoiseach tòiseachaidh agus leasachadh air mòran deagh chleachdaidhean stiùireadh leasachaidh.

Tuigidh sinn dè na prionnsapalan SOLID agus mar a tha iad gar cuideachadh.

Tha Skillbox a’ moladh: Cùrsa practaigeach "Mobile Developer PRO".

Tha sinn a ’cur nar cuimhne: airson a h-uile leughadair de "Habr" - lasachadh de 10 rubles nuair a chlàraicheas tu ann an cùrsa sam bith Skillbox a 'cleachdadh a' chòd adhartachaidh "Habr".

Dè th' ann an SOLID?

Tha an teirm seo na ghiorrachadh, tha gach litir den teirm mar thoiseach ainm prionnsapal sònraichte:

  • Single Prionnsabal Uallach. Faodaidh aon adhbhar agus dĂŹreach aon adhbhar a bhith aig modal airson atharrachadh.
  • Tha Opeann/Prionnsabal DĂšinte (prionnsabal fosgailte / dĂšinte). Bu chòir clasaichean agus eileamaidean eile a bhith fosgailte airson leudachadh, ach dĂšinte airson atharrachadh.
  •  Tha Liskov Prionnsapal ionadachaidh (prionnsabal ionadachaidh Liskov). Bu chòir gum biodh comas aig gnĂŹomhan a chleachdas seòrsa bun-stèidh subtypes den t-seòrsa bunaiteach a chleachdadh gun fhios a bhith aca.
  • Tha IPrionnsabal dealachaidh eadar-aghaidh  (prionnsabal dealachaidh eadar-aghaidh). Cha bu chòir do bhuidhnean bathar-bog a bhith an urra ri dòighean nach bi iad a’ cleachdadh.
  • Tha Dpendency Inversion Prionnsapal (prionnsabal tionndadh eisimeileachd). Cha bu chòir modalan aig ĂŹrean nas Ă irde a bhith an urra ri modalan aig ĂŹrean nas ĂŹsle.

Prionnsabal Uallach Singilte

 
Tha am Prionnsabal Dleastanas Singilte (SRP) ag ràdh gum bu chòir do gach clas no modal ann am prògram a bhith cunntachail airson dìreach aon phàirt de ghnìomhachd a’ phrògraim sin. A bharrachd air an sin, bu chòir eileamaidean den uallach seo a bhith air an sònrachadh don chlas aca fhèin, seach a bhith sgapte thairis air clasaichean gun cheangal. Tha leasaiche SRP agus prìomh shoisgeulaiche, Raibeart S. Màrtainn, a 'toirt cunntas air cunntachalachd mar an adhbhar airson atharrachadh. Mhol e an teirm seo an toiseach mar aon de na h-eileamaidean den obair aige "Principles of Object-Oriented Design". Tha am bun-bheachd a’ toirt a-steach mòran den phàtran ceangail a chaidh a mhìneachadh roimhe le Tom DeMarco.

Bha a’ bhun-bheachd cuideachd a’ toirt a-steach grunn bhun-bheachdan a chruthaich Daibhidh Parnas. Is e an dà phrìomh fhear cruinneachadh agus falach fiosrachaidh. Bha Parnas ag argamaid nach bu chòir siostam a roinn ann am modalan fa leth a bhith stèidhichte air mion-sgrùdadh air blocaichean diagraman no sruthan cur gu bàs. Feumaidh fuasgladh sònraichte a bhith ann an gin de na modalan a bheir seachad beagan fiosrachaidh do luchd-dèiligidh.

Air an t-slighe, thug Màrtainn eisimpleir inntinneach le àrd-mhanaidsearan companaidh (COO, CTO, CFO), agus bidh gach fear dhiubh a 'cleachdadh bathar-bog gnìomhachais sònraichte airson diofar adhbharan. Mar thoradh air an sin, faodaidh gin dhiubh atharrachaidhean sa bhathar-bog a chuir an gnìomh gun a bhith a’ toirt buaidh air ùidhean mhanaidsearan eile.

nĂŹ dhiadhaidh

Mar as àbhaist, is e an dòigh as fheàrr air SRP ionnsachadh a bhith ga fhaicinn ann an gnìomh. Bheir sinn sùil air earrann den phrògram NACH EIL a’ leantainn a’ Phrionnsabail Uallach Singilte. Is e seo còd Ruby a tha a’ toirt cunntas air giùlan agus feartan an stèisein fhànais.

Dèan lèirmheas air an eisimpleir agus feuch ris na leanas a dhearbhadh:
Dleastanasan nan nithean sin a tha air an ainmeachadh sa chlas SpaceStation.
An fheadhainn a dh 'fhaodadh Úidh a bhith aca ann an obrachadh an stèisein fhànais.

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

Gu fìrinneach, tha an stèisean fànais againn mì-ghnìomhach (chan eil mi a ’smaoineachadh gum faigh mi fios bho NASA uair sam bith a dh’ aithghearr), ach tha rudeigin ri sgrùdadh an seo.

Mar sin, tha grunn dhleastanasan (no gnìomhan) eadar-dhealaichte aig a’ chlas SpaceStation. Faodar iad uile a roinn ann an seòrsachan:

  • mothachairean;
  • stuthan (stuthan);
  • connadh;
  • luathaichean.

Eadhon ged nach eil clas air a thoirt do neach-obrach an stèisein, is urrainn dhuinn gu furasta smaoineachadh cò air a bheil uallach airson dè. Nas coltaiche, bidh smachd aig an neach-saidheans air na mothachairean, tha uallach air an neach-logaidh airson goireasan a thoirt seachad, tha uallach air an innleadair airson solar connaidh, agus bidh am pìleat a ’cumail smachd air na boosters.

An urrainn dhuinn a ràdh nach eil am prògram seo a’ gèilleadh ri SRP? Seadh, cinnteach. Ach tha an clas SpaceStation na “rud dia” àbhaisteach aig a bheil eòlas air a h-uile càil agus a nì a h-uile càil. Tha seo na phrìomh fhrith-phàtran ann am prògramadh a tha ag amas air nithean. Airson neach-tòiseachaidh, tha na stuthan sin gu math duilich a chumail suas. Gu ruige seo tha am prògram gu math sìmplidh, tha, ach smaoinich air dè a thachras ma chuireas sinn feartan ùra ris. Is dòcha gum feum an stèisean fànais againn stèisean meidigeach no seòmar coinneimh. Agus mar as motha de ghnìomhan a th’ ann, is ann as motha a dh’ fhàsas SpaceStation. Uill, leis gum bi an goireas seo ceangailte ri feadhainn eile, bidh e eadhon nas duilghe seirbheis a thoirt don togalach gu lèir. Mar thoradh air an sin, is urrainn dhuinn casg a chuir air gnìomhachd, mar eisimpleir, luathadairean. Ma dh’ iarras neach-rannsachaidh atharraichean air na mothachairean, dh’ fhaodadh seo buaidh mhòr a thoirt air siostaman conaltraidh an stèisein.

Le bhith a’ briseadh prionnsapal an SRP dh’ fhaodadh buaidh innleachdach geàrr-ùine a thoirt seachad, ach aig a’ cheann thall caillidh sinn “an cogadh”, agus bidh e gu math duilich a leithid de uilebheist a chumail san àm ri teachd. Tha e nas fheàrr am prògram a roinn ann an earrannan fa leth de chòd, agus tha uallach air gach fear dhiubh airson gnìomhachd sònraichte a dhèanamh. Le seo a thuigsinn, atharraichidh sinn an clas SpaceStation.

Sgaoilidh sinn uallach

Gu h-àrd mhÏnich sinn ceithir seòrsaichean obrachaidhean a tha fo smachd clas SpaceStation. Cumaidh sinn cuimhne orra nuair a bhios sinn ag ath-bheachdachadh. Tha an còd Úraichte nas fheàrr a rèir an 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

Tha tòrr atharrachaidhean ann, tha am prògram gu cinnteach a’ coimhead nas fheàrr a-nis. A-nis tha an clas SpaceStation againn air fàs nas motha de shoitheach anns a bheil gnìomhachd air a thòiseachadh airson pàirtean eisimeileach, a’ toirt a-steach seata de luchd-mothachaidh, siostam solarachaidh a ghabhas ithe, tanca connaidh, agus boosters.

Airson gin de na caochladairean tha a-nis clas co-fhreagarrach: Sensors; SupplyHold; Tanca connaidh; Trusgan.

Tha grunn atharrachaidhean cudromach anns an dreach seo den chòd. Is e a’ phuing gu bheil gnìomhan fa leth chan ann a-mhàin air an gabhail a-steach anns na clasaichean aca fhèin, ach gu bheil iad air an eagrachadh ann an dòigh a dh’ fhàsas dùil agus cunbhalach. Bidh sinn a’ cruinneachadh eileamaidean le comas-gnìomh coltach ri chèile gus prionnsapal co-leanailteachd a leantainn. A-nis, ma dh’ fheumas sinn an dòigh anns a bheil an siostam ag obair atharrachadh, a’ gluasad bho structar hash gu raon, dìreach cleachd an clas SupplyHold; chan fheum sinn suathadh air modalan eile. San dòigh seo, ma dh’ atharraicheas an t-oifigear logistics rudeigin san roinn aige, bidh an còrr den stèisean fhathast slàn. Anns a 'chùis seo, cha bhi an clas SpaceStation eadhon mothachail air na h-atharrachaidhean.

Is dòcha gu bheil na h-oifigearan againn a tha ag obair air an stèisean fànais toilichte leis na h-atharrachaidhean oir faodaidh iad an fheadhainn a tha a dhìth orra iarraidh. Mothaich gu bheil dòighean anns a’ chòd leithid report_supplies agus report_fuel anns na clasaichean SupplyHold agus FuelTank. Dè thachradh nan iarradh an Talamh an dòigh anns a bheil e ag aithris atharrachadh? Bidh feum air an dà chlas, SupplyHold agus FuelTank, atharrachadh. Dè ma dh’ fheumas tu an dòigh anns a bheil connadh agus stuthan consum air an lìbhrigeadh atharrachadh? Is dòcha gum feum thu na h-aon chlasaichean atharrachadh a-rithist. Agus tha seo mar-thà na bhriseadh air prionnsapal SRP. Feuch an cuir sinn seo ceart.

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.

Anns an dreach as ùire seo den phrògram, chaidh na dleastanasan a roinn ann an dà chlas ùr, FuelReporter agus SupplyReporter. Tha iad le chèile nan clann den chlas Neach-aithris. A bharrachd air an sin, chuir sinn caochladairean eisimpleir ris a’ chlas SpaceStation gus an gabh an fho-chlas a tha thu ag iarraidh a thòiseachadh ma tha sin riatanach. A-nis, ma cho-dhùnas an Talamh rudeigin eile atharrachadh, nì sinn atharrachaidhean air na fo-chlasaichean, agus chan ann air a’ phrìomh chlas.

Gun teagamh, tha cuid de na clasaichean againn fhathast an urra ri chèile. Mar sin, tha an nÏ SupplyReporter an urra ri SupplyHold, agus tha FuelReporter an urra ri FuelTank. Gu dearbh, feumaidh na boosters a bhith ceangailte ris an tanca connaidh. Ach an seo tha a h-uile dad mar-thà a 'coimhead loidsigeach, agus cha bhith e gu sònraichte doirbh atharrachaidhean a dhèanamh - cha toir deasachadh còd aon nÏ buaidh mhòr air fear eile.

Mar sin, tha sinn air còd modular a chruthachadh far a bheil dleastanasan gach nì / clas air am mìneachadh gu mionaideach. Chan eil e na dhuilgheadas a bhith ag obair le còd mar sin, bidh e na obair shìmplidh a chumail suas. Tha sinn air an “rud diadhaidh” gu lèir a thionndadh gu SRP.

Tha Skillbox a’ moladh:

Source: www.habr.com

Ceannaich aoigheachd earbsach airson làraich le dìon DDoS, frithealaichean VPS VDS 🔥 Ceannaich aoigheachd làrach-lìn earbsach le dìon DDoS, frithealaichean VPS VDS | ProHoster