Κάθε στήλη του πίνακα είναι ένας διαφορετικός κανόνας.
Προϋποθέσεις | 1 | 2 | 3 | 4 | 5 |
Προϋπόθεση 1 | X | X | X | - | - |
Προϋπόθεση 2 | - | - | - | X | - |
Προϋπόθεση 3 | X | - | - | - | - |
Προϋπόθεση 4 | X | X | - | - | - |
| - | - | - | - | - |
| - | - | - | - | - |
Ενέργειες |
Ενέργεια 1 | X | - | - | - | - |
Ενέργεια 2 | - | X | - | - | - |
Ενέργεια 3 | - | - | X | - | - |
Ενέργεια 4 | - | - | - | X | - |
Ενέργεια 5 | - | - | - | - | X |
Ενέργεια 6 | X | X | - | - | X |
Πρότυπα κωδικοποίησης
Ο τρόπος της κωδικοποίησης καθορίζεται συχνά από έναν
οδηγό ύφους (style guide).
Αυτός ορίζει στοιχεία πέρα από αυτά που προσδιορίζει η σύνταξη μιας συγκεκριμένης
γλώσσας.
Για παράδειγμα το παρακάτω είναι ένα νόμιμο αλλά όχι ευανάγνωστο πρόγραμμα
γραμμένο σε C:
#define O(b,f,u,s,c,a)b(){int o=f();switch(*p++){X u:_ o s b();X c:_ o a b();default:p--;_ o;}}
#define t(e,d,_,C)X e:f=fopen(B+d,_);C;fclose(f)
#define U(y,z)while(p=Q(s,y))*p++=z,*p=' '
#define N for(i=0;i<11*R;i++)m[i]&&
#define I "%d %s\n",i,m[i]
#define X ;break;case
#define _ return
#define R 999
typedef char*A;int*C,E[R],L[R],M[R],P[R],l,i,j;char B[R],F[2];A m[12*R],malloc
(),p,q,x,y,z,s,d,f,fopen();A Q(s,o)A s,o;{for(x=s;*x;x++){for(y=x,z=o;*z&&*y==
*z;y++)z++;if(z>o&&!*z)_ x;}_ 0;}main(){m[11*R]="E";while(puts("Ok"),gets(B)
)switch(*B){X'R':C=E;l=1;for(i=0;i<R;P[i++]=0);while(l){while(!(s=m[l]))l++;if
(!Q(s,"\"")){U("<>",'#');U("<=",'$');U(">=",'!');}d=B;while(*F=*s){*s=='"'&&j
++;if(j&1||!Q(" \t",F))*d++=*s;s++;}*d--=j=0;if(B[1]!='=')switch(*B){X'E':l=-1
X'R':B[2]!='M'&&(l=*--C)X'I':B[1]=='N'?gets(p=B),P[*d]=S():(*(q=Q(B,"TH"))=0,p
=B+2,S()&&(p=q+4,l=S()-1))X'P':B[5]=='"'?*d=0,puts(B+6):(p=B+5,printf("%d\n",S
()))X'G':p=B+4,B[2]=='S'&&(*C++=l,p++),l=S()-1 X'F':*(q=Q(B,"TO"))=0;p=B+5;P[i
=B[3]]=S();p=q+2;M[i]=S();L[i]=l X'N':++P[*d]<=M[*d]&&(l=L[*d]);}else p=B+2,P[
*B]=S();l++;}X'L':N printf(I)X'N':N free(m[i]),m[i]=0 X'B':_ 0 t('S',5,"w",N
fprintf(f,I))t('O',4,"r",while(fgets(B,R,f))(*Q(B,"\n")=0,G()))X 0:default:G()
;}_ 0;}G(){l=atoi(B);m[l]&&free(m[l]);(p=Q(B," "))?strcpy(m[l]=malloc(strlen(p
)),p+1):(m[l]=0,0);}O(S,J,'=',==,'#',!=)O(J,K,'<',<,'>',>)O(K,V,'$',<=,'!',>=)
O(V,W,'+',+,'-',-)O(W,Y,'*',*,'/',/)Y(){int o;_*p=='-'?p++,-Y():*p>='0'&&*p<=
'9'?strtol(p,&p,0):*p=='('?p++,o=S(),p++,o:P[*p++];}
Οι οδηγοί ύφους έχουν ως στόχο να προλαμβάνουν φαινόμενα σαν το παραπάνω.
Για παράδειγμα ο οδηγός ύφους της γλώσσας C "Recommended C Style and Coding Standards"
γνωστός ως "Indian Hills Style Guide" περιέχει τα παρακάτω στοιχεία:
- File Organization
- Comments
- Declarations
- Function Declarations
- Whitespace
- Examples
- Simple Statements
- Compound Statements
- Operators
- Naming Conventions
- Constants
- Macros
- Conditional Compilation
- Program Structure
- Debugging
- Portability
- ANSI C
- Special Considerations
- Make
- Project-Dependent Standards
Δομές δεδομένων
Οι βασικές δομές δεδομένων που θα συναντήσετε είναι:
Σύγχρονες γλώσσες όπως η C++ και η Java παρέχουν έτοιμη υποστήριξη για πολλούς
από τους παραπάνω τύπους.
Χρήση βεβαιώσεων
Προγραμματίζουμε με σιγουριά αν εκφράζουμε τους αλγορίθμους μας
με βάση:
Παράδειγμα
Είσοδος:
Α(1..Ν): πίνακας ακεραίων
N : ακέραιος
Έξοδος:
Β(1..Ν): πίνακας ακεραίων
Προϋποθέσεις:
Ν >= 1
Μετασυνθήκες:
Β(1..Ν) περιέχει τις τιμές του Α(1..Ν)
Μεταβλητές
Ι : Ακέραιος
I := 1
Όσο Ι <= Ν
Β(Ι) := Α(Ι)
Αναλλοίωτη συνθήκη: Β(1..Ι) := Α(1..Ι)
Συνθήκη σύγκλισης: Ν - Ι
Ι := Ι + 1
Τέλος
Σε στρατηγικά σημεία του κώδικα μπορούμε να εκφράζουμε τις παραπάνω
έννοιες με τη βοήθεια μιας βεβαίωσης (assertion).
Παράδειγμα:
void
arraycopy(int a[], int b[], int n)
{
assert(n >= 0);
// ...
}
Απλοί κανόνες
Μερικοί κανόνες (Kernighan και Plauger 1976, Davis 1995) που πρέπει να ακολουθούμε κατά την κωδικοποίηση είναι οι παρακάτω:
- Αυτοματοποιήστε όσα στοιχεία της διεργασίας μπορείτε
- Τακτοποιείτε τον κώδικα σε τακτά διαστήματα
- Χρησιμοποιείτε έτοιμες βιβλιοθήκες
- Βάζετε παρενθέσεις για να κάνετε τον κώδικα πιο σαφή
- Να εκφράζετε περίπλοκες δομές ελέγχου ως δεδομένα
static const int month_days[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
- Μετά την πρώτη έκδοση του προγράμματος, βελτιώστε τον κώδικα
- Μη διορθώνετε κακογραμμένο κώδικα, ξαναγράψτε τον
- Χρησιμοποιείτε αναδρομικές διαδικασίες για αναδρομικές δομές δεδομένων
- Να ελέγχετε την είσοδο του προγράμματός σας
- Όταν βρείτε ένα λάθος, ψάξτε για παρόμοια και για το επόμενο
- Τα σχόλια να μην επαναλαμβάνουν ό,τι λέει ο κώδικας
- Μην επεξηγείτε τον κακό κώδικα με σχόλια, ξαναγράψτε τον
- Μη χρησιμοποιείτε υπερβολικά πολλά σχόλια
- Ο κώδικας να συμφωνεί με τα σχόλια
- Αποφεύγετε τα "έξυπνα" τεχνάσματα
int a, b;
a ^= b;
b ^= a;
a ^= b;
int a, b, tmp;
tmp = a;
a = b;
b = tmp;
- Αποφεύγετε τις καθολικές μεταβλητές
- Το πρόγραμμά σας να διαβάζεται από πάνω προς τα κάτω
- Αποφεύγετε τα παράπλευρα αποτελέσματα (side effects)
- Χρησιμοποιείτε κατανοητά ονόματα μεταβλητών
- Ο κώδικάς σας να στοχεύει κύρια τους ανθρώπους
- Να χρησιμοποιείτε αποδοτικές δομές δεδομένων και αλγορίθμους
- Να στοχεύετε στην ορθότητα πριν την ταχύτητα
- Γράφετε τα σχόλια από την αρχή
- Τεκμηριώστε πριν αρχίσετε να γράφετε τον κώδικα
- Να εκτελείτε με το χέρι το κάθε τμήμα του κώδικα
- Επιθεωρείτε τον κώδικα
- Γράφετε δομημένα ακόμα και σε αδόμητες γλώσσες
- Αποφεύγετε την υπερβολική εμφώλευση
- Να χρησιμοποιείτε την κατάλληλη γλώσσα για κάθε εφαρμογή
- Προσέχετε την όψη του κώδικα
- Να χρησιμοποιείτε βεβαιώσεις
- Να γράφετε ρουτίνες ελέγχου του κώδικα
- Μη βιαστείτε να αρχίσετε
Εσωτερική και εξωτερική τεκμηρίωση
-
Η εσωτερική τεκμηρίωση βοηθά στην καλύτερη διαχείριση και οργάνωση του κώδικα.
- Υπάρχουν συστήματα που μετατρέπουν την τεκμηρίωση αυτή και σε εξωτερική
τεκμηρίωση.
Παράδειγμα:
/**
* A class containing static methods that allow the simple, correct,
* and efficient procesing of a console application's standard input
* and output streams.
* Output is buffered, but automagically flushed, so that prompts in
* interactive applications work as expected.
* All errors will terminate the application with an error message.
* The code was written to provide an easy-to-learn and consistent interface
* for learning Java. It is not intended for production work.
*
* @author Diomidis Spinellis
* @version $Revision: 1.4 $
* @see java.io
* @see java.io.Writer
* @see java.io.PrintWriter
*/
public class BIO {
// Reader and Writer
private static BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter out =
new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
private static boolean needFlush = false;
// Class initializer
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
// Will run when VM shuts down
public void run()
{
try {
in.close();
out.close();
} catch (Exception e) {
}
}
});
}
/**
* Flush the output stream. If the stream has saved any characters from
* the various write() methods in a buffer, write them immediately to
* their intended destination.
* Flushing is automatically performed before reading input from a
* source * that could be affected by reading the program's output
* (e.g. a human).
*/
public static void flush() { out.flush(); needFlush = false; }
/** Print the argument of type char on the standard output. */
public static void print(char x) { out.print(x); needFlush = true; }
/** Print the argument of type int on the standard output. */
public static void print(int x) { out.print(x); needFlush = true; }
/** Print the argument of type boolean on the standard output. */
public static void print(boolean x) { out.print(x); needFlush = true; }
/** Print the argument of type double on the standard output. */
public static void print(double x) { out.print(x); needFlush = true; }
/** Print the argument of type Object on the standard output. */
public static void print(Object x) { out.print(x); needFlush = true; }
Βιβλιογραφία
- Εμμανουήλ Σκορδαλάκης.
Εισαγωγή στην Τεχνολογία Λογισμικού, σελίδες 119-132.
Εκδόσεις Συμμετρία, 1991.
- Εμμ. Α. Γιακουμάκης
Τεχνολογία Λογισμικού: Απαιτήσεις Λογισμικού, σχεδίαση λογισμικού,
σελίδες 157-196.
Εκδόσεις Α. Σταμούλης, Αθήνα, Πειραιάς, 1994.
- Εμμ. Α. Γιακουμάκης
Τεχνολογία Λογισμικού: Κωδικοποίηση, έλεγχος και συντήρηση λογισμικού.
σελίδες 17-54.
Εκδόσεις Α. Σταμούλης, Αθήνα, Πειραιάς, 1993.
- L.W. Cannon, R.A. Elliott, L.W.
Kirchhoff, J.H. Miller, J.M. Milner, R.W. Mitze, E.P. Schan, N.O.
Whittington, Henry Spencer, David Keppel, and Mark Brader.
Recommended C style
and coding standards.
Available online http://sunland.gsfc.nasa.gov/info/cstyle.html (December 2001).
Updated version of the Indian Hill C Style and Coding Standards paper.
- Edsger Wybe Dijkstra.
Go to statement considered harmful.
Communications of the ACM, 11(3):147–148, March 1968.
- Richard Stallman et al.
GNU coding
standards.
Available online http://www.gnu.org/prep/standards_toc.html (December 2001),
October 2001.
- The FreeBSD Project.
Style – Kernel Source File Style Guide, December 1995.
FreeBSD Kernel Developer's Manual: style(9).
- Andrew Hunt and David
Thomas.
The
Pragmatic Programmer: From Journeyman to Master.
Addison Wesley Longman, 2000.
- Brian W. Kernighan
and Rob Pike.
The
Practice of Programming.
Addison-Wesley, 1999.
- Brian W. Kernighan
and P. J. Plauger.
Software Tools.
Addison-Wesley, 1976.
- Brian W. Kernighan
and P. J. Plauger.
The
Elements of Programming Style.
McGraw-Hill, second edition, 1978.
- Karl Lieberherr
and Ian Holland.
Assuring good style for object-oriented programs (ftp://ftp.ccs.neu.edu/pub/research/demeter/documents/papers/LH89-law-of-demeter.ps).
IEEE Software, pages 38–48, September 1989.
- Roger S. Pressman.
Software Engineering: A Practitioner's Approach, pages 420–425.
McGraw-Hill, 1987.
- Roger S. Pressman.
Software Engineering: A Practitioner's Approach, pages 413–425.
McGraw-Hill, fifth edition, 2000.
European Adaptation. Adapted by Darrel Ince.
- Charles Simonyi.
Hungarian notation (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvsgen/html/hunganotat.asp).
Available online
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvsgen/html/hunganotat.asp (December 2001), November 1999.
Microsoft Developer Network Library.
- Ian Sommerville.
Software Engineering, pages 260–284,392–416.
Addison-Wesley, sixth edition, 2001.
- Henry Spencer.
The Ten Commandments for C programmers (annotated edition).
;login:, 18(2):29–31, March slash April 1993.
- Sun
Microsystems Inc.
Java code conventions (http://java.sun.com/docs/codeconv/).
Available online http://java.sun.com/docs/codeconv/ (December 2001), April
1999.
Ασκήσεις
- Ξαναγράψτε μερικά από τα παλιά σας προγράμματα σύμφωνα με τις αρχές του
μαθήματος αυτού.
- Αξιολογείστε προγράμματα ανοιχτού κώδικα που θα βρείτε στο Internet
ως προς τις αρχές κωδικοποίησης που ακολουθούν.
- Διαβάστε προσεκτικά έναν πλήρη οδηγό ύφους προγραμματισμού (βλ. βιβλιογραφία).