socialgekon.com
  • Главни
  • Уређивање
  • Укс Дизајн
  • Наука О Подацима И Базе Података
  • Дизајн Процес
Бацк-Енд

Изградите елегантне шинске компоненте са обичним старим рубин објектима

Ваша веб локација се креће напред, а ви брзо растете. Руби / Раилс је ваша најбоља опција за програмирање. Ваш тим је већи и већ сте напустили концепт „дебели модели, танки покретачи“ ( дебели модели, мршави контролори ) као стил дизајна за ваше Раилс апликације. Међутим, и даље не желите да престанете да користите Раилс.

Нема проблема. Данас ћемо разговарати о томе како користити најбоље праксе из ООП-а како бисте свој код учинили чишћим, изолованијим и одвојенијим.

Да ли је вредно рефакторизирати вашу апликацију?

За почетак, размотрите како бисте требали одлучити да ли је ваша апликација добар кандидат за рефакторирање.



Ево листе показатеља и питања која си обично постављам да бих утврдио да ли мојим кодовима треба рефакторирање или не.

  • Спори тест јединице. ПОРО јединице за тестирање обично раде брзо, са добро изолованим кодовима, тако да споро тестирање често може бити показатељ лошег дизајна или прекомерне одговорности.
  • ФАТ модели или контролери. Модел или контролер са више од 200 линије кода ( МЕСТО ) генерално је добар кандидат за рефакторирање.
  • Прекомерно дугачка база кода. Ако имате ЕРБ / ХТМЛ / ХАМЛ са више од 30.000 МЕСТО или Руби изворни код (без ГЕМс ) са више од 50.000 МЕСТО , постоји велика шанса да ћете морати да преправите.

Покушајте да употребите овако нешто да бисте сазнали колико редака Руби изворног кода имате:

find app -iname '*.rb' -type f -exec cat {} ;| wc -l

Ова наредба ће претражити све датотеке са наставком .рб (руби датотеке) у директоријуму / апп, а затим одштампати број редова. Имајте на уму да је овај број само процена, јер ће редови коментара бити укључени у овај укупан број.

Друга тачнија и информативнија опција је коришћење задатка грабље stats Раилс, који излаже брзи сажетак линија кода, броја класа, броја метода, односа метода према класама и односа линија кода по методи:

*bundle exec rake stats* +----------------------+-------+-----+-------+---------+-----+-------+ | Nombre | Líneas | LOC | Clase | Método | M/C | LOC/M | +----------------------+-------+-----+-------+---------+-----+-------+ | Controladores | 195 | 153 | 6 | 18 | 3 | 6 | | Helpers | 14 | 13 | 0 | 2 | 0 | 4 | | Modelos | 120 | 84 | 5 | 12 | 2 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 45 | 12 | 0 | 3 | 0 | 2 | | Bibliotecas | 0 | 0 | 0 | 0 | 0 | 0 | | Controlador specs | 106 | 75 | 0 | 0 | 0 | 0 | | Helper specs | 15 | 4 | 0 | 0 | 0 | 0 | | Modelo specs | 238 | 182 | 0 | 0 | 0 | 0 | | Petición specs | 699 | 489 | 0 | 14 | 0 | 32 | | Routing specs | 35 | 26 | 0 | 0 | 0 | 0 | | Vista specs | 5 | 4 | 0 | 0 | 0 | 0 | +----------------------+-------+-----+-------+---------+-----+-------+ | Total | 1472 |1042 | 11 | 49 | 4 | 19 | +----------------------+-------+-----+-------+---------+-----+-------+ Código LOC: 262 Prueba LOC: 780 Ratio Código a Prueba: 1:3.0
  • Могу ли да издвојим понављајуће обрасце у својој бази кода?

Одвајање на делу

Почнимо са примером из стварног живота.

Претпоставимо да желимо да напишемо апликацију која прати време за људе који трче; На главној страници корисник може видети унесена времена.

Сваки од уноса времена садржи датум, удаљеност, трајање и додатне релевантне информације о статусу (нпр. Време, тип терена итд.) И просечну брзину која се може израчунати када је потребно.

Потребан нам је извештај који показује просечну брзину и удаљеност недељно. Ако је просечна брзина на улазу већа од укупне просечне брзине, обавестићемо корисника путем СМС-а (за овај пример ћемо користити Некмо РЕСТфул АПИ за слање СМС-а).

Главна страница ће вам омогућити да одаберете удаљеност, датум и време на којем трчите како бисте направили унос сличан овом:

Такође имамо estadísticas страницу, која је у основи недељни извештај који укључује просечну пређену брзину и удаљеност недељно.

  • Узорак можете видети на мрежи овде .

Код

Структура директоријума aplicación изгледа слично овоме:

⇒ tree . ├── assets │ └── ... ├── controllers │ ├── application_controller.rb │ ├── entries_controller.rb │ └── statistics_controller.rb ├── helpers │ ├── application_helper.rb │ ├── entries_helper.rb │ └── statistics_helper.rb ├── mailers ├── models │ ├── entry.rb │ └── user.rb └── views ├── devise │ └── ... ├── entries │ ├── _entry.html.erb │ ├── _form.html.erb │ └── index.html.erb ├── layouts │ └── application.html.erb └── statistics └── index.html.erb

Нећу расправљати о моделу Usuario јер није ништа необично, јер га користимо са Мото за спровођење аутентификације.

Што се тиче Entrada модела, он садржи пословну логику за нашу апликацију.

Сваки Entrada припада а Usuario.

Проверавамо присуство следећих атрибута за сваки улаз distancia, períodode_tiempo, fecha_hora и estatus.

Сваки пут када креирамо унос, упоређујемо просечну брзину корисника са просеком свих корисника у систему и обавештавамо корисника путем СМС-а, користећи Некмо (Нећемо разговарати о томе како се користи Некмо библиотека, иако сам желео да демонстрирам случај када користимо спољну библиотеку).

  • Узорак суштине

Имајте на уму да Entrada модел садржи више од саме пословне логике. Такође обрађује неке валидације и позиве.

Тхе entries_controller.rb има акције Сурово главни (иако без ажурирања). EntriesController#index добија уносе за тренутног корисника и сортира записе по датуму креирања, док EntriesController#create креирајте нови унос. Нема потребе да расправљамо о очигледном или одговорностима EntriesController#destroy :

  • Узорак суштине

Док је statistics_controller.rb одговоран је за израчунавање недељног извештаја, StatisticsController#index добија улазе за пријављеног корисника и групише их по недељама, користећи #group_by која је у разреду Бројне у Раилс. Затим покушајте да украсите резултате неким приватним методама.

  • Узорак суштине

Овде не расправљамо много о ставовима јер изворни код сам по себи објашњава.

Испод је приказ листе уноса за пријављеног корисника (index.html.erb). Ово је образац који ће се користити за приказ резултата радње индекса (методе) у обрађивачу уноса:

  • Узорак суштине

Имајте на уму да користимо render @entries Учесници, да делимо код делимично _entry.html.erb тако да можемо задржати свој код СУВ и за вишекратну употребу:

  • Узорак суштине

Исто се односи и на _forma делимично. Уместо да користимо исти код са (новим и измењеним) радњама, креирамо делимични образац за вишекратну употребу:

  • Узорак суштине

Што се тиче изгледа странице недељног извештаја, statistics/index.html.erb приказује неке статистике и извештава о недељним активностима корисника груписањем неких уноса:

  • Узорак суштине

И коначно, помоћник за улазе, entries_helper.rb, укључује два помагачи readable_time_period и readable_speed што би требало олакшати читање атрибута:

  • Узорак суштине

За сада ништа превише компликовано.

Већина вас може тврдити да је рефакторирање ово против принципа КИСС и то ће систем учинити сложенијим.

Дакле, да ли ову апликацију заиста треба реконструисати?

Апсолутно не , али ми ћемо га узети у обзир само у сврху узорковања.

На крају, ако погледате следећи одељак и карактеристике које указују на то да је апликацији потребан рефакторинг, постаће очигледно да апликација у нашем примеру није ваљани кандидат за рефакторирање.

Круг живота

Почнимо са објашњавањем структурног обрасца МВЦ у Раилс.

Обично започиње претраживачем подношењем захтева попут https://www.toptal.com/jogging/show/1.

Веб сервер прима захтев и користи rutas да дефинише шта controlador употреба.

Контролори обављају посао анализе захтева корисника, испоруке података, колачића, сесија итд., А затим траже modelo добити податке.

Тхе modelos Они су Руби класе које разговарају са базом података, спремају и потврђују податке, извршавају пословну логику и раде тешко. Прикази су оно што корисник може видети: ХТМЛ, ЦСС, КСМЛ, Јавасцрипт, ЈСОН.

Ако желимо да прикажемо редослед захтева за животни циклус програма Раилс, то би изгледало овако:

Шине раздвајају животни циклус МВЦ

Оно што желим да постигнем је да додам више апстракције, користећи ПОРО-ове и направим образац сличним следећем, за акције create/update

Шема шина креира облик

И нешто слично овоме за акције list/show :

Упит за списак шина шина

Додавањем ПОРО апстракција осигуравамо потпуно раздвајање одговорности СИЦКЛЕ , нешто што Раилс не савлада у потпуности.

Смернице

Да бих постигао нови дизајн, послужићу се смерницама у наставку, али имајте на уму да то нису правила која морате поштовати до краја. Сматрајте их флексибилним смерницама које олакшавају рефакторирање.

  • АцтивеРецорд модели могу садржати асоцијације и константе, али ништа друго. То значи да неће бити позива (користите услужне објекте и тамо додајте позиве) и неће бити валидације (усе Обликујте објекте да би се укључила имена и валидације за модел).

  • Држите контролере као танке слојеве и увек позивајте сервисне објекте. Неки од вас се можда питају зашто користити контролере ако желимо да наставимо да позивамо сервисне објекте да садрже логику? Па, контролори су добро место за њихово коришћење усмеравање ХТТП, рашчлањивање параметара, аутентификација, преговарање о садржају, позивање исправне услуге или објекта уређивача, хватање изузетака, форматирање одговора и враћање исправног статуса ХТТП кода.

  • Услуге треба да позивају објекте Упит , и не чувају стање. Користите методе класе које нису класе. Мора да се сачува врло мало јавних метода СИЦКЛЕ .
  • Упити треба правити са предметима упит . Објектне методе Упит мора вратити предмет, а хасх или низ , али не и АцтивеРецорд асоцијација.

  • Избегавајте употребу Помагачи , боље користити декоратере. Зашто? Честа потешкоћа са помагачи у Раилс-у је да се они могу претворити у гомилу ОО , који деле име простора и међусобно се преклапају. Али много је горе, чињеница да се ниједан полиморфизам не може користити са помагачи Шине - пружањем различитих примена за различите контексте или типове, и заобилажењем или пот класификацијом помагача. Мислим да врсте помоћник у шинама би се углавном требало користити за корисне методе, а не за посебне случајеве употребе; како форматирати атрибуте модела за било коју логику презентације. Нека буду лагане и лако их је пратити. Боље декоратори / делегати. ** Зашто? Напокон, чини се да су бриге део шина и могу се осушити ( Исушити ) код који се дели између више модела. Међутим, већи је проблем што забринутост не чини предмет модела кохезивнијим. Само је код боље организован. Другим речима, нема стварне промене у АПИ-ју модела.

  • Покушајте да извучете Драгоцени предмети модела да би ваш код био чистији и да бисте повезали његове атрибуте.

  • Увек проследите променљиву инстанце за сваки приказ.

Рефацторизар

Пре него што почнем, желим да разговарам о нечем другом. Када започне рефакторирање, обично се на крају запитате: „Да ли је то добра рефакторизација?“

Ако се осећате као да правите више раздвајања или изолације између одговорности (чак и ако то значи додавање још кода и нових датотека), онда је ово добра ствар. На крају, одвајање апликације је врло добра пракса и олакшава нам обављање одговарајућег јединственог теста.

Нећу расправљати о стварима, попут пребацивања логике са контролера на моделе, јер претпостављам да то радите и да вам је угодно да користите Раилс (обично Скинни Цонтроллер и ФАТ модел).

Да би овај чланак био сажет, нећу расправљати о тестирању, али то не значи да не бисте требали тестирати.

Напротив, требало би увек почните са тестом како би били сигурни да ствари иду добро, пре него што кренете напред. Ово је нешто потребан, посебно када се ради рефакторирање.

Тада можемо применити промене и осигурати да тестови прођу кроз одговарајуће делове кода.

Издвоји драгоцености

Прво, шта је предмет вредности?

Мартин Фовлер Објасните:

Објект вредности је мали објекат, као што је новац или предметни опсег. Њихова кључна карактеристика је да следе вредносну семантику, а не референтну семантику.

Понекад се можете наћи у ситуацији када концепт заслужује своју апстракцију и где се његова једнакост не заснива на вредностима, већ на идентитету. Примери за то могу бити: Руби-ов датум, УРИ и име путање. Издвајање драгоценог објекта (или модела домена) велика је погодност.

Зашто гњавити?

Једна од великих предности вредносног објекта је што помажу у постизању изражајности вашег кода. Ваш код ће бити јаснији или барем може бити ако имате добру праксу именовања. С обзиром да је Валуе Објецт апстракција, то доводи до јаснијих кодова и мање грешака.

Још један добитак је непроменљивост . Непроменљивост предмета је веома важна. Када складиштимо одређене скупове података, који се могу користити у вредносном објекту, обично не волим податке којима се манипулише.

Када је ово корисно?

На ово питање нема савршеног одговора. Радите оно што је у вашем најбољем интересу и оно што има највише смисла у датој ситуацији.

Поред овога, постоје неке смернице које ми помажу да донесем одлуку.

Ако мислите да је група метода повезана, па, са драгоценостима је скупља. Ова експресивност значи да вредносни објекат треба да представља препознатљив скуп података, који ваш просечни програмер може закључити само гледањем имена објекта.

Како се то ради?

Вредности треба да следе одређена правила:

  • Вредности би требало да имају више атрибута.
  • Атрибути би требало да буду непроменљиви током читавог животног циклуса предмета.
  • Једнакост се одређује својствима предмета.

У нашем примеру, креираћу вредносни објекат EntryStatus, да апстрахујем атрибуте Entry#status_weather и Entry#status_landform својој класи, која изгледа овако:

  • Узорак суштине

Напомена: Ово је само ПОРО (обичан стари руби објекат), не наслеђује се из ActiveRecord::Base. Дефинисали смо методе читача за наше атрибуте и додељујемо их приликом покретања. Такође, користимо упоредиву комбинацију за подударање објеката помоћу методе ().

Можемо модификовати модел Entry да користимо објект вредности који смо креирали:

  • Узорак суштине

Такође можемо изменити методу EntryController#create да сходно томе употребимо нови објект вредности:

  • Узорак суштине

Издвоји услужне објекте

Шта је услужни објекат?

Посао услужног објекта је задржавање кода током одређеног простора пословне логике. За разлику од стила 'Дебели модел' , где мали број објеката садржи много, много метода, за сву потребну логику, коришћење услужних објеката резултира у многим класама, од којих свака има јединствену сврху.

Зашто? Које су предности?

  • Искидати. Услужни објекти помажу вам да постигнете већу изолацију између објеката.

  • Видљивост. Објекти услуге (ако су правилно именовани) показују шта апликација ради. Могу да погледам директоријум услуга да видим које могућности нека апликација пружа.

  • Чисти модели и управљачки програми. Контролери се укључују на захтев ( парамс , сессион, цоокиес) у аргументима их прослеђује сервису и преусмерава или оставља у зависности од одговора услуге. Док се модели баве само удруживањем и упорношћу. Издвајање кода из контролера / модела у сервисне објекте би подржало СИЦКЛЕ и то би даље одвојило код. Одговорност модела требала би се бавити само асоцијацијама и спремати / брисати записе, док би објект Услуга имао само једну одговорност ( СИЦКЛЕ ). То доводи до бољег дизајна и бољих тест јединица.
  • СУВ и Прихватите промену. Услужне предмете држим што једноставнијим и мањим. Компонујем сервисне објекте са другим услужним објектима и поново их користим.

  • Очистите и убрзајте свој тестни пакет. Услуге се брзо и лако тестирају, јер су то мали Руби објекти са улазном тачком (метода која се назива). Сложене услуге се састоје од других услуга, тако да можете лако раздвојити тестове. Такође, коришћење услужних објеката олакшава преузимање повезаних објеката без потребе за учитавањем читавог окружења шина.

  • Откупљиво са било ког места. Услужни објекти ће се сигурно позивати из контролера, као и из услужних објеката, ДелаиедЈоб / Ресцуе / Сидекик Јобс, Раке задаци, конзола итд.

С друге стране, ништа није савршено. Један недостатак Услужних објеката је тај што могу бити претерани за сваку малу радњу. У тим случајевима можете на крају компликовати и не поједноставити свој код.

Када треба издвојити услужне објекте?

Ни овде не постоји фиксно правило.

Типично су услужни објекти најбољи за средње до велике системе: оне са пристојном количином логике, изван стандардних ЦРУД операција.

Дакле, када мислите да комад кода не припада директоријуму, на месту где сте га намеравали додати, било би добро да га преиспитате и видите да ли би било боље да иде на услужни објекат.

Ево неколико упута када треба користити услужне објекте:

  • Акција је сложена.
  • Акција досеже више модела.
  • Акција је у интеракцији са спољном услугом.
  • Акција није примарна брига подвученог модела.
  • Постоји више начина за извођење акције.

Како треба да дизајнирате услужне објекте?

Дизајнирање класе за услужни објекат релативно је једноставно, јер вам није потребно драгуље не би требало да учите а ДЛС нова, али можете се, мање или више, ослонити на вештине дизајнирања софтвера које већ поседујете.

Обично користим следеће смернице и конвенције за дизајн објекта услуге:

  • Не чувајте стање предмета.
  • Користите методе инстанце, а не методе класе.
  • Требало би бити врло мало јавних метода (по могућности оних који подржавају * СИЦКЛЕ .
  • Методе треба да врате обогаћене, а не логичке резултате објекта.
  • Услуге иду под директоријум app/services . Саветујем вам да користите поддиректоријуме за јаке домене пословне логике. На пример, датотека app/services/report/generate_weekly.rb дефинисаће Report::GenerateWeekly док app/services/report/publish_monthly.rb дефинисаће Report::PublishMonthly.
  • Услуге почињу глаголом (и не завршавају се услугом): ApproveTransaction, SendTestNewsletter, ImportUsersFromCsv.
  • Службе одговарају на позвани метод. Открио сам да га употреба другог глагола чини мало сувишним: АппровеТрансацтион.аппрове () не чита добро. Такође, позвана метода је де фацто метода ламбда , процс , и објекти метода.

Ако погледате StatisticsController#index, приметићете групу метода (weeks_to_date_from, weeks_to_date_to, avg_distance, итд.) Груписане у контролер. То није добро. Размотрите последице ако желите да генеришете недељни извештај изван statistics_controller.

У нашем случају ћемо створити Report::GenerateWeekly и извуците логички извештај из StatisticsController:

  • Узорак суштине

Дакле StatisticsController#index сада изгледа чистије:

  • Узорак суштине

Применом обрасца објекта Сервице, ми групишемо код око сложене и специфичне акције и промовишемо стварање мањих и јаснијих метода.

Домаћи задатак: размислите о коришћењу Вредан објекат за WeeklyReport уместо Struct .

Издвој објекте Упит Контролери

Шта је објекат Упит ?

Објекат Упит је ПОРЕ, који представља базу података упита. Може се поново користити на различитим местима у апликацији, истовремено скривајући логику упита. Такође пружа добру изоловану јединицу за испитивање.

Требали бисте извући сложене СКЛ / НоСКЛ упите у њихове властите класе.

Сваки објекат Упит одговоран је за враћање скупа резултата на основу критеријума / правила пословања.

У овом примеру немамо упит ( упит ) сложен, па користи објект Упит не би било ефикасно. Међутим, у сврху демонстрације, издвојићемо упит у Report::GenerateWeekly#call и ми ћемо створити generate_entries_query.rb:

  • Узорак суштине

А у Report::GenerateWeekly#call заменимо:

def call @user.entries.group_by(&:week).map do |week, entries| WeeklyReport.new( ... ) end end

са:

def call weekly_grouped_entries = GroupEntriesQuery.new(@user).call weekly_grouped_entries.map do |week, entries| WeeklyReport.new( ... ) end end

Узорак предмета упит (упит) помаже да логика вашег модела буде строго повезана са понашањем класе, а да истовремено контролори остану мршави. Јер они нису ништа друго до обичне старе класе Руби , предмети упит не требају насљеђивати од ActiveRecord::Base и не би требали бити одговорни за ништа осим за извршавање упита.

Исечак Створи унос у услужни објекат

Сада ћемо извући логику стварања новог уноса у нови објект услуге. Искористимо конвенцију и креирајмо CreateEntry:

  • Узорак суштине

А сада наш EntriesController#create је као што следи:

def create begin CreateEntry.new(current_user, entry_params).call flash[:notice] = 'Entry was successfully created.' rescue Exception => e flash[:error] = e.message end redirect_to root_path end

Више потврда за облик објекта

Сад ствари постају занимљивије.

Запамтите да смо се у нашим смерницама сложили да желимо да модели имају асоцијације и константе, али ништа друго (без валидације или позива). Па кренимо уклањањем додатних описа и уместо тога користимо облик Схапе.

Објект Схапе је ПОРО (обичан стари рубин објекат). Преузмите команду над објектом контролера / услуге када требате разговарати с базом података.

Зашто користити Схапе објекте?

Када требате да рефакторизујете своју апликацију, увек је добро имати на уму, главну појединачну одговорност ( СИЦКЛЕ ).

СИЦКЛЕ помаже вам у доношењу бољих дизајнерских одлука у погледу одговорности коју треба да има час.

На пример, модел табеле базе података (модел АцтивеРецорд у контексту програма Раилс) представља јединствени запис базе података у коду, тако да нема разлога да се бринете о било чему што ваш корисник ради.

Овде долази објект Схапе.

Објект Схапе одговоран је за представљање облика у вашој апликацији. Дакле, свако поље за унос може се третирати као атрибут у класи. Можете проверити да ли ти атрибути испуњавају нека правила за проверу ваљаности и можете проследити „чисте“ податке тамо где треба (нпр. Модел базе података или можда ваш креатор претраживања упита).

Када треба да користите објект Схапе?

  • Када желите да издвојите валидације из Раилс модела.
  • Када се више модела може ажурирати једним начином испоруке, требали бисте створити објект Облик.

То вам омогућава да на једно место ставите сву логику облика (конвенције именовања, валидације и друго).

Како створити Схапе објект?

  • Направите једноставну класу Руби.
  • Укључује ActiveModel::Model (У Раилс 3, уместо тога, морате да укључите Име, Конверзију и Валидацију).
  • Почните да користите своју нову класу облика, као да је то уобичајени модел АцтивеРецорд, где је највећа разлика у томе што не можете да наставите са подацима ускладиштеним у овом објекту.

Имајте на уму да можете да користите драгуљ реформа , али настављајући са ПОРО, створићемо entry_form.rb што изгледа овако:

  • Узорак суштине

И ми ћемо изменити CreateEntry за почетак коришћења објекта Формат EntryForm:

class CreateEntry ...... ...... def call @entry_form = ::EntryForm.new(@params) if @entry_form.valid? .... else .... end end end

Белешка: Неки од вас ће рећи да није потребно приступити објекту Схапе из објекта Сервице и да објект Схапе можемо позвати директно из контролера, што је ваљан аргумент. Међутим, радије бих имао јасан ток, зато увек зовем Схапе објект из Сервице објекта.

Преместите позиве на објекат услуге.

Као што смо се раније договорили, не желимо да наши модели садрже потврде и позиве. Издвојили смо валидације помоћу Схапе објеката. Али и даље користимо неке позиве (after_create у моделу Entry compare_speed_and_notify_user).

Зашто желимо да уклонимо додатне описе са модела?

Раилс Девелоперс обично почну да примећују бол током позива, током тестова. Ако не тестирате своје АцтивеРецорд моделе, бол ћете почети примећивати касније, како ваша апликација расте и што је више логике потребно за позивање или избегавање позива.

después_* позиви се користе првенствено у односу на чување или наставак са објектом.

Једном када је објекат сачуван, сврха објекта (нпр. Одговорност) је испуњена. Дакле, ако и даље видимо да се позивају позиви, након што је објекат сачуван, то су вероватно позиви који желе да изађу из подручја одговорности објекта и тада наилазимо на проблеме.

У нашем случају, кориснику шаљемо СМС који није повезан са улазном доменом.

Једноставан начин за решавање проблема је премештање позива у повезани услужни објекат. На крају крајева, слање СМС-а одговарајућем кориснику повезано је са Услужним објектом CreateEntry а не модел Ентри, као такав.

Радећи ово, више не морамо да искључујемо, compare_speed_and_notify_user у нашим тестовима. Ово смо учинили једноставним, створили смо унос без потребе за слањем СМС-а и пратимо добар објектно оријентисан дизајн, водећи рачуна да наши часови имају јединствену одговорност СИЦКЛЕ ).

Дакле, сада CreateEntry то је нешто слично овоме:

  • Узорак суштине

Уместо помагача користите декоратере

Иако колекцију можемо лако користити Драпер модела и декоратера, остајем при ПОРО-у за овај чланак, као и до сада.

Оно што ми треба је класа која позива методе на украшеном објекту.

Могу да користим method_missing да то имплементирам, али користићу стандардну Руби библиотеку, SimpleDelegator. Следећи код показује како се користи SimpleDelegator да имплементирамо наш основни декоратор:

% app/decorators/base_decorator.rb require 'delegate' class BaseDecorator

Зашто метода _h

Овај метод делује као прокси за контекст приказа. Подразумевано је контекст приказа инстанца класе погледа, која је ActionView::Base. Можете приступити помагачи погледа на следећи начин:

_h.content_tag :div, 'my-div', class: 'my-class'

Да би било погодније додајемо метод decorado а ApplicationHelper:

module ApplicationHelper # ..... def decorate(object, klass = nil) klass ||= '#{object.class}Decorator'.constantize decorator = klass.new(object, self) yield decorator if block_given? decorator end # ..... end

Сада можемо да померимо помагачи EntriesHelper декоратерима:

# app/decorators/entry_decorator.rb class EntryDecorator

И можемо користити readable_time_period и readable_speed као што следи:

# app/views/entries/_entry.html.erb - + - +

Структура након рефакторирања

Завршили смо са више датотека, али то није нужно лоше (и запамтите ово, од почетка смо били свесни да је овај пример у демонстрацијске сврхе и не је нужно био добар случај за рефакторирање):

app ├── assets │ └── ... ├── controllers │ ├── application_controller.rb │ ├── entries_controller.rb │ └── statistics_controller.rb ├── decorators │ ├── base_decorator.rb │ └── entry_decorator.rb ├── forms │ └── entry_form.rb ├── helpers │ └── application_helper.rb ├── mailers ├── models │ ├── entry.rb │ ├── entry_status.rb │ └── user.rb ├── queries │ └── group_entries_query.rb ├── services │ ├── create_entry.rb │ └── report │ └── generate_weekly.rb └── views ├── devise │ └── .. ├── entries │ ├── _entry.html.erb │ ├── _form.html.erb │ └── index.html.erb ├── layouts │ └── application.html.erb └── statistics └── index.html.erb

закључак

Иако се у овом посту на блогу фокусирамо на Раилс, РоР (Руби он Раилс) није зависност од услужних објеката или других ПОРО-ова. Овај приступ можете користити са било којим фрамеворк веб , апликација за мобилне уређаје или конзоле.

Када користиш МВЦ Као архитектура, све се држи и успорава јер већина промена утиче на друге делове апликације. Такође вас приморава да размислите где да ставите неку пословну логику - да ли то треба да иде у модел, контролер или поглед?

Користећи једноставан ПОРО, пребацили смо пословну логику на моделе или услуге који се не наслеђују из ActiveRecord, што је већ добитак, а да не помињемо да имамо јаснији код који подржава СИЦКЛЕ и бржи јединични тестови.

Чиста архитектура покушава да постави оквире за употребу у средиште / врх ваше структуре тако да можете лако видети шта ваша апликација ради. Такође олакшава усвајање промена, јер је више модуларна и изолована. Надам се да сам показао како треба Обични стари рубинасти објекти и више апстракција, раздваја бриге, поједностављује тестирање и помаже у стварању чистог и одрживог кода.

Повезан: Које су предности Руби он Раилс? После две деценије програмирања. Користите шине

Супер једноставан водич за иконографију

Уи Десигн

Супер једноставан водич за иконографију
Аутоматски ажурирајте еластични стог помоћу Ансибле Плаибоокс

Аутоматски ажурирајте еластични стог помоћу Ансибле Плаибоокс

Технологија

Популар Постс
Зашто се више предузетника одлучује за изградњу фондова за претрагу преко стартупа
Зашто се више предузетника одлучује за изградњу фондова за претрагу преко стартупа
Послови које треба обавити: Претворите потребе купаца у решења за производе
Послови које треба обавити: Претворите потребе купаца у решења за производе
Свет је наше сучеље - еволуција дизајна корисничког интерфејса
Свет је наше сучеље - еволуција дизајна корисничког интерфејса
Контекст свесне апликације и сложена архитектура обраде догађаја
Контекст свесне апликације и сложена архитектура обраде догађаја
Уметност фотографије цвећа: 15 савета за више уметничких резултата
Уметност фотографије цвећа: 15 савета за више уметничких резултата
 
Истински повраћај улагања у УКС: Студије случаја редизајнирања Б2Б
Истински повраћај улагања у УКС: Студије случаја редизајнирања Б2Б
Најузбудљивија класа имовине у приватном капиталу? Претражите средства из перспективе инвеститора
Најузбудљивија класа имовине у приватном капиталу? Претражите средства из перспективе инвеститора
Уобичајене грешке у комуникацији са купцима: Како не фрустрирати купца
Уобичајене грешке у комуникацији са купцима: Како не фрустрирати купца
Како спојити на ТикТок-у и дозволити другима да спајају ваше видео записе
Како спојити на ТикТок-у и дозволити другима да спајају ваше видео записе
Процена професионалне франшизе у спорту
Процена професионалне франшизе у спорту
Категорије
Људи И ТимовиОкретанПланирање И ПредвиђањеАгиле ТалентНачин ЖивотаИнвеститори И ФинансирањеИнжењерски МенаџментКпи И АналитикаМобилеПуцање

© 2023 | Сва Права Задржана

socialgekon.com