Din ce în ce mai des, aud de la dezvoltatori și citesc în articole că nimeni nu are nevoie de modele de design (aka modele de design). Ei spun că au apărut în timpul „înfloririi” sistemelor UML, RUP, CASE și a altor instrumente, abordări și practici prea „complexe”. Și acum cel mai important lucru este să scrieți cod de lucru și rapid. Nimeni nu are timp pentru cărți inteligente și groase, cu excepția unui interviu. Pentru cei care doresc să discute acest subiect, vă rugăm să mergeți la cat.
Când eram la universitate, am fost învățați modele de design ca parte a unuia dintre cursurile noastre. La acea vreme, mi s-au părut ceva ca un cal sferic în vid, pentru că nu aveam experiență practică în folosirea lor (acesta era al treilea sau începutul celui de-al patrulea an, acum mulți ani). De asemenea, a fost destul de dificil să ne amintim care dintre ele era care, ca să nu mai vorbim de subtilități și detalii. Cu toate acestea, întrebările despre modelele de design au fost puse fără greș în fiecare interviu de angajare. Candidații au fost nevoiți să-și umfle obrajii și să demonstreze cât de cool sunt diversele șabloane (în special Singleton), văzându-le în viață cel mult o dată sau de două ori pe paginile cărților.
Dar nu oamenii proști au venit cu modele de design:
Nu are rost să continuăm cronicile istorice. Aceasta a fost prima carte din care generația noastră și-a luat cunoștințele despre modelele de design și a încercat să le aplice în munca lor. Este considerat un clasic al subiectului și trebuie citit.
După ceva timp de muncă, am început să observ că mă ajută chiar și cunoștințele teoretice despre modelele de design înțelege codul altcuiva mult mai repede. Și acest lucru este deosebit de important la începutul carierei tale, când trebuie să te aprofundezi în proiecte existente fără experiență de lucru. De exemplu, când am întâlnit o clasă cu sufixul Builder, am înțeles că a fost adăugată pentru a simplifica și izola logica construcției obiectelor complexe. Am găsit imediat cu ușurință cum să-l folosesc și să îl aplic în codul meu. Reprezentanții șablonului Singleton au fost împrăștiați peste tot, a fost atât de ușor să greșiți când le inițializați fără a cunoaște regulile de aplicare. În codul cu care am lucrat, Fațadă, Vizitator, Lanț de responsabilitate, Iterator, Adaptor, Decorator, Proxy, Strategie, Metoda șablon și alte modele de design populare au fost abundente.
Mi-am dat seama cât de mult timp economisesc aplicând slabele mele cunoștințe de carte despre modelele de design și chiar am început să-i respect pe autorii lor în inima mea. Mi-a fost ușor nu numai să înțeleg codul altor oameni, ci și să-l extind cu propriile mele soluții, precum și să adaug altele noi.
Timpul a trecut... M-am obișnuit rapid cu utilizarea pe scară largă a modelelor de design și mi-a devenit dificil să lucrez fără ele. Am început să înțeleg de ce candidații sunt întrebați despre ei în timpul interviurilor (desigur, dacă nu doar „pentru spectacol”). Aici nici măcar nu vorbim despre utilizarea obligatorie a modelelor de design, ci despre simplificarea comunicării între dezvoltatori. Și acesta este procesul care ocupă un loc cheie în dezvoltare - discuția despre arhitectura și designul unei soluții specifice la o problemă.
Primul parametru important este timpul petrecut discutând și luând decizii(Sper că aveți mai mult de un arhitect senior senior global de produse software care ia decizii). Imaginează-ți cât de greu ar fi să explici rapid cuiva că trebuie să implementezi un Decorator: „trebuie să facem o clasă căreia îi trecem în constructor o instanță a unei alte implementări a aceleiași interfețe și care să adauge logică apelului. dintre aceste metode fără a-și schimba comportamentul de bază..” Dar încă mai sunt o mulțime de lucruri mărunte și nuanțe rămase în culise. Și asta pentru un mic detaliu al designului tău, dintre care în majoritatea soluțiilor există zeci, sau chiar sute. Nici măcar nu atingem modele arhitecturale complexe și serioase.
Folosind exemplul cu Decorator, este ușor de înțeles al doilea parametru important - aceeași înțelegere a designului rezolvarea problemei în mintea tuturor membrilor echipei. Dacă formularea este vagă, toată lumea poate înțelege soluția diferit, iar aceasta este plină de probleme. La urma urmei, implementarea poate diferi foarte mult de ideea în discuție. Și acest lucru va duce la timp suplimentar pentru revizuirea și reluarea codului.
Al treilea parametru important este înțelegerea instrumentelor și bibliotecilor terțe.În prezent, aproape fiecare proiect utilizează multe soluții de la terți. Pentru a le folosi corect și a nu călca pe grebla, arhitectul și dezvoltatorul trebuie să înțeleagă cum funcționează lucrurile. Și pentru aceasta, sunt folosite șabloane binecunoscute, care sunt concepute pentru a simplifica foarte mult înțelegerea și a compara cu soluții alternative.
În viață, folosim în mod activ exemple pentru a descrie situații, obiecte și acțiuni. Pentru a explica cuiva un concept, ne bazăm pe cunoștințele comune și construim exemple în jurul acestuia. „La fel de sănătos ca Vasia”, „la fel de greu ca după o alergare de 5 km”, „la fel de rău ca mahmureala”, „acru ca o lămâie”, etc. Folosim astfel de expresii în discursul nostru tot timpul și nici măcar nu le observăm. Pentru noi, utilizarea lor este mai simplă decât o descriere detaliată și asta permite interlocutorului tău să te înțeleagă mai bine.
Dacă observați că nu încercați să vă amintiți detaliile de implementare a unui model de design, ci puteți pur și simplu să precizați detaliile aplicării acestuia în propriile cuvinte, atunci ați depășit nivelul Shu în celebra filozofie orientală a lui Shuhari (am scris un cu mult timp în urmă despre aplicabilitatea sa la abordări și practici Agile) . La nivel Shu pur și simplu urmați tipare și nu le recunoașteți utilitatea, subtilitățile și impactul. La nivelul Ha, ești deja conștient de tot și poți să refuzi în mod conștient anumite modele, să critici deciziile bazate pe acestea și să modifici unele modele pentru a se potrivi cu o situație și un context specific.
La nivel Ha Recomand cu căldură să citești excelenta carte „Refactoring to Patterns” de Joshua Kerievsky. Vorbește despre cum să găsești modele de design neadecvate sau aplicate prost în cod și apoi să le refactorizezi în soluții corecte și adecvate. Această carte ar trebui citită la nivelul Ha, pentru că înainte de asta va fi doar o frază goală pentru tine.
Dar nivelul? Ri? La acest nivel, nu te mai gândești la utilizarea șabloanelor. Soluțiile se nasc în mod natural din cunoștințele și abilitățile tale pe care le-ai acumulat de-a lungul anilor. Undeva apar doar șabloane, undeva propriile tale dezvoltări, care au devenit șabloane pentru tine în acest context. Lanțul „de la șablon la soluție” nu mai funcționează în capul tău și rămâne doar „de la soluție la șablon”. Apoi, în loc să puneți întrebări despre anumite modele de design într-un interviu, treceți la întrebări deschise despre aplicabilitatea instrumentului și exemple din viața reală...
Modelele de design sunt unul dintre instrumentele dezvoltatorului care îl ajută să economisească timp și să creeze o soluție mai bună. Ca orice alt instrument, în unele mâini poate aduce multe beneficii, dar în altele poate aduce doar rău. Am încercat să transmit prin exemple ce anume îți vor oferi modelele de design și cum ar trebui să le tratezi. sper ca am reusit...
P.S. La unul dintre cursurile mele, cartea despre modele de design pentru începători „Head First Design Patterns” a fost lăudată. Personal, nu l-am citit eu, pentru că aveam destule cunoștințe despre subiect din alte surse și sunt neîncrezător în cărțile de acest format.
Șabloane Calificare de plumb vă permit să grupați contactele după tipul și nivelul lor de implicare (de exemplu, după frecvența clicurilor pe e-mailuri). Odată ce persoanelor de contact li se atribuie un anumit scor sau etichetă, le puteți muta într-o altă campanie. Cu informațiile pe care le obțineți din aceste acțiuni, veți fi sigur că trimiteți oferte care vă vor interesa contactele.
Etichetați Linia de bază tip implicare. Procesul etichetează automat contactele în funcție de tipurile de oferte la care răspund. Datorită acestui lucru vei putea segmentați-vă baza de contact în funcție de interese și comportamentși trimiteți-le oferte personalizate în viitor.
Plan de punctaj de bază vă permite să identificați contacte prin nivel implicare. Acest proces adaugă sau scade automat puncte în funcție de activitatea de contact (deschideri de e-mail, clicuri, abonamente la newsletter). și schimbă constant puncte în funcție de acțiunile efectuate de abonați.
Pentru a crește vânzările, puteți utiliza șablonul Oferta demo. Poate fi folosit pentru a crea un proces de direcționare a persoanelor de contact calificate și de adăugare a acestora la o anumită etapă a canalului CRM. Acest proces poate fi utilizat atât pentru contactele noi, cât și pentru cele existente:
În pasul final, procesul atribuie etichete persoanelor de contact pentru a le identifica pentru campanii și mailing-uri viitoare.
Acest șablon este aprobat de expertul în conversii Talia Wolf.
Pentru a crește conversia și vânzările, puteți utiliza șablonul Etichetarea persoanelor de contact pe baza scorurilor. Șablonul vă ajută să creați un proces care:
Acest șablon este aprobat de expertul în conversii Talia Wolf.
Concepte generale despre construcția web.
Crearea site-ului web astazi atinge un nivel cu totul nou. Uneori, designerii web vă surprind plăcut până la bază cu talentul, priceperea și capacitatea lor de a-și transpune planurile în viața reală, iar lucrările create de maeștri merită cu adevărat să fie considerate o formă de artă modernă. Tehnologiile moderne ajută la simplificarea imaginilor design web, iar pe de altă parte, este necesară o cantitate considerabilă de cunoștințe în diverse științe, precum și abilități destul de bune în tehnologia informatică.
Pret mare designul site-ului web al autorului, realizat la comandă, este uneori un obstacol destul de serios în calea existenței pe Internet: serviciile dezvoltatorilor web profesioniști nu sunt ieftine și design de înaltă calitate un site web poate costa câteva sute de dolari. Cu costuri atât de mari, nu există nicio certitudine că costul creării unui site web va plăti. Șabloane de site-uri webîn această situație – soluția optimă. Când le folosiți costuri pentru fie foarte scăzut, fie complet absent (cu condiția să descărcați șablonul gratuit).
Un șablon de site este o pagină HTML pe care o utilizați pentru a lucra singur pe site-ul dvs. web. Toate graficele de design șablon și fișierele sale de serviciu (PSD, CSS, scripturi Java) au fost deja dezvoltate profesional designer web, și trebuie doar să îi modificați conținutul cu textul și imaginile.
De obicei, site-urile sunt create pentru a fi utilizate într-un fel de editor HTML și pentru a le schimba, abilitățile unui utilizator obișnuit de PC sunt suficiente.
Compoziția fișierelor incluse în livrarea unui șablon de site web depinde dacă sunteți dispus să plătiți pentru acesta.
Șabloane de site-uri plătite conțin întotdeauna toate fișierele necesare pentru editare, cu care puteți modifica grafica de design (PSD, Flash).
Șabloane gratuite pentru site-uri web, sunt furnizate în principal ca o singură pagină web și fișierele necesare. Lipsesc fișierele de bază șablon gratuite.
Deși standardele șablon au fost publicate de mult timp, acestea nu sunt încă distribuite pe scară largă. Desigur, este greu să folosești ceva pe care compilatorul tău nu îl acceptă, care este probabil motivul numărul unu pentru care majoritatea programatorilor C++ nu știu să lucreze cu șabloane. Din fericire, toți compilatorii majori au intrat acum în secolul al XX-lea, așa că această problemă a dispărut deja. Tot ce rămâne este să înțelegeți ce este un șablon, cum să ocoliți toate capcanele sintactice, dar, mai ales, de ce este necesar. Acest capitol depășește o prezentare generală a sintaxei. De asemenea, acoperă elementele de bază ale siguranței de tip în C++, cu un accent special pe șabloane.
Interfața unei clase simple de colecție (folosind o listă legată ca exemplu) arată astfel:
clasa ListNode (privat:
ListNode* următor; date nule*;
ListNode(void* d, ListNode* n = NULL) : next(n), data(d) () ~ListNode() (șterge următorul; )
void* Data() ( returnează date; ) ListNode* Next() ( returnează următorul; )
Ai observat ceva special?
În primul rând, toate aceste goluri* sunt izbitoare. Și tu și eu știm foarte bine că de fapt în spatele lor se află ceva cu totul diferit. Undeva în codul clientului va trebui să faceți ceva de genul acesta:
pentru (ListNode* n = listHead; n != NULL; n = n->Next()) f((Foo*)n->Data());
Cu alte cuvinte, va trebui să aruncați în mod constant void* într-un tip concret. Dar cum puteți fi sigur că indicatorul rezultat este de fapt de tip Foo*? Aici va trebui să te bazezi doar pe tine, deoarece compilatorul, cu cuvintele „Sper că știi ce faci”, își spală mâinile de el. Să presupunem că sunteți încrezător că utilizarea unei clase este sigură. Dar este posibil să se garanteze că un alt programator nu va face o prostie și nu va adăuga un obiect de alt tip la colecție? Dacă credeți cu fermitate în acest lucru, vă recomand să stați departe de investițiile riscante și să vă investiți banii în titluri de stat, este puțin probabil să aveți noroc în această viață.
A doua problemă este că elementele listei nu știu la ce tip indică. Să presupunem că doriți ca destructorul listei să ștergă nu numai nodurile în sine, ci și datele la care se referă. Nu puteți transmite un pointer void* operatorului de ștergere și sperați că va alege destructorul potrivit.
O soluție posibilă este să cereți ca toate obiectele din colecția dvs. să descende dintr-un strămoș comun. În acest caz, void* poate fi înlocuit cu un pointer către clasa de bază, creând cel puțin aspectul de ordine. Dacă destructorul clasei de bază este virtual, cel puțin putem rescrie destructorul ListNode, astfel încât atunci când se sinucide, să distrugă și conținutul listei. Dar dacă acea clasă de bază are clase derivate, cu siguranță va trebui să faceți modele nesigure pentru acele tipuri derivate.
O altă soluție este să creați o listă adaptată unui anumit tip. Să spunem, pentru a menține o listă de obiecte din clasa Foo, este creată o clasă de colecție ListOfFoos. În acest caz, nu va trebui să faceți modele de tip dacă Foo nu are clase derivate. Dar merită să creați clase duplicate care diferă doar prin tipurile cu care lucrează? Desigur, tăierea și lipirea în editorii de text este un lucru minunat, iar scripturile de procesare de text vă ajută să reproduceți rapid codul. Dar dacă trebuie să schimbați prezentarea tuturor acestor liste, veți ajunge inevitabil cu o durere de cap masivă.
În trecut, probleme de genul acesta erau adesea rezolvate folosind #define macros:
#define ListNode(Type) \ class ListNode##Type (\privat: \
ListNode##Type* în continuare; \Type* date; \
ListNode##Type(Type* d, ListNode* n = NULL) : next(n), data(d) () \ ~ListNode() (șterge următorul; ) \
void* Data() ( returnează date; ) \ ListNode* Next() ( return next; ) \
Dacă uitați din greșeală să includeți un \ , compilatorul va izbucni în urlete puternice de indignare, dar cu atenția cuvenită această tehnică funcționează. Simbolurile ## indică concatenarea. Designul devine și mai urât, dar trebuie să-l suportați - trebuie să vă asigurați că numele tipurilor de colecție sunt unice. Această tehnică are numeroase dezavantaje. Dacă funcțiile de clasă nu sunt inline, va trebui să creați macrocomenzi suplimentare pentru ele și să vă asigurați că sunt implementate în aceeași unitate de compilare. Unele compilatoare au probleme cu macrocomenzile prea lungi. #defines nu poate fi imbricat, așa că nu mai sunt necesare structuri de date recursive, sigure de tip. Cel mai rău lucru este că atunci când o eroare este detectată într-o macrocomandă, depanatorul își încrucișează brațele și raportează că a existat o eroare undeva în macro, dar nu indică un anumit număr de linie.
Șabloane - macrocomenzi avansate
Motorul de șablon intră în imagine - un procesor macro îmbunătățit pentru directivele #define. Șabloanele nu sunt altceva decât macrocomenzi fără toate limitările enumerate mai sus. Ele pot fi imbricate. Nu va trebui să vă faceți griji cu privire la duplicarea funcțiilor acestora. Majoritatea depanatoarelor C++ specifică corect șirul de model atunci când apare o eroare. Dimensiunea șablonului nu va cauza probleme. În cele din urmă, nu trebuie să-ți strici programul frumos cu squiggles ca \ și ## .
Șabloanele de documente sunt necesare pentru a completa automat câmpurile și tabelele din documentele MS Word cu date din baza de date. Acest lucru vă permite să creați documente precum Aplicație, Factură, Factură, Factură, Acord, Act și multe, multe altele. Ele pot fi tipărite, trimise prin poștă etc.
Un element de meniu apare în orice tabel Șabloane de documente.
Selectarea acestui meniu deschide o listă de șabloane de document pentru acest obiect.
Selectând un șablon și făcând clic pe butonul Completați vei primi un document completat.
Aceste setări trebuie făcute o singură dată.
După reconectare, selectați meniu Setări - Șabloane documente. Va apărea un dialog în care sunt configurate șabloanele de documente.
Descrierea zonelor ferestrelor:
Secțiunea Document conține următoarele butoane:
A treia și a patra zonă conțin câmpuri care sunt inserate în document. Există butoane:
În a patra zonă, puteți face clic dreapta pe câmpul marcat și puteți seta sortarea.
Să presupunem că trebuie să creați un șablon care va afișa informații despre client și achizițiile sale.
Dacă este necesar, configurați sortarea în tabele.
Iată cum arată configurarea unui șablon de document în program:
Și așa arată șablonul de document în sine cu câmpuri:
Pentru a utiliza șabloane de document, trebuie să acordați permisiunea corespunzătoare utilizatorului și obiectului. Apoi:
Ca rezultat, obținem un șablon completat.
Acum puteți imprima acest document sau îl puteți salva dacă este necesar.