Differences

This shows you the differences between two versions of the page.

Link to this comparison view

programare:coding-style [2019/10/01 20:15]
darius.neatu [Coding style]
programare:coding-style [2024/11/05 16:33] (current)
darius.neatu [Convenție]
Line 1: Line 1:
-===== Coding style =====+===== Coding style example ​=====
  
 **Responsabili:​** ​ **Responsabili:​** ​
-  * [[neatudarius@gmail.com|Darius Neațu ​ ]] (2018, 2019+  * [[neatudarius@gmail.com|Darius Neațu ​ ]] (2018-2024
-  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip]] (2018, 2019)+  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip]] (2018-2024)
  
  
Line 20: Line 20:
  
 **Toate** scenariile de mai sus reprezintă exemple care v-ar putea afecta în sens negativ, de aceea la materia PC (și multe altele în facultate) vi se va impune să urmăriți anumite aspecte care să vă obisnuiască încă de la început, când lucrurile sunt foarte simple, astfel încât aceste deprinderi să intre în modul vostru normal de a coda. **Toate** scenariile de mai sus reprezintă exemple care v-ar putea afecta în sens negativ, de aceea la materia PC (și multe altele în facultate) vi se va impune să urmăriți anumite aspecte care să vă obisnuiască încă de la început, când lucrurile sunt foarte simple, astfel încât aceste deprinderi să intre în modul vostru normal de a coda.
 +
 +<note warning>​Pe lângă respectarea convenției (a coding style-ului),​ este important să scriem cod **reutilizabil** și **ușor de întreținut**.
 +
 + În mare, acest lucru se obține prin **modularizarea bună a codului** și prin **evitarea unor practici nerecomandate** care fac codul greu de înțeles și întrețnut.
 +
 +În consecință,​ este **nerecomandată** utilizarea **variabilelor globale** și a **salturilor nedisciplinate** (goto).
 +
 +Utilizarea celor 2 de mai sus în cazuri în care nu sunt absolut necesare, precum și scrierea de funcții nejustificat de lungi vor atrage după sine depunctarea în cadrul temelor de casă.</​note>​
  
 ==== Convenție ==== ==== Convenție ====
Line 25: Line 33:
  
 Pentru a rezolva toate problemele care pot apărea, vom folosi o ** convenție de coding style**. Convențiile sunt seturi de reguli acceptate de comunități largi. Există mici diferențe între ele, fapt care face ca atunci când se trece de la o convenție la alta (ex. alta firmă) să nu reprezinte o problemă. Pentru a rezolva toate problemele care pot apărea, vom folosi o ** convenție de coding style**. Convențiile sunt seturi de reguli acceptate de comunități largi. Există mici diferențe între ele, fapt care face ca atunci când se trece de la o convenție la alta (ex. alta firmă) să nu reprezinte o problemă.
- 
-=== Google Coding Style === 
-La Programarea Calculatoarelor **seria CA** vom folosi o convenție de coding style extrasă din documentația oficială de C++ de la Google ([[https://​google.github.io/​styleguide/​cppguide.html|Google C++ ]]). Motivele pentru care am ales-o este că este larg folosită de comunitatea open-source,​ oferă un script automat de testare care afisează toate problemele pentru a le corecta, iar acest script poate fi ușor adaptat de la C++ la C. 
  
  
Line 35: Line 40:
  * Codul trebuie să fie:  * Codul trebuie să fie:
    * **clar** și ** modularizat**    * **clar** și ** modularizat**
-     * Codul se va împărți în componente astfel încât să existe o separație logică (ex. mai multe fișiere, mai mule funcții etc). Fiecare bucată elementară de logică va fi mutată într-o funcție (ceea ce permite și **reutilizarea** codului. Funcțiile care au ceva în comun (ex. funcții matematice) vor fi grupate.+     * Codul se va împărți în componente astfel încât să existe o separație logică (ex. mai multe fișiere ​- sursă și header, mai mule funcții etc). Fiecare bucată elementară de logică va fi mutată într-o funcție (ceea ce permite și **reutilizarea** codului. Funcțiile care au ceva în comun (ex. funcții matematice) vor fi grupate.
    * **expresiv**    * **expresiv**
      * **Numele** entităților trebuie să fie sugestive.      * **Numele** entităților trebuie să fie sugestive.
-       * Numele de variabilă trebuie să fie sugestiv și să arate la ce e folosită aceea variabilă. Este perfect ok să avem nume precum **i, j, k, p, q** pentru ​indecsi/contori folosiți ​atunci cand lucrăm cu tablouri, dar pentru lucruri netriviale, numele de variabilă trebuie să arate mai mult (ex. ** int count_duplicates;​** vs **int c;** - prima situatie ​exprima ​clar ca acest contor este folosit pentru a număra duplicatele,​ în schimb în cea dea doua situație nu putem înțelege la ce e folosit c fara a citi tot codul care îl folosește).+       * Numele de variabilă trebuie să fie sugestiv și să arate la ce e folosită aceea variabilă. Este perfect ok să avem nume precum **i, j, k, p, q** pentru ​index/contor folosit ​atunci cand lucrăm cu tablouri, dar pentru lucruri netriviale, numele de variabilă trebuie să arate mai mult (ex. ** int count_duplicates;​** vs **int c;** - prima situatie ​exprimă ​clar ca acest contor este folosit pentru a număra duplicatele,​ în schimb în cea dea doua situație nu putem înțelege la ce e folosit ​*c* fără ​a citi tot codul care îl folosește).
        * **Numele de funcții** reflectă de asemenea acțiunea pe care aceasta o realizează. Exemplu: **int count_duplicates(int n, int v[NMAX]); ** vs **int f(int n, int v[NMAX]);​**. Primul caz spune ce face funcția, în cel de-al doilea caz numele funcției nu ne spune nimic.        * **Numele de funcții** reflectă de asemenea acțiunea pe care aceasta o realizează. Exemplu: **int count_duplicates(int n, int v[NMAX]); ** vs **int f(int n, int v[NMAX]);​**. Primul caz spune ce face funcția, în cel de-al doilea caz numele funcției nu ne spune nimic.
-         * **Convenție**:​ numele de variabile și funcții vor fi sugestive, vor fi compuse din litere mici, cifre si underscore (în cazul in care dorim să avem mai mult cuvinte).+         * **Convenție**:​ numele de variabile și funcții vor fi sugestive, vor fi compuse din litere mici, cifre sau underscore (în cazul in care dorim să avem mai mult cuvinte).
      * **Comentariile** ajută la îmbunătățirea expresivității,​ atunci când numele și organizarea codului nu sunt suficiente. Exemplu: o funcție care care caută duplicatele dintr-un vector, apoi șterge elementele duplicate, iar din cele ramăse le șterge pe toate pare sau divizibile cu 1007 și returnează și câte numere sunt prime. Nu putem exprima întreaga funcționalitate doar prin numele funcției, astfel că o vom numi ** update_array**,​ iar înainte de semnatura funcției vom explica algoritmul de update în **câteva** cuvinte.      * **Comentariile** ajută la îmbunătățirea expresivității,​ atunci când numele și organizarea codului nu sunt suficiente. Exemplu: o funcție care care caută duplicatele dintr-un vector, apoi șterge elementele duplicate, iar din cele ramăse le șterge pe toate pare sau divizibile cu 1007 și returnează și câte numere sunt prime. Nu putem exprima întreaga funcționalitate doar prin numele funcției, astfel că o vom numi ** update_array**,​ iar înainte de semnatura funcției vom explica algoritmul de update în **câteva** cuvinte.
    ​* ​ **lizibil**    ​* ​ **lizibil**
Line 53: Line 58:
     * Pentru operatorii binari avem convenția: **operand1 spatiu operator spatiu operand2**. (Ex. "x + 2", int x =  y + 2;")     * Pentru operatorii binari avem convenția: **operand1 spatiu operator spatiu operand2**. (Ex. "x + 2", int x =  y + 2;")
     * Pentru operatorii unari nu lăsăm spațiu între operator și operand. (Ex. "​i++",​ "​++i"​).     * Pentru operatorii unari nu lăsăm spațiu între operator și operand. (Ex. "​i++",​ "​++i"​).
-    * Nu lăsăm spațiu niciodată înainte de punct și virgulă.+    * Nu lăsăm spațiu niciodată înainte de ';'​.
     * Lăsăm spațiu mereu după virgulă, niciodată înainte.     * Lăsăm spațiu mereu după virgulă, niciodată înainte.
-  * identarea (de fiecare data când se intră în {} se scrie cu un tab mai la dreapta)+  * identarea (de fiecare data când se intră în '{}' ​se scrie cu un tab mai la dreapta)
   * cum se închid și deschid acoladele   * cum se închid și deschid acoladele
-    * chiar dacă avem o singură instrucțiune în if și nu e nevoie să punem acolade, în convenția stabilită vom pune pentru a pastra aspectul unitar al codului; un alt motiv ar putea fi acela că putem adăuga direct intrucțiuni noi fără să omitem din greșeală să mai punem și acolade.+    * chiar dacă avem o singură instrucțiune în if și nu e nevoie să punem acolade, în convenția stabilită vom pune pentru a pastra aspectul unitar al codului; un alt motiv ar putea fi acela că putem adăuga direct intrucțiuni noi fără să omitem din greșeală să mai punem și acolade. ​
   * cum se scrie o cascadă de if-else if-uri   * cum se scrie o cascadă de if-else if-uri
  
Line 140: Line 145:
  
 == functions == == functions ==
 +
 Analizați exemplele de funcții de mai jos și observați că. Analizați exemplele de funcții de mai jos și observați că.
    * numele funcțiilor e sugestiv    * numele funcțiilor e sugestiv
 +   * cum pune '​{}'​ față de celelalte cazuri
    * spațierea se menține și la nivelul listei de parametri    * spațierea se menține și la nivelul listei de parametri
      * ATENȚIE! Nu punem spațiu între numele funcției și '​('​      * ATENȚIE! Nu punem spațiu între numele funcției și '​('​
Line 148: Line 155:
    
 <code c> <code c>
-void clean_display() {+void clean_display(void) 
 +{
     ...     ...
 } }
Line 155: Line 163:
 ... ...
  
-void print_array(int n, int v[NMAX]) {+void print_array(int n, int v[NMAX]) 
 +{
     ...     ...
 } }
  
-int print_gigel(int gigel) {+int print_gigel(int gigel) 
 +{
     ...     ...
     return result;     return result;
 } }
  
-int count_duplicates(int n, int v[NMAX]) {+int count_duplicates(int n, int v[NMAX]) 
 +{
     int x = n;             // niciodata nu lasam prima linie dintr-un block {} goala, nu are sens     int x = n;             // niciodata nu lasam prima linie dintr-un block {} goala, nu are sens
     ...     ...
Line 179: Line 190:
  
 == programs == == programs ==
 +
 Fie următorul șablon de program. Analizați: Fie următorul șablon de program. Analizați:
- * cum scriem în fișier mai multe funcții +   * cum scriem în fișier mai multe funcții 
- * care e structura generală a unui program+   ​* care e structura generală a unui program
  
 <code c> <code c>
Line 189: Line 201:
 #define NMAX 100    // nu vom declara tablouri cu int v[100]; ci vom folosi un macro pentru dimensiune ​     ​ #define NMAX 100    // nu vom declara tablouri cu int v[100]; ci vom folosi un macro pentru dimensiune ​     ​
                     // linie goala                     // linie goala
-void dummy() {+void dummy(void) 
 +{
 } }
                     // lasam o linie goala intre functii                     // lasam o linie goala intre functii
-int print_array(int n, int v[NMAX]) {+int print_array(int n, int v[NMAX]) 
 +{
      ...      ...
 } }
                     // lasam o linie goala intre functii                     // lasam o linie goala intre functii
-int main() {+int main(void) 
 +{
    ...    ...
    ​return 0;    ​return 0;
Line 204: Line 219:
  
 <​note>​ <​note>​
-  ​Evident ca atunci ​cand fișirul main devine prea mare, este nevoie să grupăm componentele după logică și să le mutăm în alte fișiere sursă C/headere.+Evident ca atunci ​când fișierul 'main.c' ​devine prea mare, este nevoie să grupăm componentele după logică și să le mutăm în alte fișiere sursă C/headere.
 </​note>​ </​note>​
  
-=== Coding Style checker - seria CA=== 
-Toate aspectele menționate mai sus sunt foarte importante și trebuie să vi le însușiți. Evident că la început este greu să rețineți toate regulile, de aceea va punem la dispoție o modalitate de testare, folosind scriptul [[https://​google.github.io/​styleguide/​cppguide.html|Google C++]], adaptat pentru nevoile noastre. 
  
-Varianta de script pe care o vom folosi ​la PC este [[https://​ocw.cs.pub.ro/​courses/​_media/​programare/​teme_2018/​cs.zip|aici]].+=== Seria CA - Coding Style checker === 
 +Pentru a vă ajuta la teme și a evita eventualele depunctări pentru chestii standard, echipa vă pune la dispoziție scriptul *cs.sh*Acesta va fi folosit la teme pentru a depuncta în mod automat cele mai frecvente erori de coding style la seria CA.
  
-== Exemplu == +<​note>​ 
-Să presupunem că cineva a scris din greșeală următorul cod (sigur nu voi).+Conveția impusă de checkerul nostru este cea din [[https://​www.kernel.org/​doc/​html/​v4.10/​process/​coding-style.html| Linux Kernel]], cu mici ajustări. 
 +</​note>​
  
-<code cpp+<note
-#include <​stdio.h>​ +Checkerul de coding style se găsește la adresa ​[[https://cutt.ly/PCLP1-CA-CS-2024]]. 
- +</note>
-int main() +
- +
- +
-+
- +
-int x = 0; +
-    printf("​%d\n"​ +
- +
- +
-    , x); +
- +
-    return 0;} +
-</​code>​ +
- +
-În caz că nu observ problemele pe care trebuie să le corectez, rulez următoarea comandă: +
-<code bash> +
-darius@pc ~ $ python cs.py cs_negative_example.c +
-cs_negative_example.c:​0: ​ No copyright message found. ​ You should have a line: "​Copyright ​[year] <​Copyright Owner>"  ​[legal/​copyright] [5] +
-cs_negative_example.c:6:  { should almost always be at the end of the previous line  [whitespace/braces] [4] +
-cs_negative_example.c:​7: ​ Redundant blank line at the start of a code block should be deleted. ​ [whitespace/blank_line] [2] +
-cs_negative_example.c:12:  Tab found; better to use spaces ​ [whitespace/tab[1] +
-Done processing cs_negative_example.+
-Total errors found: 4 +
-</​code>​ +
- +
-Dacă vom corecta cele reclamate de script, vom obține un nou fișier cu următorul conținut:​ +
-<code cpp> +
-// Copyright 2018 Darius Neatu (neatudarius@gmail.com) +
- +
-#include <​stdio.h>​ +
- +
-int main() { +
-    int x = 0; +
-    printf("​%d\n",​ x); +
-    return 0; +
-+
- +
-</​code>​ +
- +
-Rulăm din nou scriptul și observăm că problemele au dispărut. +
-<code bash> +
-darius@pc ~ $ python cs.py cs_positive_example.c  +
-Done processing cs_positive_example.c +
-Total errors found: 0 +
-</code>+
  
 <note warning> <note warning>
-În exemplele ​de mai sus s-a presupus că atât sursele C cât și scriptul cs.py sunt în același director.+ATENȚIE! Anumite aspecte ​de coding style nu pot fi verificate automat prin checkerDe aceea punctajul final pentru coding style se acordă după corectarea manuală.
 </​note>​ </​note>​
  
-=== Concluzie - seria CA=== 
-Este foarte important să avem un coding style OK. Această pagină vine în ajutorul vostru. 
- 
-<note warning> 
-Scriptul prezentat pe această pagină va fi folosit pentru verificarea automată a temelor de la **seria CA**a coding style-ului la teme. În caz ca apar erori se va penaliza cu **15** puncte conform regulamentului. 
- 
-</​note>​ 
programare/coding-style.1569950116.txt.gz · Last modified: 2019/10/01 20:15 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0