Σχεδιασμός, εμφάνιση και ύφος

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Δομημένος προγραμματισμός

Ο νόμος Demeter

Σημείωση: Ο νόμος Demeter (προφ. νταϊμέτρ) (Lieberherr και Holland 1989) έλαβε το όνομά του από το ομώνυμο ερευνητικό έργο, το οποίο με τη σειρά του ονομάστηκε προς τιμή της αρχαίας θεάς Δήμητρας.

Παράδειγμα Demeter

class Demeter { private A a; private int myFunc() { /* ... */ } public void example (B b) { C c = new C(); int f = myFunc(); // ... b.paramMethod(); a = new A(); a.createdMethod(); c.ownMethod(); } }

Απλοί κανόνες 1

Μερικοί κανόνες (Kernighan και Plauger 1976, Davis 1995) που πρέπει να ακολουθούμε κατά την κωδικοποίηση είναι οι παρακάτω:

Απλοί κανόνες 2

  • Χρησιμοποιείτε αναδρομικές διαδικασίες για αναδρομικές δομές δεδομένων
  • Να χρησιμοποιείτε αποδοτικές δομές δεδομένων και αλγορίθμους
  • Τακτοποιείτε τον κώδικα σε τακτά διαστήματα
  • Μετά την πρώτη έκδοση του προγράμματος, βελτιώστε τον κώδικα
  • Το πρόγραμμά σας να διαβάζεται από πάνω προς τα κάτω
  • Ο κώδικάς σας να στοχεύει κύρια τους ανθρώπους
  • Χρησιμοποιείτε κατανοητά ονόματα μεταβλητών
  • Να εκτελείτε με το χέρι το κάθε τμήμα του κώδικα
  • Γράφετε δομημένα ακόμα και σε αδόμητες γλώσσες
  • Να χρησιμοποιείτε την κατάλληλη γλώσσα για κάθε εφαρμογή
  • Προσέχετε την όψη του κώδικα

    Πόσα σχόλια είναι αρκετά;

    Unneeded comments

    Σχόλια για τα σχόλια

    Έλεγχοι

    Τι να αποφεύγετε

    Οδηγίες και παράδειγμα μορφοποίησης κώδικα

    /*
     * Όνομα της κλάσης
     *
     * Copyright έτος όνομα/οργανισμός.
     */
    
    package gr.aueb.dmst.Package;
    
    import java.blah.blough.bligh;
    
    /**
     * Σύνοψη της κλάσης σε μια γραμμή.
     * Αναλυτική περιγραφή της κλάσης.
     *
     * @version     1.82 18 Mar 1999
     * @author      Όνομα Επώνυμο
     */
    
    public class SpecialHtmlParser extends FileHtmlParser {
    
        /*
         * Εδώ γράφεται το σχόλιο υλοποίησης της κλάσης.
         */
    
        /** Σύνοψη του πεδίου κλάσης classVar1 */
        public static int classVar1;
    
        /** Σύνοψη του πεδίου κλάσης classVar2 */
        protected static int classVar2;
    
        /** Σύνοψη του πεδίου κλάσης classVar3 */
        static int classVar3;
    
        /** Σύνοψη του πεδίου κλάσης classVar3 */
        private static Object classVar3;
    
        /**
         * Σύνοψη του πεδίου υπόστασης instanceVar1
         * Εκτενής επεξήγηση του πεδίου instanceVar1 σε πολλαπλές
         * γραμμές
         */
        public int instanceVar1;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar2 */
        protected int instanceVar2;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar3 */
        static int instanceVar3;
    
        /** Σύνοψη του πεδίου υπόστασης instanceVar4 */
        private Object instanceVar4;
    
        /** Construct a parser for the specified HTML dialect. */
        SpecialHtmlParser(string dialect, int maxNesting) {
            // Κώδικας
        }
    
        /** Construct a default HTML parser. */
        SpecialHtmlParser(string dialect, int maxNesting) {}
    
        /**
         * Σύνοψη της μεθόδου.
         * Εκτενής επεξήγηση της μεθόδου σε πολλαπλές
         * γραμμές.
         */
        public void doSomething() {
    
        int nLines = 0;                // HTML lines in the file
        int nChars = 0                // Number of characters in the file
        int i;
        double averageDensity = 1.;        // Average density of comments in the file
        Car transport;                // Transport to use
    
            for (;;)
                a++;
    
            for (int j = 0; j < 10; j++) {
                a++;
                b++;
            }
    
            while (a < 10) {
                a++;
                b += 12;
            }
    
            while (a < 10) {
                a++;
                for (int i = 0; i < 10; i++)
                    b += 12;
            }
    
            do {
                a++;
                b += 12;
            } while (a < 10);
    
            switch (c) {
            case 'a':
                system.out.println("Alpha");
                break;
            case 'b':
                system.out.println("Bravo");
                break;
            case 'c':
                system.out.println("Charlie");
                break;
            default:
                system.out.println("???");
                break;
            }
    
            if (a == 3) {
                system.out.println("Threee");
                k = 52;
            }
    
            if (a == 3) {
                system.out.println("Three");
                k = 52;
            } else {
                system.out.println("Not three");
                k = 55;
            }
    
            if (a == 3)
                system.out.println("Three");
            else
                system.out.println("Not three");
    
            if (s.equals("a")
                system.out.println("Alpha");
            else if (s.equals("b")
                system.out.println("Bravo");
            else if (s.equals("c")
                system.out.println("Charlie");
            else
                system.out.println("???");
    
            try {
                i = 12;
                o.myMethod();
            } catch (ExceptionClass e) {
                statements;
            } finally {
                statements;
            }
    
        if (a && !b) {
            a = 2 * (3 + 8) % 15;
            k = a.myMethod(q, b, c);
        }
        return k;
    
       /**
        * Returns an Image object that can then be painted on the screen.
        * The url argument must specify an absolute {@link URL}. The name
        * argument is a specifier that is relative to the url argument.
        * <p>
        * This method always returns immediately, whether or not the
        * image exists. When this applet attempts to draw the image on
        * the screen, the data will be loaded. The graphics primitives
        * that draw the image will incrementally paint on the screen.
        *
        * @param  url  an absolute URL giving the base location of the image
        *         name the location of the image, relative to the url argument
        * @return      the image at the specified URL
        * @see         Image
        */
        public Image getImage(URL url, String name) {
            try {
                return getImage(new URL(url, name));
            } catch (MalformedURLException e) {
                return null;
            }
        }
    
         /*
          * A non-javadoc comment with a special keyword
          * (recommended keywords in parenthesis)
          *
          * (XXX, FIXME, TODO): The comment
          */
    
    Σημείωση: οι στηλοθέτες (tab) πρέπει να αντιστοιχούν σε 8 κενά, έστω και αν πάντα η στοίχιση γίνεται σε 4 κενά. Στο διορθωτή vim οι σωστές ρυθμίσεις είναι:
    set shiftwidth=4
    set smarttab
    

    Βιβλιογραφία

    Πρόσθετες πληροφορίες

    Ασκήσεις

    Άσκηση 15

    Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

    Περιεχόμενα