pbp Δημοσ. 11 Ιανουαρίου 2012 Δημοσ. 11 Ιανουαρίου 2012 Γεια σας, έχω μια απορία σχετική με την αντικειμενοστραφή σχεδίαση ενός προγράμματος. Έστω ότι έχω μία κλάση και αυτή περιέχει κάποια πεδία (Ομάδα Α) τα οποία όμως είναι μοναδικά για κάθε αντικείμενο αυτής της κλάσης δηλαδή δεν πρόκειται να χρειαστούμε να τα χρησιμοποιήσουμε χωρίς την κλάση που προανέφερα. Αυτά τα πεδία έχουν τη δική τους συμπεριφορά. Επίσης έχω και κάποια πεδία (Ομάδα Β) τα οποία δεν είναι μοναδικά σε αυτήν την κλάση, δηλαδή η κλάση μπορεί να περιέχει και 2 και 3 σαν αυτά ή μπορεί να περιέχονται ως αντικείμενα και σε άλλες κλάσεις. Φυσικά και αυτά τα πεδία έχουν την δική τους συμπεριφορά. Η ερώτηση μου είναι η εξής: Σύμφωνα με αυτά που περιέγραψα παραπάνω, είναι σωστό με βάση την φιλοσοφία της αντικειμενοστρέφειας να μη δημιουργήσουμε ξεχωριστή κλάση για κάθε πεδίο το οποίο ανήκει στην ομάδα Α που περιέγραψα? Ένα παράδειγμα για να καταλάβετε καλύτερα τι εννοώ: έστω ότι έχω την κλάση "επιτραπέζιο παιχνίδι" και αυτή η κλάση πρέπει να περιέχει ένα ταμπλό (έστω ότι θα το αναπαραστήσουμε με ένα δισδιάστατο πίνακα) και 2 παίκτες. Θα ήταν πιο σωστό να φτιάξω μία κλάση "παίκτης" και να βάλω 2 αντικείμενα "παίκτης" στην κλάση "επιτραπέζιο παιχνίδι" αλλά τον δισδιάστατο πίνακα να τον αφήσω σαν ένα απλό πεδίο της κλάσης "επιτραπέζιο παιχνίδι" ή να φτιάξω και μια κλάση "ταμπλό" και να βάλω ένα αντικείμενο της μέσα στην κλάση "επιτραπέζιο παιχνίδι" ? Ευχαριστώ.
GKNSB Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Από το παράδειγμα σου κατάλαβα τι εννοείς γιατί τα από πάνω τα λες λίγο μπερδεμένα. Με βάση το παράδειγμα σου λοιπόν το λογικό κατ'εμέ θα ήταν το ταμπλό να περιέχεται μέσα σε μια κλάση επιτραπέζιο και ο παίχτης να είναι μια ξεχωριστή κλάση, αντικείμενα της οποίας θα δημιουργείς εσύ όποτε χρειαστείς.
defacer Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Το αν πρέπει να φτιάξεις μια ξεχωριστή class ή όχι για κάτι δεν έχει καθόλου να κάνει με το αν θα το χρησιμοποιήσεις εκτός άλλης class ή όχι και πόσες φορές. Πρέπει να κατανοήσεις ότι ο λόγος που γράφουμε classes δεν είναι για να "λέμε ότι κάνουμε OOP" -- υπάρχουν συγκεκριμένοι στόχοι που θέλουμε να πετύχουμε. Αν λοιπόν όντως θέλεις να πετύχεις κάτι το οποίο το πετυχαίνουμε γράφοντας class, το κάνεις. Διαφορετικά δεν το κάνεις. Επειδή πιθανόν σε μπέρδεψα, συνεχίζω με συγκεκριμένους όρους. Ο λόγους που θα έπαιρνες ένα δισδιάστατο πίνακα και θα τον έβαζες μέσα σε μια class GameΒοard δεν είναι γιατί αν δεν το κάνεις δε γράφεις αντικειμενοστραφή κώδικα. Είναι γιατί θέλεις να βάλεις ένα επίπεδο "μόνωσης" ανάμεσα στον πίνακα (που είναι ο τρόπος με τον οποίο επέλεξες να υλοποιήσεις το ταμπλό) και στον κώδικα που θα χρειαστεί να αλληλεπιδράσει με το ταμπλό. Η μόνωση αυτή ονομάζεται class GameBoard. Τι εννοώ μόνωση; Ας υποθέσουμε ότι έχεις σε διάφορα σημεία του προγράμματός σου έλεγχο για το αν στο τετράγωνο [X,Y] υπάρχει π.χ. λάβα. Υποθέτω επίσης ότι το ταμπλό είναι δισδιάστατος πίνακας από int, όπου λάβα = 42. Οπότε θα έγραφες: >if(table[x][y] == 42) /* blah blah */ Αυτό είναι κακό και θέλουμε να το αποφύγουμε, και αυτός είναι ο λόγος που γράφεις μια class (τέλος πάντων ένας από τους λόγους, αλλά εδώ αυτός είναι ο πρωταγωνιστής). Γιατί όμως είναι κακό; Δες την εναλλακτική λύση: >class GameBoard { private int board[100][100]; // Αυτό φυσικά δε θα το έκανες τόσο ξερά, αλλά χάριν απλότητας... public int GetTerrainType(int x, int y) { return board[x][y]; } } if (board.GetTerrainType(x, y) == 42) /* blah blah */ Αυτό είναι πολύ καλύτερο, γιατί απομονώνει τους "χρήστες" του ταμπλό από την υλοποίηση του ταμπλό. Φαντάσου τι θα γίνει αν κάποια στιγμή αποφασίσεις ότι πρέπει να αλλάξεις την υλοποίηση από πίνακα σε οτιδήποτε άλλο. Τι θα χρειαστεί να κάνεις; Στην πρώτη περίπτωση, θα πρέπει να βρεις σε όλο σου το πρόγραμμα όλα τα σημεία (μπορεί σε ένα μεγάλο πρόγραμμα να μιλάμε για χιλιάδες σημεία) όπου χρησιμοποιείς τον πίνακα ένα-ένα και να αλλάξεις τον σχετικό κώδικα. Στη δεύτερη περίπτωση, θα αλλάξεις το private field και την υλοποίηση της GetTerrainType (2 σημεία) και τέλος. Το παραπάνω είναι μια από τις βασικότερες αρχές σχεδιασμού συστημάτων που ονομάζεται information hiding, και η οποία στον OOP συναντάται υπο τον όρο encapsulation.
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Το αν πρέπει να φτιάξεις μια ξεχωριστή class ή όχι για κάτι δεν έχει καθόλου να κάνει με το αν θα το χρησιμοποιήσεις εκτός άλλης class ή όχι και πόσες φορές. Πρέπει να κατανοήσεις ότι ο λόγος που γράφουμε classes δεν είναι για να "λέμε ότι κάνουμε OOP" -- υπάρχουν συγκεκριμένοι στόχοι που θέλουμε να πετύχουμε. Αν λοιπόν όντως θέλεις να πετύχεις κάτι το οποίο το πετυχαίνουμε γράφοντας class, το κάνεις. Διαφορετικά δεν το κάνεις. Επειδή πιθανόν σε μπέρδεψα, συνεχίζω με συγκεκριμένους όρους. Ο λόγους που θα έπαιρνες ένα δισδιάστατο πίνακα και θα τον έβαζες μέσα σε μια class GameΒοard δεν είναι γιατί αν δεν το κάνεις δε γράφεις αντικειμενοστραφή κώδικα. Είναι γιατί θέλεις να βάλεις ένα επίπεδο "μόνωσης" ανάμεσα στον πίνακα (που είναι ο τρόπος με τον οποίο επέλεξες να υλοποιήσεις το ταμπλό) και στον κώδικα που θα χρειαστεί να αλληλεπιδράσει με το ταμπλό. Η μόνωση αυτή ονομάζεται class GameBoard. Τι εννοώ μόνωση; Ας υποθέσουμε ότι έχεις σε διάφορα σημεία του προγράμματός σου έλεγχο για το αν στο τετράγωνο [X,Y] υπάρχει π.χ. λάβα. Υποθέτω επίσης ότι το ταμπλό είναι δισδιάστατος πίνακας από int, όπου λάβα = 42. Οπότε θα έγραφες: >if(table[x][y] == 42) /* blah blah */ Αυτό είναι κακό και θέλουμε να το αποφύγουμε, και αυτός είναι ο λόγος που γράφεις μια class (τέλος πάντων ένας από τους λόγους, αλλά εδώ αυτός είναι ο πρωταγωνιστής). Γιατί όμως είναι κακό; Δες την εναλλακτική λύση: >class GameBoard { private int board[100][100]; // Αυτό φυσικά δε θα το έκανες τόσο ξερά, αλλά χάριν απλότητας... public int GetTerrainType(int x, int y) { return board[x][y]; } } if (board.GetTerrainType(x, y) == 42) /* blah blah */ Αυτό είναι πολύ καλύτερο, γιατί απομονώνει τους "χρήστες" του ταμπλό από την υλοποίηση του ταμπλό. Φαντάσου τι θα γίνει αν κάποια στιγμή αποφασίσεις ότι πρέπει να αλλάξεις την υλοποίηση από πίνακα σε οτιδήποτε άλλο. Τι θα χρειαστεί να κάνεις; Στην πρώτη περίπτωση, θα πρέπει να βρεις σε όλο σου το πρόγραμμα όλα τα σημεία (μπορεί σε ένα μεγάλο πρόγραμμα να μιλάμε για χιλιάδες σημεία) όπου χρησιμοποιείς τον πίνακα ένα-ένα και να αλλάξεις τον σχετικό κώδικα. Στη δεύτερη περίπτωση, θα αλλάξεις το private field και την υλοποίηση της GetTerrainType (2 σημεία) και τέλος. Το παραπάνω είναι μια από τις βασικότερες αρχές σχεδιασμού συστημάτων που ονομάζεται information hiding, και η οποία στον OOP συναντάται υπο τον όρο encapsulation. κατάλαβα! Μιλάς για ενθυλάκωση και αναπαραγοντοθέτηση. Σε ευχαριστώ πολύ! Θα το σκεφτώ και θα το αναλύσω καλύτερα αυτό που μου είπες!!
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 κατάλαβα! Μιλάς για ενθυλάκωση και αναπαραγοντοθέτηση. Σε ευχαριστώ πολύ! Θα το σκεφτώ και θα το αναλύσω καλύτερα αυτό που μου είπες!! Λοιπόν φίλε μου διάβασα πολύ προσεκτικά όλα αυτά που μου έγραψες και συμφωνώ απόλυτα μαζί σου! Όμως με αυτή σου την απάντηση μ' έκανες να προχωρήσω την απορία μου ένα στάδιο παραπάνω Ας υποθέσουμε λοιπόν, ότι επιλέγω να μη φτιάξω την κλάση GameBoard αλλά επιλέγω να βάλω ένα private δισδιάστατο πίνακα μέσα στην κλάση Game περιγράφοντας την συμπεριφορά του με private & protected μεθόδους (++ Interfaces αν χρειάζεται) μέσα σε αυτή την κλάση. Η διαφορά όμως τώρα θα είναι ότι η κλάση Game που θα φτιάξω θα είναι abstract (και αν υπάρχουν Interfaces θα τα υλοποιεί)! Δηλαδή, για να τη χρησιμοποιήσω θα πρέπει να φτιάξω μία κλάση GameA η οποία θα είναι υποκλάση της Game(έστω μια GameA είναι μία εξειδίκευση του Game). Με αυτόν τον τρόπο εξασφαλίζω το πρόβλημα της ενθυλάκωσης των κελιών του δισδιάστατου πίνακα που ανέφερες παραπάνω? Είναι αντικειμενοστρεφής αυτή η λογική?
defacer Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 κατάλαβα! Μιλάς για ενθυλάκωση και αναπαραγοντοθέτηση. Σε χάνω... δεν ξέρω γιατί το προτιμάς, αλλά θα σου πρότεινα να συνεννοείσαι με την αγγλική ορολογία. Την ξέρουν πολλοί περισσότεροι άνθρωποι στον πλανήτη από την ελληνική, και όποιος ξέρει μόνο την ελληνική δεν αξίζει να τον ακούς. Ας υποθέσουμε λοιπόν, ότι επιλέγω να μη φτιάξω την κλάση GameBoard αλλά επιλέγω να βάλω ένα private δισδιάστατο πίνακα μέσα στην κλάση Game περιγράφοντας την συμπεριφορά του με private & protected μεθόδους (++ Interfaces αν χρειάζεται) μέσα σε αυτή την κλάση. Aυτό που έγραψες εδώ δεν "βγάζει νόημα" ακριβώς. Εξηγούμαι: οτιδήποτε private και protected είναι μέρος της υλοποίησης της κλάσης (δηλαδή είναι απομονωμένο από τους "χρήστες" της). Η υλοποίηση των interfaces όμως είναι μέρος της διεπαφής της κλάσης (αυτό που λέμε "public interface" -- με την αφηρημένη έννοια, όχι με την έννοια "έχω ένα interface ISomething"), δηλαδή αποτελεί ακριβώς αυτό που "βλέπουν" οι χρήστες της κλάσης. Επομένως το να τα βάλεις αυτές τις 2 κατηγορίες που από πλευράς αρχιτεκτονικής είναι η μέρα με τη νύχτα στην ίδια πρόταση μ' αυτό τον τρόπο δεν έχει νόημα. Επιπλέον, δεν έχει σημασία αν οι μέθοδοι που κάνουν κάτι με τον πίνακα είναι public ή όχι. Σημασία έχει ο ίδιος ο πίνακας να μην είναι public. Η διαφορά όμως τώρα θα είναι ότι η κλάση Game που θα φτιάξω θα είναι abstract (και αν υπάρχουν Interfaces θα τα υλοποιεί)! Για ποιό λόγο να είναι ντε και καλά abstract; Γενικά να έχεις υπόψη ότι οι abstract classes είναι κάπως πιο προχωρημένη έννοια -- δεν εννοώ πως είναι κάτι δύσκολο να κατανοήσεις, αλλά είναι δύσκολο να χρησιμοποιήσεις αυτή τη δυνατότητα χωρίς να κάνεις την αρχιτεκτονική σου μπάχαλο όταν είσαι αρχάριος. Επομένως προς το παρόν ξεκίνα με το δεδομένο ότι δεν κάνουμε abstract class παρα μόνο αν μπορείς να διατυπώσεις συγκεκριμένα επιχειρήματα γιατί αυτό που θέλεις να κάνεις δεν γίνεται χωρίς.
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Σε χάνω... δεν ξέρω γιατί το προτιμάς, αλλά θα σου πρότεινα να συνεννοείσαι με την αγγλική ορολογία. Την ξέρουν πολλοί περισσότεροι άνθρωποι στον πλανήτη από την ελληνική, και όποιος ξέρει μόνο την ελληνική δεν αξίζει να τον ακούς. Aυτό που έγραψες εδώ δεν "βγάζει νόημα" ακριβώς. Εξηγούμαι: οτιδήποτε private και protected είναι μέρος της υλοποίησης της κλάσης (δηλαδή είναι απομονωμένο από τους "χρήστες" της). Η υλοποίηση των interfaces όμως είναι μέρος της διεπαφής της κλάσης (αυτό που λέμε "public interface" -- με την αφηρημένη έννοια, όχι με την έννοια "έχω ένα interface ISomething"), δηλαδή αποτελεί ακριβώς αυτό που "βλέπουν" οι χρήστες της κλάσης. Επομένως το να τα βάλεις αυτές τις 2 κατηγορίες που από πλευράς αρχιτεκτονικής είναι η μέρα με τη νύχτα στην ίδια πρόταση μ' αυτό τον τρόπο δεν έχει νόημα. Επιπλέον, δεν έχει σημασία αν οι μέθοδοι που κάνουν κάτι με τον πίνακα είναι public ή όχι. Σημασία έχει ο ίδιος ο πίνακας να μην είναι public. Για ποιό λόγο να είναι ντε και καλά abstract; Γενικά να έχεις υπόψη ότι οι abstract classes είναι κάπως πιο προχωρημένη έννοια -- δεν εννοώ πως είναι κάτι δύσκολο να κατανοήσεις, αλλά είναι δύσκολο να χρησιμοποιήσεις αυτή τη δυνατότητα χωρίς να κάνεις την αρχιτεκτονική σου μπάχαλο όταν είσαι αρχάριος. Επομένως προς το παρόν ξεκίνα με το δεδομένο ότι δεν κάνουμε abstract class παρα μόνο αν μπορείς να διατυπώσεις συγκεκριμένα επιχειρήματα γιατί αυτό που θέλεις να κάνεις δεν γίνεται χωρίς. Καταρχάς, αυτό με το interface πες ότι δεν το έχω αναφέρει καν... Δεν παίζει τόσο ρόλο (λάθος μου που το ανέφερα, παραπέμπει αλλού)... Την κλάση Game την έκανα Abstract για να αναγκάσω κάποιον που θέλει να τη χρησιμοποιήσει, να κληρονομήσει από αυτήν με αποτέλεσμα να προφυλάξω τα private πεδία της κλάσης όπως πχ ο δισδιάστατος πίνακας (θεώρησε το όμως κι αυτό περιττό). Επιστρέφοντας όμως στο πρώτο παράδειγμα, αναφέρεις ότι: "δεν έχει σημασία αν οι μέθοδοι που κάνουν κάτι με τον πίνακα είναι public ή όχι. Σημασία έχει ο ίδιος ο πίνακας να μην είναι public." , συνεπώς με βάση αυτό, από το πρώτο παράδειγμα που είχα αναφέρει, αντί να κάνω ξεχωριστή κλάση GameBoard - μπορώ να κάνω τον δισδιάστατο πίνακα private και να έχω encapsulation ως προς αυτό. Στο πρώτο παράδειγμα που ανέφερα, λέω: "Θα ήταν πιο σωστό να φτιάξω μία κλάση "παίκτης" και να βάλω 2 αντικείμενα "παίκτης" στην κλάση "επιτραπέζιο παιχνίδι" αλλά τον δισδιάστατο πίνακα να τον αφήσω σαν ένα απλό πεδίο της κλάσης "επιτραπέζιο παιχνίδι" ή να φτιάξω και μια κλάση "ταμπλό" και να βάλω ένα αντικείμενο της μέσα στην κλάση "επιτραπέζιο παιχνίδι" ?". Εδώ, παρέλειψα να πω ότι ο δισδιάστατος πίνακας φυσικά θα είναι private πεδίο γιατί το θεώρησα δεδομένο. Άρα, σύμφωνα με αυτά, συμφωνείς με αυτό που λέει ο πρώτος φίλος. Σωστά?
Aztec Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Η ερώτηση που καταλαβαίνω πάντως εγώ είναι η εξής Αν μεταφέρω όλη την gameboard class δηλαδή τον πίνακα και όλες τις μεθόδους διαχείρισης στην gameclass και ο κώδικας κάνει χρήση μονο των μεθόδων αυτών δεν υπάρχει πρακτικά encapsulation ? Καλά μπορεί και να μην κατάλαβα ορθά Η λογική και καθαρή λύση είναι αυτή του defacer παντως
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Η ερώτηση που καταλαβαίνω πάντως εγώ είναι η εξής Αν μεταφέρω όλη την gameboard class δηλαδή τον πίνακα και όλες τις μεθόδους διαχείρισης στην gameclass και ο κώδικας κάνει χρήση μονο των μεθόδων αυτών δεν υπάρχει πρακτικά encapsulation ? Καλά μπορεί και να μην κατάλαβα ορθά Αυτή είναι η μισή ερώτηση (που προκύπτει έμμεσα). Η άλλη μισή "Σύμφωνα με αυτά που περιέγραψα παραπάνω, είναι σωστό με βάση την φιλοσοφία της αντικειμενοστρέφειας να μη δημιουργήσουμε ξεχωριστή κλάση για κάθε πεδίο το οποίο ανήκει στην ομάδα Α που περιέγραψα?" αφορά κυρίως την ΣΥΝΟΧΗ (COHESION) του προγράμματος. Γι αυτό άλλωστε ρωτάω αν είναι σωστό αυτο που λέω με βάση την αντικειμενοστρεφή φιλοσοφία ή ξεφεύγει απο τα πλαίσια αυτής - Είναι ερώτηση του τύπου: έχω μία κλάση > class Person{ private String name; private int age; // constructor // getters/setters methods } και ρωτάω. Να βάλω πχ το πεδίο name έτσι όπως το έχω ή να κάνω μια καινούρια κλάση name? Φυσικά εδώ το παράδειγμα είναι τόσο απλό που δεν τίθεται θέμα - O defacer υποστηρίζει πως "Το αν πρέπει να φτιάξεις μια ξεχωριστή class ή όχι για κάτι δεν έχει καθόλου να κάνει με το αν θα το χρησιμοποιήσεις εκτός άλλης class ή όχι και πόσες φορές." αλλά παρόλα αυτά νομίζω ότι πρέπει να μας ενδιαφέρει και η ΣΥΖΕΥΞΗ(COUPLING) και η ΣΥΝΟΧΗ(COHESION) του προγράμματος και της σχεδίασης μας
Aztec Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Η προσέγγιση του defacer έχει loose coupling και high cohesion άρα θα έπρεπε να συμφωνείτε
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Η προσέγγιση του defacer έχει loose coupling και high cohesion άρα θα έπρεπε να συμφωνείτε Ναι αλλά δεν έχω καταλάβει αν ο άλλος ο τρόπος θεωρείται σωστός :/ O defacer υποστηρίζει πως η προσέγγισή του είναι ορθή από άποψη encaptulation(αλλά και στον πρώτο τρόπο private θα ήταν ούτως η άλλως ο δισδιάστατος πίνακας). Δεν αναφέρεται σε συνοχή και σύζευξη.
defacer Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Την κλάση Game την έκανα Abstract για να αναγκάσω κάποιον που θέλει να τη χρησιμοποιήσει, να κληρονομήσει από αυτήν με αποτέλεσμα να προφυλάξω τα private πεδία της κλάσης όπως πχ ο δισδιάστατος πίνακας (θεώρησε το όμως κι αυτό περιττό). Θα το σχολιάσω μιας και το συζητάμε. Αν κάποιος κληρονομήσει από την κλάση τότε τα private members είναι προφυλαγμένα έτσι κι αλλιώς. Αν πάλι δεν κληρονομήσει τότε είναι προφυλαγμένα γιατί όλος ο κώδικας μέσα στην κλάση είναι δικός σου, και όχι αυτού που έφτιαξε το αντικείμενο. Οπότε το abstract δεν έχει να κάνει μ' αυτό. Να ξέρεις πως ένα από τα δυσκολότερα πράγματα στην αρχιτεκτονική του OOP για τους λιγότερο έμπειρους είναι να ξέρουν πότε πρέπει να κληρονομήσουν και πότε όχι, καθώς τι πρέπει να είναι private και τι protected και τι virtual σε μια class. Γενικά σε μια σωστά σχεδιασμένη class μπορείς όταν αποκτήσεις εμπειρία να καταλάβεις βλέποντας τον κώδικά της αν υποτίθεται ότι πρέπει να κληρονομήσεις απ' αυτήν ή όχι. Εξυπακούεται ότι αφού χρειάζεται εμπειρία για να το καταλάβεις, χρειάζεται διπλάσια εμπειρία για να φτιάξεις την κλάση "σωστά" έτσι ώστε να το καταλαβαίνουν άλλοι όταν τη διαβάζουν. Επιστρέφοντας όμως στο πρώτο παράδειγμα, αναφέρεις ότι: "δεν έχει σημασία αν οι μέθοδοι που κάνουν κάτι με τον πίνακα είναι public ή όχι. Σημασία έχει ο ίδιος ο πίνακας να μην είναι public." , συνεπώς με βάση αυτό, από το πρώτο παράδειγμα που είχα αναφέρει, αντί να κάνω ξεχωριστή κλάση GameBoard - μπορώ να κάνω τον δισδιάστατο πίνακα private και να έχω encapsulation ως προς αυτό. Ναι, αλλά μετά πάλι καταλήγουμε να παίζουμε την κολοκυθιά: μήπως τώρα ο κώδικας της ίδιας σου της κλάσης πρόκειται να γίνει πολύ coupled με την συγκεκριμένη αναπαράσταση του game board? Αν ναι, βάζεις άλλο ένα επίπεδο abstraction κάνοντας το GameBoard κλάση όπου ο πίνακας είναι private μέσα της κλπ. Γενικά το τι είναι "σωστό" εξαρτάται άμεσα από το τι σκοπούς και ορίζοντες έχει ο κώδικας που γράφεις. Όσο τραγικό είναι το να κάνεις couple όλο το σύμπαν με το δισδιάστατο πίνακα σχεδόν άλλο τόσο άσχημο είναι το να φτιάξεις μια αρχιτεκτονική με 100 interfaces και 200 classes χωρίς λόγο. Στο πρώτο παράδειγμα που ανέφερα, λέω: "Θα ήταν πιο σωστό να φτιάξω μία κλάση "παίκτης" και να βάλω 2 αντικείμενα "παίκτης" στην κλάση "επιτραπέζιο παιχνίδι" αλλά τον δισδιάστατο πίνακα να τον αφήσω σαν ένα απλό πεδίο της κλάσης "επιτραπέζιο παιχνίδι" ή να φτιάξω και μια κλάση "ταμπλό" και να βάλω ένα αντικείμενο της μέσα στην κλάση "επιτραπέζιο παιχνίδι" ?". Εδώ, παρέλειψα να πω ότι ο δισδιάστατος πίνακας φυσικά θα είναι private πεδίο γιατί το θεώρησα δεδομένο. Άρα, σύμφωνα με αυτά, συμφωνείς με αυτό που λέει ο πρώτος φίλος. Σωστά? Ο πρώτος φίλος δεν λέει ακριβώς αυτό (σκόπιμα ή όχι δε μπαίνει σε όλη αυτή τη λεπτομέρεια). Όταν λες ότι από τη μία θα βάλεις αντικείμενα "παίκτης" στην "επιτραπέζιο" ενώ από την άλλη το ταμπλό δε θα είναι αντικείμενο αλλά ξερός πίνακας, ασυνείδητα ίσως παίρνεις την απόφαση πως η μοντελοποίηση ενός παίκτη θα είναι αρκετά περίπλοκη και γι' αυτό βάζεις μια class για να έχεις encapsulation κλπ, ενώ η μοντελοποίηση του ταμπλό δεν είναι. Αυτή η απόφαση καλό είναι να παίρνεται συνειδητά και όχι ασυνείδητα. Θεωρώντας δεδομένο ότι μιλάμε για ένα συγκεκριμένο παιχνίδι (δηλαδή ότι αντικείμενα της κλάσης Game θα αναφέρονται σε διαφορετικές παρτίδες του ίδιου όμως πάντα παιχνιδιού), τότε θα σου πρότεινα να κάτσεις και να γράψεις ένα interface IGameBoard και να δεις ποιές είναι όλες οι μέθοδοι που θα πρέπει να έχει αυτό για να υλοποιήσεις το παιχνίδι βάσει τον κανόνων που έχει. Αν δεις ότι η υλοποίηση όλων αυτών των μεθόδων χρειάζεται παραπάνω από μια γραμμή κώδικα έκαστη, τότε κάνε class αντί για πίνακα. Το IGameBoard μπορείς να το κρατήσεις ή να το πετάξεις. Το ανέφερα βασικά σαν βοήθημα σκέψης, στην προκειμένη δε θα σου προσφέρει κάτι χειροπιαστό όταν καταλήξεις τι θέλεις να κάνεις και μετά. Η άλλη μισή "Σύμφωνα με αυτά που περιέγραψα παραπάνω, είναι σωστό με βάση την φιλοσοφία της αντικειμενοστρέφειας να μη δημιουργήσουμε ξεχωριστή κλάση για κάθε πεδίο το οποίο ανήκει στην ομάδα Α που περιέγραψα?" αφορά κυρίως την ΣΥΝΟΧΗ (COHESION) του προγράμματος. Γι αυτό άλλωστε ρωτάω αν είναι σωστό αυτο που λέω με βάση την αντικειμενοστρεφή φιλοσοφία ή ξεφεύγει απο τα πλαίσια αυτής Σύμφωνα με τη "φιλοσοφία" της αντικειμενοστρέφειας θα πρέπει να έχεις class για τα πάντα, μη σου πω και interface που υλοποιεί η class. Δεν πρέπει όμως να ξεχνάμε ότι όλα αυτά είναι εργαλεία για να κάνουμε τη δουλειά μας και όχι αυτοσκοπός. Αν έχει κάτι να σου προσφέρει το κάνεις, αλλιώς το αφήνεις. Τέλος δεν είμαι σίγουρος τι εννοείς "συνοχή" -- ένα παράδειγμα;
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Τέλος δεν είμαι σίγουρος τι εννοείς "συνοχή" -- ένα παράδειγμα; Η συνοχή αφορά τον αριθμό και την ποικιλία των εργασιών μιας μονάδας κώδικα (μέθοδος,κλάση,πακέτο). Καλή σχεδίαση --> υψηλή συνοχή.
Aztec Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Η συνοχή αφορά τον αριθμό και την ποικιλία των εργασιών μιας μονάδας κώδικα (μέθοδος,κλάση,πακέτο). Καλή σχεδίαση --> υψηλή συνοχή. Λάθος είναι πόσο επικεντρωμένο σε έναν σκοπό είναι ένα module .Όχι ποικιλία. Αυτό συνεπάγεται πολλά όπως reusabily, readability , maintenance. Στην συγκεκριμένη περίπτωση το Gameboard είναι αρκετά focus ενώ η Gameclass αρχίζει να μπαχαλέυει με μεθόδους που είναι εστιασμένες σε συγκεκριμένους διαφορετικούς σκοπούς. Δηλαδή αν βάλεις δέκα κλάσεις σε μία θα παίξει. Το cohesion όμως θα πάει περίπατο.
pbp Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Λάθος είναι πόσο επικεντρωμένο σε έναν σκοπό είναι ένα module .Όχι ποικιλία. Αυτό συνεπάγεται πολλά όπως reusabily, readability , maintenance. Στην συγκεκριμένη περίπτωση το Gameboard είναι αρκετά focus ενώ η Gameclass αρχίζει να μπαχαλέυει με μεθόδους που είναι εστιασμένες σε συγκεκριμένους σκοπούς. Δηλαδή αν βάλεις δέκα κλάσεις σε μία θα παίξει. Το cohesion όμως θα πάει περίπατο. Αν βάλεις 10 κλάσεις σε μία πάει περίπατο το cohesion ++ το coupling μιας και από τη στιγμή που συνδέεις μία κλάση με άλλες 10 δεν επιδιώκεις loose coupling. Αλλά τι να κάνεις σε μία τέτοια περίπτωση που μια κλάση "του τύπου" Gameclass πρέπει να χρησιμοποιεί όλες τις υπόλοιπες όπως και να χει
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα