Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα και πάλι..στο συννημένο αρχείο έχω ενδεικτικα 3 πίνακες της βάσης. Κάθε πίνακας έχει πρωτεύων κλειδί ένα id το οποίο είναι αυτόματη αρίθμηση. Χρειάζεται να σπάσω τους πίνακες?σχετικά με την κανονικοποίηση αναφέρομαι.

ΠΙΝΑΚΕΣ SQL.pdf

Δημοσ.

Πως μπορούμε να ξέρουμε αν το σχήμα σου είναι σωστό, αφού δεν ξέρουμε τις προδιαγραφές/απαιτήσεις;

Παραθέτεις ένα σχήμα, και ζητάς να σου πούμε αν αυτή είναι η σωστή απάντηση σε μια άγνωστη ερώτηση!

Δημοσ.

Σ' αυτή την περίπτωση να σε ενημερώσω ότι το (2) έχει το τεράστιο μειονέκτημα πως με τον τρόπο αυτό το σχετικό business logic της εφαρμογής σου αντί να είναι όλο όμορφα μαζεμένο σε κάποια function σκορπίζεται όχι απλά απο δω κι απο κει αλλά ανάμεσα σε τελείως διαφορετικά πράγματα (τον κώδικα και το σχήμα της βάσης).

εδώ θα διαφωνήσω μαζί σου, πράγμα που είναι εξαιρετικά σπάνιο.

ο trigger γράφεται μια φορά και κρατάς για πάντα. (ή έως φτάσει η ώρα για αλλαγή στο schema)

 

αντιθέτως... αν πας με τον #1 τρόπο, κάθε φορά που θα κάνεις insert, θα χρειάζεται να κάνεις και τα υπόλοιπα...

  • Like 1
Δημοσ.

αντιθέτως... αν πας με τον #1 τρόπο, κάθε φορά που θα κάνεις insert, θα χρειάζεται να κάνεις και τα υπόλοιπα...

Δεν καταλαβαίνω την ουσία αυτής της αντίρρησης. Με το φτυάρι θα τα κάνεις; Θα έχεις κάπου μια function create user. Τι σημασία έχει αν αυτή κάνει 1 insert ή 10; Εσύ έτσι κι αλλιώς μία φορά θα το γράψεις, όπως ακριβώς και αν το κάνεις με trigger.

Δημοσ.

Δεν καταλαβαίνω την ουσία αυτής της αντίρρησης. Με το φτυάρι θα τα κάνεις; Θα έχεις κάπου μια function create user. Τι σημασία έχει αν αυτή κάνει 1 insert ή 10; Εσύ έτσι κι αλλιώς μία φορά θα το γράψεις, όπως ακριβώς και αν το κάνεις με trigger.

Αν υποθέσεις ότι το interface σου θα είναι η μόνη "οντότητα" που θα κάνει ποτέ connect στη βάση, τότε έχεις δίκιο.

Αλλά πόσο συχνά συμβαίνει αυτό;

  • Κάποτε θα μπεις από ένα management console και θα κάνεις ένα insert, ξεχνώντας ότι πρέπει να ενημερώσεις και τους υπόλοιπους πίνακες. Αλλά κι αν το θυμηθείς, θα πρέπει να το κάνεις με το χέρι, και είσαι και άνθρωπος, και κάνεις και λάθη κλπ κλπ
  • Κάποτε θα βάλεις να εκτελείται κάτι από ένα cron job, ίσως φτιαγμένο ακόμα και σε άλλη γλώσσα, και θα πρέπει να θυμηθείς να γράψεις την αντίστοιχη create user και εκεί.
  • Κάποτε θα προσθέσεις άλλον ένα πίνακα στη βάση, ο οποίος θα πρέπει επίσης να ενημερώνεται, και θα πρέπει να γυρίσεις όλα τα προγραμματάκια που έχεις φτιάξει για να τροποποιήσεις την αντίστοιχη κατά τόπους create user.
  • Και κάποτε θα χρειαστεί, από την ίδια την εφαρμογή σου, να κάνεις άλλο ένα insert από άλλο σημείο, και θα ξεχάσεις την create user και θα κάνεις καρφωτό insert.

 

Ύστερα, υπάρχουν και τα transactions. Συνήθως, αν για ΧΨ λόγους αποτύχει ο trigger, το transaction κάνει rollback και δεν ενημερώνεται τίποτα. Ενώ αν διακοπεί η create user στη μέση, μένουν τα δεδομένα σου ξεκρέμαστα.

Ξέρω, υπάρχει τρόπος να φτιάξεις transaction και προγραμματιστικά, αλλά γιατί να το κάνεις;

 

Disclaimer: Είμαι εντελώς κατά των triggers για ακεραιότητα δεδομένων τέτοιου τύπου, και δεν ξέρω την αναγκαιότητα η οποία τους επιβάλλει στην προκειμένη περίπτωση. Όμως, γεγονός είναι ότι υπάρχουν για κάποιο λόγο, και αν τους καταργείς μεταφέροντας τη λειτουργία τους στο interface, νομίζω ότι κάτι κάνεις λάθος...

Δημοσ.

Κάποτε θα μπεις από ένα management console και θα κάνεις ένα insert, ξεχνώντας ότι πρέπει να ενημερώσεις και τους υπόλοιπους πίνακες. Αλλά κι αν το θυμηθείς, θα πρέπει να το κάνεις με το χέρι, και είσαι και άνθρωπος, και κάνεις και λάθη κλπ κλπ

Όχι, δε θα το κάνω ποτέ αυτό.  :)

 

Όσες φορές χρειάστηκε προτίμησα να γράψω ένα throwaway script (μιλάμε για 10 γραμμές max) που κάνει τη δουλειά μέσω του κανονικού code base.

 

Γενικότερα, σε production εφαρμογή το να μπαίνεις μέσα με το χέρι απαγορεύεται δια ροπάλου τελεία και παύλα.

 

 

 

Το έκανα μια φορά όταν ήμουν μικρός και το αποτέλεσμα ήταν να γίνουν reset τα passwords για ~3000 users. Ψύχραιμος γυρνάω στον sysadmin και του λέω στο χαλαρό "να σου πω, το τελευταίο backup της βάσης από πότε είναι?". Μετά από αυτό έχω πάντα ένα checklist 3 σημείων για το access με το χέρι:

  1. Don't do it.
  2. Seriously, don't do it.
  3. Τουλάχιστον βάλε ένα syntax error στο query που γράφεις επίτηδες με το καλημέρα ούτως ώστε αν κατα λάθος το στείλεις να χτυπήσει και να φύγει άσφαιρο.

 

 

 

Σε non production ακόμα κι αν το κάνεις για κάποιο λόγο δεν έγινε τίποτα.

 

Κάποτε θα βάλεις να εκτελείται κάτι από ένα cron job, ίσως φτιαγμένο ακόμα και σε άλλη γλώσσα, και θα πρέπει να θυμηθείς να γράψεις την αντίστοιχη create user και εκεί.

 

Γιατί όμως να είναι φτιαγμένο σε άλλη γλώσσα; Αφού μπορώ να βάλω στο cron να εκτελεί οτι θέλω.

 

Κάποτε θα προσθέσεις άλλον ένα πίνακα στη βάση, ο οποίος θα πρέπει επίσης να ενημερώνεται, και θα πρέπει να γυρίσεις όλα τα προγραμματάκια που έχεις φτιάξει για να τροποποιήσεις την αντίστοιχη κατά τόπους create user.

 

DRY. Μόνο σε ένα σημείο θα υπάρχει ο κώδικας για την create user.

 

Και κάποτε θα χρειαστεί, από την ίδια την εφαρμογή σου, να κάνεις άλλο ένα insert από άλλο σημείο, και θα ξεχάσεις την create user και θα κάνεις καρφωτό insert.

Σε καμία απολύτως περίπτωση. Αυτό που γίνεται είναι πως υπάρχει μια π.χ. class UserModel η οποία είναι μοναδικός αρμόδιος για οτιδήποτε έχει να κάνει με user. Αν αρχίσεις και γράφεις SQL με το χέρι εκτός της class αυτής έχεις φύγει από το παράθυρο. 

 

Για τα transactions που λες, θα έχεις έτσι κι αλλιώς transaction παντού (σε κάποιο αρκετά "ψηλά στην ιεραρχία" σημείο). Και αυτό θα το κάνεις διότι αν δεν το κάνεις θα πρέπει να θυμάσαι να βάλεις transaction εκεί που είναι απαραίτητο, πράγμα το οποίο μπορεί να ξεχάσεις. Σε περίπτωση που χρειαστεί για οποιοδήποτε λόγο κάτι να γίνει χωρίς transaction, θα κάνεις το transaction να είναι opt-out. Έτσι και δεν υπάρχει περίπτωση να το ξεχάσεις, και αν θέλεις να βγάλεις τα μάτια σου μπορείς αλλά τουλάχιστον θα πρέπει να το κάνεις με τα χέρια σου.

 

Δε θέλω να πω ότι τέτοιου είδους triggers είναι άχρηστα, υπάρχουν σενάρια τα οποία δεν κάλυψα παραπάνω (π.χ. πρόσβαση στη βάση από πολλές εφαρμογές που δεν είναι όλες υπό τον άμεσο έλεγχό σου, αν και σ' αυτή την περίπτωση πάλι υπάρχουν non-trigger λύσεις όπως stored procedures και αφαίρεση "άμεσου" write access από το χρήστη). Αλλά εμένα δε μου "χρειάστηκαν" ποτέ, με την έννοια ότι πάντα υπήρχε άλλη λύση που θεωρώ καλύτερη.

Δημοσ.

Τώρα περιγράφεις μία ουτοπία....

 

Υπάρχουν πολλές περιπτώσεις που θα μπεις με management console σε production βάση - εγώ το κάνω μέρα παρά μέρα. Και αν μπορούσα να το αποφύγω δεν θα το έκανα, αλλά καμιά φορά δεν είναι στο χέρι σου...

Αλλά σκέψου το: Μήπως εσύ δεν θα το έκανες, ακριβώς διότι δεν θα υπήρχαν οι ανάλογοι triggers/constraints και οτιδήποτε άλλο σε προστατεύει από τον Mr Hyde μεσα σου;

 

Υπάρχουν λόγοι για τους οποίους θα πρέπει να φτιαχτούν διάφορα utilities σε διάφορες γλώσσες.

Ο απλούστερος; Δουλεύει ένα team για την εφαρμογή. O ένας ξέρει php και ο άλλος .net. Γιατί να μην μπορεί να είναι ο καθένας πιο παραγωγικός με αυτό που νοιώθει πιο άνετα; Γιατί να τους περιορίσεις στη χρήση ενός συγκεκριμένου codebase;

Αλλά κι όταν δίνεις ανοικτή πρόσβαση στη βάση σου, ώστε να μπορεί ο καθένας να φτιάξει το δικό του interface, για ένα μέρος μόνο του συστήματος. Πχ έχεις μία enterprise βάση, και ο ένας φτιάχνει τη μισθοδοσία, ο άλλος το πελατολόγιο, ο άλλος maintenance utilities, ο άλλος web interface για e-shop... Εκεί, το μόνο "κοινό codebase" είναι... η ίδια η βάση!

 

Και όσες κλάσεις και να φτιάξεις, κάποια στιγμή θα πεις "έλα μωρε, δεν βαριέσαι... ας το κάνω QnD..." Ή αυτός που θα αναλάβει μετά από σένα, θα αρχίσει να γράφει κώδικα πριν μάθει καλά την κλάση σου, γιατί βαριέται να διαβάσει το documentation που του άφησες.

 

Κι αν φτιάξεις μία stored procedure, έχεις κάνει το 90% της δουλειάς για τον trigger. Το να τη μετατρέψεις σε trigger είναι το πρόβλημα;

 

Αυτά που είπα, τα είπα γιατί τα βλέπω σε καθημερινή βάση. Μακάρι να ήμασταν όλοι τόσο πειθαρχημένοι όσο το περιγράφεις, αλλά η πραγματικότητα είναι άλλη. Μηχανισμοί σαν τους triggers έχουν εφευρεθεί για να μας προστατεύουν από τους εαυτούς μας, και το κάνουν πολύ καλά.

 

Και στην τελική, τι πιο DRY από τον trigger;

Δημοσ.

Δε με έχεις πείσει ομολογώ αλλά εφόσον εκθέσαμε και αιτολογήσαμε τις απόψεις μας νομίζω πως μπορούμε να το αφήσουμε εδώ και να πάμε να πιούμε μπύρες.
 
Δύο πράγματα μόνο:
 

Και όσες κλάσεις και να φτιάξεις, κάποια στιγμή θα πεις "έλα μωρε, δεν βαριέσαι... ας το κάνω QnD..."


Ποτέ. Π Ο Τ  Ε (εκτός βέβαια κι αν το QnD είναι παραγγελία από τον PM). Το αν και πόσο συχνά θα κάνεις κάτι τέτοιο είναι μέρος της επαγγελματικής σου ταυτότητας. Η δική μου θέλω να λέει ότι απο αυτόν τον κύριο θα πάρεις μόνο την καλύτερη δουλειά που μπορεί να αγοράσει το χρήμα.  ;) 
 

Ή αυτός που θα αναλάβει μετά από σένα, θα αρχίσει να γράφει κώδικα πριν μάθει καλά την κλάση σου, γιατί βαριέται να διαβάσει το documentation που του άφησες.

 
Ε και τι να κάνουμε τώρα; Να λειτουργούμε με βάση το ότι μετά απο μας θα έρθει ούγκανος;

 

Κι αν φτιάξεις μία stored procedure, έχεις κάνει το 90% της δουλειάς για τον trigger. Το να τη μετατρέψεις σε trigger είναι το πρόβλημα;


Η λεπτή διαφορά είναι πως με τη SP (θα έπρεπε να) είναι φανερό σε όλους όσους την καλούν πως από πίσω γίνονται πράγματα, αλλιώς δε θα είχε γραφτεί η SP. Με το trigger δεν υπάρχει τέτοια "προειδοποίηση".

Δημοσ.

Ούγκανος ξε-ούγκανος, η δική σου δουλειά είναι να διασφαλίσεις την ακεραιότητα του συστήματος. No matter what. Period.

 

Και δεν θα έπρεπε να είναι φανερό σε κανέναν τίποτα, ούτε να λαμβάνει κανενός είδους "προειδοποιήσεις", για μία λειτουργία που εκτελείται στο background και δεν ενδιαφέρει κανέναν (εκτός από αυτόν που τη σχεδίασε) τι γίνεται σαν συνέπεια ενός insert.

Μαύρο κουτί!

 

Όσο για τα "ποτέ των ποτών", μεγάλη μπουκιά φάε, μεγάλη κουβέντα μην πεις.

 

Και κάτι τελευταίο: Η δουλειά του προγραμματιστή είναι να επιβάλλει κανόνες στη μηχανή. Όχι το αντίστροφο!

Σκέψου το...

Δημοσ.

Ούγκανος ξε-ούγκανος, η δική σου δουλειά είναι να διασφαλίσεις την ακεραιότητα του συστήματος. No matter what. Period.

Να τη διασφαλίσω αλλά μέχρι ενός σημείου που είναι λογικό. Με την ίδια λογική μπορεί ο ούγκανος να βγάλει το trigger από τη database.

 

Στην τελική αυτός που φυλάει τα πρόβατα μπορεί να κλέψει πρόβατο. Ο,τι κι αν κάνεις αυτό δεν αλλάζει.

 

Και δεν θα έπρεπε να είναι φανερό σε κανέναν τίποτα, ούτε να λαμβάνει κανενός είδους "προειδοποιήσεις", για μία λειτουργία που εκτελείται στο background και δεν ενδιαφέρει κανέναν (εκτός από αυτόν που τη σχεδίασε) τι γίνεται σαν συνέπεια ενός insert.

Μαύρο κουτί!

Διαφωνώ. Πες ότι γράφεις σε μια γλώσσα που επιτρέπει user-defined properties στις κλάσεις. Κανείς δε σε εμποδίζει να γράψεις μια property της οποίας ο getter κάνει πράγματα τα οποία είναι observable απ' έξω, και αν το κάνεις (αντί να γράψεις μια method της οποίας η κλήση είναι implicit συμβόλαιο πως τώρα που με κάλεσες μπορεί να κάνω ότι μου αρέσει) τότε φταις.

 

Κλασικό παράδειγμα λάθους το DateTime.Now σε .NET το οποίο είναι property αλλά θα έπρεπε να είναι method διότι το άτυπο συμβόλαιο για μια property είναι ότι αν δεν την πειράξεις εσύ δεν πειράζεται μόνη της.

 

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

 

Καταλαβαίνω τη θέση σου περι μαύρου κουτιού (και γενικά συμφωνώ) αλλά πρέπει να καταλαβαίνεις και συ πως όταν το ένα προβατάκι είναι διαφορετικό από όλα τα άλλα, όταν κινείσαι κοντά του πρέπει να είσαι σε εγρήγορση.

 

Όσο για τα "ποτέ των ποτών", μεγάλη μπουκιά φάε, μεγάλη κουβέντα μην πεις.

ΟΚ, αλλά στόχους που δεν βάζεις δεν τους πετυχαίνεις κιόλας.

 

Και κάτι τελευταίο: Η δουλειά του προγραμματιστή είναι να επιβάλλει κανόνες στη μηχανή. Όχι το αντίστροφο!

Σκέψου το...

Δε νομίζω πως είπα ότι η μηχανή επιβάλλει κανόνες ή κάτι ανάλογο. Απλά διαφωνούμε στο ποιό "πλεονέκτημα" μετράει περισσότερο.

Δημοσ.

Να τη διασφαλίσω αλλά μέχρι ενός σημείου που είναι λογικό. Με την ίδια λογική μπορεί ο ούγκανος να βγάλει το trigger από τη database.

 

Αν τον βγάλει, εσύ συνεχίζεις να έχεις κάνει τη δουλειά σου.

Αν δεν τον βάλεις, δεν έχεις πάρει όλα τα μέτρα που θα έπρεπε.

 

Δε νομίζω πως είπα ότι η μηχανή επιβάλλει κανόνες ή κάτι ανάλογο. Απλά διαφωνούμε στο ποιό "πλεονέκτημα" μετράει περισσότερο.

 

Λοιπόν:

  • Δεν θα μπω ποτέ από management console (κι έχω και checklist)
  • Θα χρησιμοποιώ πάντα το ίδιο codebase για οτιδήποτε κάνει πρόσβαση στη βάση
  • Θα φτιάξω ένα UserModel και τα πάντα θα τα κάνω με αυτό
  • Δεν θα κάνω ποτέ τίποτα QnD
  • Seriously, όλα τα παραπάνω

Κανόνες;;; Σαν όρκος μου ακούγεται.

"Ομνύω εις το όνομα του ενός και μοναδικού codebase..."

 

Εμένα πάλι, μου αρέσει να σουλατσάρω στις κονσόλες και, όταν θέλω να εισάγω ένα item, να λέω απλά "insert into item". Και ξέρω ότι τα ρέστα θα τα φροντίσει ο "δούλος" από πίσω. Και δεν θα σπάσω τα αυγά.

 

Όταν κάποιος με ρωτά "αν το φτιάξω αυτό σε perl, θα υπάρξει πρόβλημα;" του λέω "Δεν πα' να το φτιάξεις και σε Σανσκριτικά; Τι με νοιάζει εμένα;"

 

Γράφω μια ρουτίνα, μια κλάση, ένα model, και μετά αν είμαι στα κέφια μου το γράφω σε 3-4 παραλλαγές, έτσι, απλά διότι "what if..." Και δεν θέλω να χρειάζεται να θυμάμαι πολλά πράγματα.

 

Ξέρω (και μ' αρέσει) ότι κάποιες φορές θα είμαι τυπικός και κάποιες φορές ούγκανος. Και θέλω να έχω την επιλογή, χωρίς να έχω επιπτώσεις στη δουλειά μου.

 

Δεν είναι λοιπόν θέμα σύγκρισης πλεονεκτημάτων. Για μένα τουλάχιστον, η επιλογή αυτού του τρόπου δουλειάς νοιώθω ότι μου προσφέρει την ελευθερία που χρειάζομαι.

 

Και φυσικά, την άποψή μου λέω, και δεν υποστηρίζω σε καμία περίπτωση ότι το ένα είναι σωστό και το άλλο λάθος. Στο κάτω-κάτω, όλα είναι θέμα επιλογών, έτσι;

 

Άσχετο: Καλά, εσύ δεν θα πήγαινες για μπύρα; :D

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...