Fundamentele AntiPatterns Vizualizări Rails

În această serie de utilizatori începători, ne uităm la AntiPatterns, care - așa cum sugerează și numele - reprezintă aproape opusul modelelor de design. Ele sunt descoperiri de soluții la probleme pe care ar trebui să le eviți.

În acest articol ne vom concentra pe principalul View AntiPattern-PHPitis și vom lucra prin câteva tehnici pentru a vă păstra opinia înclinată și medie. Având tone de cod Ruby în opinia dvs. nu este doar urât, dar de multe ori simplu inutile.

Subiecte

  • Rails Vizualizări
  • PHPitis
  • Extragerea ajutoarelor
  • Ajutoare utile
  • Formulare
  • amprente parțiale
  • Conținut condiționat
  • Semantic Markup

Rails Vizualizări

Rails vine cu ERb (Embedded Ruby) din cutie și cred că nu este necesar să aruncăm motoarele de afișare răcoritoare, cum ar fi Slim, pentru exemplele noastre de acum. Dacă credeți că "convenția peste configurație" se aplică în cea mai mare parte la straturile de model și controler, vă lipsesc pe multe dintre bunele care fac lucrul cu Rails atât de rapid și progresiv. Îngrijirea stratului de vizualizare include nu numai modul în care compuneți marcajele, ci și CSS / Sass, JavaScript, asistenții de vizualizare și șabloanele de aspect. Privită din acest unghi, devine un pic mai adânc decât credeți la început. Numărul mare de tehnologii care pot fi implicate în crearea vederilor dvs. sugerează că ar trebui să se acorde o atenție deosebită păstrării unor lucruri clare, clare și flexibile.

Deoarece modul în care scriem marcajul și stilurile este mult mai puțin constrâns decât modelarea domeniului, doriți să fiți foarte precauți pentru a păstra lucrurile cât mai simple posibil. Întreținerea ar trebui să fie o prioritate numărul unu. Deoarece reproiectările sau iterațiile de proiectare pot fi mai frecvente decât modificările extinse ale stratului dvs. de model, pregătirea pentru schimbare are un sens cu totul nou atunci când vine vorba de stratul dvs. orientat spre utilizator. Sfatul meu: nu construiți neapărat pentru viitor, dar, de asemenea, nu subestimați rata de schimbare - mai ales dacă aveți unul dintre acei "tipi de idei" care știe Jack despre implementări în echipă. Ceea ce îmi place de abordarea lui Rails față de punctele de vedere în MVC este că este tratată la fel de importantă și lecțiile învățate din domeniul modelului au fost încorporate în vedere - ori de câte ori este posibil și util. Alte cadre par să fie de acord, deoarece au integrat multe dintre aceste idei pionierate de Rails.

Din moment ce ultimul articol a fost un pic mai extins, am ales acest subiect ca o mică respirație. Următoarele articole despre controlerele Rails și testele sunt din nou mai mari. Antipaternele pentru opinii nu sunt atât de multe, dar ele sunt totuși la fel de importante. Ne vom concentra pe cea principală, PHPitis, și vom lucra cu ajutorul a două tehnici pentru a vă menține opiniile înclinate și însemnate. Din moment ce vederea este stratul de prezentare, poate ar trebui sa fiti foarte atenti sa nu creati o mizerie periculoasa. Hai să ajungem la asta!

PHPitis

De ce avem în primul rând MVC? Da, deoarece separarea preocupărilor părea a fi cel mai rezonabil lucru de făcut. Sigur, implementările acestei idei variază puțin aici și acolo, însă conceptul general de a avea responsabilități distincte pentru fiecare strat este motivația de bază pentru construirea de aplicații robuste. Având tone de cod în stratul dvs. de vedere, ar putea să nu fie străin dezvoltatorilor care provin din partea PHP a lucrurilor - deși am auzit că cadrele lor au ajuns deja (influențate puternic de lucruri ca Rails?) - dar în Ruby-land aceste lucruri au lung a fost un AntiPattern cu voce tare.

Problemele evidente, cum ar fi amestecarea responsabilităților și duplicarea, se simte pur și simplu urâtă și leneșă - și puțin proastă, pentru a fi sinceră. Sigur, înțeleg, când dezvolți mult într-un cadru, într-un limbaj sau în orice ecosistem, este ușor să devii complicat sau amorțit față de astfel de lucruri. Ceea ce îmi place despre oamenii care împing pe Ruby este că aceste lucruri par a avea o greutate mult mai mică - acesta ar putea fi un motiv pentru care inovarea nu părea a fi o problemă în cadrul comunității. Oricare ar fi cele mai bune lucrări câștigă argumentul și putem merge mai departe.

Deci este o sectiune dedicata miscarii PHP? Deloc! În trecut, aplicațiile PHP aveau reputația de a avea separări slabe între modele, vizualizări și controlori (poate că acesta a fost unul dintre motivele principale pentru care oamenii au simțit că scrierea de aplicații cu Rails era mult mai atrăgătoare). A avea fișiere unice cu cod pentru toate cele trei straturi nu părea sexy. Deci, atunci când suntem în ton de Ruby sau cod de domeniu în punctul nostru de vedere, acesta începe să arate ca un stil de temut PHP de structurare a lucrurilor - PHPitis. Doar câteva lucruri sunt la fel de rele ca aceasta atunci când vine vorba de dezvoltarea de aplicații web, mă simt. Când îți pasă de dezvoltatorii fericiți și de sanatatea ta viitoare, nu înțeleg de ce cineva ar merge pe drumul ăsta - nu este decât o durere înainte, se pare.

Rails oferă o mulțime de bunuri pentru a minimiza codul în vedere cât mai mult posibil. Trebuie să învățați modalitățile de ajutorare, machete și preprocesoare pentru a obține o viziune mai curată. O regulă simplă este păstrarea logicii domeniului din vizualizări - fără comenzi rapide!

Prețul care trebuie plătit pentru a fi leneș în acest sens este greu de supraestimat. Codul Ruby care trebuie să fie prezent în stratul de prezentare trebuie să fie cât mai mic și mai simplu posibil, precum și inteligent organizat. Răsplata dvs. va fi un cod care este o bucurie de extindere și menținere, iar noii membri ai echipei vor avea, de asemenea, un timp mai ușor de a-și împacheta capul în jurul noului codaj. Ca un bonus, designerii ciudați care codifică, de asemenea, nu vor fi supărați și nu vor ascunde alimentele puturoase în salată dacă păstrați tone de cod Ruby din marcajul lor.

Ajutoare utile

Cunoașterea nenumăratelor metode de ajutor în Rails va îmbunătăți semnificativ calitatea stratului de prezentare. Nu numai că va curăța lucrurile și va injecta ocazional creșterea vitezei în productivitate, dar mai important vă ajută să luptați cu PHPitis.

Lucrul pe care ar trebui să-l apreciezi în legătură cu acești ajutoare este că reprezintă reprezentări ale extragerilor din codul obișnuit. În loc să reinventezi roata, atunci când ai dubii, verifică dacă nu există deja un ajutor în jurul care rezolvă problema în vedere - același lucru este valabil și pentru modelele și controlorii, bineînțeles.

Iată o listă de ajutoare pe care ar trebui să le priviți imediat:

  • form_for
  • Alte ajutoare pentru formulare.
  • fields_for
  • LINK_TO
  • content_for
  • Și scrieți-vă foarte bine, bineînțeles.

Formulare

Să aruncăm o privire form_for primul. Știu că formele sunt puțin plictisitoare și nu sexy pentru un subiect, dar vă încurajez foarte mult să le citiți pentru a vă familiariza cu detaliile mai fine. Este important să înțelegeți cum funcționează. Îmi amintesc de multe ori doar căutându-le peste ele fără să le acordăm multă atenție. Sigur, îi puteți face să lucreze destul de ușor, fără a înțelege ce se întâmplă sub capotă. În viitor, mi-ar lua timp să scriu un articol complet despre ei. Între timp, vă recomandăm să vă petreceți puțin timp verificând documentația - cel puțin veți aprecia cât de convenabil îl face Rails să se ocupe de chestii de formă.

Urâtul

Exemplul de mai jos vă arată codul HTML al unei mici forme de care avem nevoie pentru a crea agenți. Acceptă numai trei parametri ca intrări: Nume, număr și licence_to_kill. O mulțime de cod pentru această sarcină mică, de fapt. authenticity_token vine de la Rails - este un lucru de securitate care protejează aplicația de "falsificarea cererii între site-uri".

some.html.erb
 

Scrierea unui formular manual nu este doar lungă, ci și predispusă la erori. De asemenea, dacă am fi abordat-o astfel, ar trebui să rezolvăm problema și cu rutele și clasele variate de CSS care ne-ar putea fi necesare pentru crearea unui obiect nou și pentru actualizarea unui efect existent, ar trebui să duplicăm formulare creați și editați înregistrări. După cum veți vedea în curând, Rails vă întâlnește mai mult de jumătate de vreme. Verdict: cu toate acestea ați pus-o, abordarea manuală este neplăcută și lipsită de confort.

Răul

Am putea merge în jos pe următoarea cale, care nu folosește perfect convențiile în Rails. Cu capul în sus, nu o faci. În principiu, arată că nu gestionați instrumentele disponibile în avantajul dvs. și că duplicați formularul nou și Editați | × acţiuni.

some.html.erb
 <%= form_for :agent, url: agents_path(@agent), html: method: :post do |form_object| %> <%= form_object.label :name %> <%= form_object.text_field :name %> <%= form_object.label :number %> <%= form_object.text_field :number %> <%= form_object.label :licence_to_kill %> <%= form_object.check_box :licence_to_kill %> <%= form_object.submit 'Create New Agent' %> <% end %> 

Ce se întâmplă aici este faptul că constructorul de forme poartă modelul de care aveți nevoie pentru formular.

 <%= form_object.text_field :name %> 

În spatele scenei, linia de mai sus se extinde în următoarele:

 <%= text_field :agent, :name %> 

form_for Metoda ia câteva argumente:

  • un simbol sau un șir pentru specificarea obiectului
  • A URL-ul hașiș
  • un html hașiș
  • A Spațiu de nume hașiș

Hash-ul url este pentru specificarea opțiunilor de rutare. Asta inseamna ca puteti specifica manual calea de rutare pe care o trimiteti, traseele formate fiind la indemana cu aceasta. Acest stil este numit "mod generic" deoarece trebuie să configurați manual form_for apel.

De ce este această soluție suboptimală? Pentru că dorim să păstrăm cât mai mult posibil logica de afaceri din vizualizările și controlorii noștri. Un efect secundar al acestui lucru este că trebuie să schimbăm mai puține părți atunci când este necesar.

HTML
 

În cazul în care ați pierdut-o, această abordare nu ne-a furnizat ID-uri și clase pentru formă etichetă automat. Cei pentru intrare tag-uri, cu toate acestea, au fost generate pentru tine. O vom rezolva într-un minut. Doar știți ce puteți obține gratuit și că probabil că ar trebui să folosiți acest lucru în avantajul dvs. Dacă aveți nevoie de ceva diferit sau de un spațiu de nume suplimentar, puteți utiliza html hash sau Spațiu de nume hash pentru a specifica lucrurile un pic mai mult.

some.html.erb
 <%= form_for :agent, url: agents_path(@agent), html: method: :post, class: 'create_agent', id: 'unique_agent', namespace: 'mi6' do |form_object| %> 
HTML
 

Nu-i rău! Acum formă tag-ul are clasa specificată și id-orice face fluxul sanguin-și intrare etichetele sunt asociate cu MI6. Aproape acolo.

Binele

Aceasta se numește "stil orientat spre resurse" și are cea mai mică cantitate de Ruby pe care trebuie să o scrieți în opiniile dvs. Prin această abordare, dorim să ne bazăm pe identificarea automată a resurselor. Rails evaluează ce rute are nevoie pe baza obiectului propriu-zis. Nu numai că, vă oferă o ieșire HTML diferită pentru a crea un obiect nou sau pentru a edita unul existent. În spatele scenei, Rails doar întreabă obiectul dacă există deja și acționează în consecință.

Crearea de formulare în acest mod este o utilizare inteligentă a convențiilor și ajută la evitarea dublei acțiuni. O linie și toată ridicarea grele se face pentru dvs..

some.html.erb
 <%= form_for @agent do |form_object| %> <%= form_object.label :name %> <%= form_object.text_field :name %> <%= form_object.label :number %> <%= form_object.text_field :number %> <%= form_object.label :licence_to_kill %> <%= form_object.check_box :licence_to_kill %> <%= form_object.submit %> <% end %> 

Mult mai bine, nu-i așa? Acum obținem exact ceea ce avem nevoie atât pentru obiecte existente, cât și pentru noi. De asemenea, nu era necesar să adăugăm textul butonului nostru de trimitere. Rails a avut grijă de acest lucru și se adaptează, de asemenea, obiectelor noi sau existente.

HTML pentru un obiect nou
 
HTML pentru editarea obiectelor
...

Când se editează obiecte, se reflectă și în ieșirea HTML prin adăugarea id-ului la id-ul formei și ruta sau acțiunea necesară pentru actualizarea unui anumit obiect.

Un cuvânt despre magia Rails. Când oamenii susțin exact în aceste situații că Rails este prea magic pentru gustul lor, eu cred că adesea înseamnă că nu au petrecut suficient timp învățând instrumentele comerțului lor. Odată ce ați luat timp pentru a stăpâni aceste instrumente, veți înțelege adesea de ce a fost făcută o simplificare sau o extragere și, de asemenea, acestea apar mult mai sobru și mai direct.

Atenţie!

Exemplele de cod de mai sus utilizate form_object ca parametru bloc. Aceasta nu este recomandată pentru cele mai bune practici, dar a fost făcută pentru a vă reaminti ce reprezintă acest obiect și de la ce provine form_for. Cei mai mulți oameni folosesc doar o câmpie | F | sau | Formular |, care arată mult mai frumos și mai concis.

Apropo, lucrurile ca eticheta, text_field, Caseta de bifat și altele asemănătoare sunt doar metode de ajutor care sunt chemați pe obiectul constructor de forme. Există o tona dintre ele care acoperă aproape orice necesitate posibilă pe care ați putea-o întâmpina.

some.html.erb
 <%= form_for @agent do |f| %> <%= f.label :name %> <%= f.text_field :name %> <%= f.label :number %> <%= f.text_field :number %> <%= f.label :licence_to_kill %> <%= f.check_box :licence_to_kill %> <%= f.submit %> <% end %> 

Concise și citește frumos, corect?

amprente parțiale

Colecțiile sunt un alt lucru pe care nu vrem să fim prea verbale. Redarea partialelor pentru obiectele individuale ale colecțiilor este atât de concisă și simplă - dacă este făcută bine - că mă simt că aveți o mică scuză pentru faptul că nu utilizați convențiile Rails pentru a reduce codul de vizualizare Ruby.

Hai să întoarcem lucrurile cu asta și să începem cu un exemplu care vă arată cum sunteți încurajați să abordați acest lucru. Pe parcurs, îți voi explica și ceea ce poți lăsa și tu.

Binele

app / opinii / agenți / index.html.erb
 <%= render @agents %> 

face metoda este destul de inteligentă. Linia de mai sus este tot ce trebuie să scrieți pentru iterarea unei colecții. Dacă aveți nevoie să modificați ceva în această privință, va fi o schimbare foarte mică - și, prin urmare, o mică cauză de eroare.

Ceea ce se întâmplă aici este că cadrul este capabil să determine ce parte are nevoie. Prin numele obiectului, știe unde să caute parțial - dat fiind faptul că aderă la denumirea convențională a lucrurilor. Felul în care îl văd, acesta este un bun exemplu al modului în care Rails nu încearcă să te impresioneze cu vrăjitoria. Echipa Rails lucrează din greu pentru a vă face viața mai ușoară prin tăierea prin birocrație repetitivă de fel.

app / opinii / agenți / _agent.erb
 

Numele agentului: <%= agent.name %>

Licență pentru a ucide: <%= agent.licence_to_kill %>

Număr: <%= agent.number %>

Jucător: <%= agent.gambler %>

Afemeiat: <%= agent.womanizer %>

Singurul lucru necesar pentru a face această lucrare este să plasați un șablon parțial pe calea potrivită din directorul obiectului și să extrageți atributele de la obiect. Nu este nevoie să scrieți niște bucle pe cont propriu. Este rapid și ușor, la îndemână și pragmatic, aș spune.

Această extragere a fost inițial făcută deoarece numele parțial a fost de cele mai multe ori numele obiectului iterat, oricum, și astfel a fost ușor să creați o convenție care să gestioneze mai eficient această sarcină comună.

Răul

OK, acum că știm cum să ne ocupăm de asta, să vedem ce ai putea și ar trebui să eviți. Exemplul de mai jos este doar o folosire proastă a lui Rails, dar nu o voi numi urâtă de data aceasta.

app / opinii / agenți / index.html.erb
 <% @agents.each do |agent| %> 

Numele agentului: <%= agent.name %>

Licență pentru a ucide: <%= agent.licence_to_kill %>

Număr: <%= agent.number %>

Jucător: <%= agent.gambler %>

Afemeiat: <%= agent.womanizer %>

<% end %>

Ați obținut același rezultat ca mai sus, dar este cu siguranță mai verbose. Repetarea colecției în vizualizare nu mai este necesară. Când utilizați face ca mai sus, parametrul bloc agent este implicit, și îl puteți folosi doar fără fiecare buclă. Asa ca stai departe de cod ca asta - nu te face sa arati foarte bine (dar nimeni nu va aduna capul pentru asta). Este pur și simplu nu este elegant și se adaugă la PHPitis.

Extragerea ajutoarelor

Cea mai evidentă soluție pentru curățarea codului din vizionările dvs. este să evitați scrierea sau să le extrageți inteligent. Să spunem că vrem să amestecăm numele agenților noștri în lista de indexuri. Nu ar trebui să punem acest cod direct în opiniile noastre. Dacă vom decide că modelul nu este, de asemenea, stratul adecvat pentru a plasa acest lucru, atunci un ajutor particularizat în app / ajutoare directorul ar putea fi alegerea potrivită.

app / ajutoare / agents_helper.rb
 Modul AgentsCharge Def Defend (agent) agent.name.split (") shuffle.join end end 

Prin ambalarea acestui lucru într-un modul din directorul helpers, acum avem acces la această metodă în vederile noastre. Vă rugăm să oferiți ajutoare specifice propriei lor case și să nu puneți totul pe cont propriu ApplicationHelper (app / ajutoare / application_helper.rb), care este cu adevărat destinată unor chestii mai "globale".

Acum pot să-l acces pe micul ăsta în șablonul meu parțial - sau orice vizualizare - pentru a-mi face colecția de agenți.

app / opinii / agenți / _agent.erb
 

Numele agentului: <%= scramble(agent) %>

Licență pentru a ucide: <%= agent.licence_to_kill %>

Număr: <%= agent.number %>

Jucător: <%= agent.gambler %>

Afemeiat : <%= agent.womanizer %>

Ajutoarele dvs. personalizate sunt o modalitate foarte bună de a vă păstra opinia curată și sănătoasă. Și așa cum ați văzut, este atât de rapid și ușor încât există scuză puțin să fie prea leneș și să nu le extrageți pentru lupta cu PHPitis.

Conținut condiționat

Metoda ajutorului content_for este un instrument util pentru extragerea de conținut care nu se potrivește cu adevărat facturii pentru o parte, dar are nevoie de un pic de încapsulare. Este o modalitate de a stoca un pic de marcaj pe care îl puteți aplica pe bază de pagină pe pagină - îl dați în aspect dacă este necesar. În dimensiune, ar trebui să fie mult mai mică decât partiale sau chiar layouts.

Această tehnică vă poate salva, de asemenea, pasul de a crea propria metodă pentru aceasta. Meniurile navigabile sau barele laterale sunt adesea exemple în care acest ajutor devine util. Să presupunem că doriți să aveți un loc în meniul dvs., care este doar pentru administratori, dar nu aveți nevoie să ajustați întregul aspect. Sau aveți pagini în care nu este nevoie de bara laterală. Cu content_for, injectați ceea ce aveți nevoie atunci când aveți nevoie de el pe o pagină pe pagină. Dublarea nu mai este!

app / opinii / agenți / index.html.erb
 <% content_for :double_o_navbar do %> 
  • <%= link_to 'Operations', operations_path %>
  • <%= link_to 'Agents', agents_path %>
  • <%= link_to 'Messages', messages_path %>
  • <% end %> <%= render @agents %>
    app / opinii / machete / application.html.erb
    ...   
    • <%= link_to 'Home', root_path %>
    • <%= link_to 'About', '#' %>
    • <%= yield :double_o_navbar %>
    <%= yield %>

    În afară de faptul că asta antet este un candidat bun pentru extracție într-o parțială, uita-te la randament: double_o_navbar secțiune. Aceasta este o regiune productivă care introduce codul de la content_for bloc. Acesta va introduce doar codul dacă numele de simbol se potrivesc. Aici dorim ca doar agenții dubli să aibă acces la anumite linkuri din navbar. Toată lumea vede doar Acasă și Despre. Gândiți-vă la legăturile speciale pe care un administrator trebuie să le vadă că niciodată nu ar trebui să facă față unei interfețe publice.

    De asemenea, puteți utiliza acest ajutor pentru inserare id sau clasă atributele pentru etichetele HTML, dacă este necesar. Din când în când, acest lucru vine la îndemână.

    O altă utilizare obișnuită este popularea </code> a unei pagini dinamic cu a <code>content_for</code> bloc.</p> <h6>app / opinii / machete / application.html.erb</h6> <pre> <title> Spectru - <%= yield(:title).presence || "Default" %>

    some.html.erb
     <% content_for :title do %> Un titlu funky <% end %> 

    Pur și simplu plasați titlul dorit într-o content_for bloc și aspectul aplicației o va insera pentru dvs. Poți să fii mai inteligent cu el, dar asta ar fi suficient pentru moment. Dacă nu aveți nevoie de un titlu sau să uitați să adăugați unul, atunci logicul || va lovi cu piciorul și va da randamentul dvs. la alegere. În exemplul de mai sus, trebuie să verificăm prezența unui titlu sau implicit nu va funcționa.

    Ceea ce cu siguranță nu vrei să faci este să creezi variabile de instanță pentru acest gen de lucruri. Responsabilități unice, amintiți-vă?

     def show @title = "Unele titluri de pagină" 

    Un lucru mai mult: puteți să întrebați dacă paginile au a content_for bloc.

    app / opinii / machete / application.html.erb
     <% if content_for?(:q_navbar) %> <%= yield :q_navbar %> <% end %> 

    Acest lucru vă poate ajuta să evitați marcarea duplicat care este relevantă pentru a modela o pagină care se adaptează dacă elementele sunt prezente pe o pagină sau nu.

    Semantic Markup

    Acestea sunt lucruri pe care cu siguranță doriți să le evitați.

    Marcajul de mai sus este din documentația de bootstrap și specifică modul în care coloanele ar trebui să "arate" - informații care nu au semnificație semantică și aparțin, de fapt, în foile de stil. Asta e designerul de lucruri despre care au coșmaruri.

    Deci, care-i treaba cu asta? Acest lucru este important deoarece, pe lângă denumirile discutabile ale claselor, se încalcă marcajul nesemantic separarea preocupărilor. Marcajul dvs. nu ar trebui să fie deranjat de informații despre stil; în schimb, ambii ar trebui să stea singuri și să vă ajute schimbați stilurile fără efort-fără a atinge codul HTML. Nu este la fel de dificilă cum s-ar părea la început. Este nevoie de un pic de disciplină, totuși.

    Când sunteți în stare să păstrați aceste informații de styling din marcajul dvs., ați redus efectiv PHPitis pe un alt front - pentru designeri unul esențial! De asemenea, utilizarea generic divs fără un înțeles inerent este un alt exemplu de marcare slabă. HTML5 vă oferă o mulțime de elemente utile care transmit mai multe informații viitoarei dvs. auto, altor dezvoltatori și motoarelor de căutare. Namingul este presupus greu, dar HTML5 vă oferă multe elemente semantice care fac opțiunile dvs. mult mai ușoare în această privință.

    Gândurile finale

    Sper că ați văzut că Rails Views nu au nevoie de multă dragoste pentru a străluci. Dezvoltatorii pot fi un snobby cu privire la stratul frontal. Confruntarea cu marcarea uneori pare a fi puțin sub ele - scrierea HTML, DUH! Ei bine, nu ar trebui să arunc nici un fel de pietre, dar am ajuns să apreciez un strat de prezentare bine reglat și bine gândit. Este mult mai distractiv să lucrați și, atunci când faceți bine, mult mai repede, pentru a face schimbările inevitabile. Parsingul de tone de cod Ruby amestecat cu marcaj grav scrise nu este o experiență distractivă în cartea mea.

    Cod