Άρθρο
Σύγκριση τμημάτων κώδικα χωρίς μεταφόρτωση
Κάθε φορά που επικολλάτε δύο αρχεία σε ένα online εργαλείο diff, αυτός ο κώδικας φεύγει από τη μηχανή σας. Αρχεία ρύθμισης, ερωτήματα βάσεων δεδομένων, κλειδιά API θαμμένα σε ένα τμήμα .env: όλα ταξιδεύουν σε έναν διακομιστή που δεν ελέγχετε. Αυτό το άρθρο καλύπτει πώς λειτουργούν οι αλγόριθμοι diff, τι σημαίνουν οι επιλογές κοκκομετρίας στην πράξη, και γιατί έχει σημασία να κρατάτε τη σύγκριση τοπική.
Τι υπολογίζει ένα Diff
Ένα εργαλείο diff παίρνει δύο κείμενα και βρίσκει το ελάχιστο σύνολο αλλαγών που μετατρέπει το ένα στο άλλο. Η βασική ιδέα είναι η μεγαλύτερη κοινή υπακολουθία, ή LCS: η μεγαλύτερη ακολουθία γραμμών (ή tokens) που εμφανίζεται και στα δύο κείμενα με την ίδια σειρά, ακόμα και αν δεν είναι γειτονικές. Κάθε τι που δεν ανήκει σε αυτή την κοινή υπακολουθία είναι είτε προσθήκη στη νέα έκδοση είτε διαγραφή από την παλιά. Ο κλασικός αλγόριθμος για αυτό οφείλεται στον Myers (1986), ο οποίος βρίσκει το συντομότερο script επεξεργασίας σε χρόνο O((N+M)D), όπου N και M είναι τα μήκη των δύο κειμένων και D είναι ο αριθμός των επεξεργασιών. Στην πράξη, τα περισσότερα εργαλεία προσθέτουν ένα βήμα προεπεξεργασίας για να αγνοήσουν τις κοινές γραμμές στην αρχή και στο τέλος, μειώνοντας το πρόβλημα στην περιοχή που άλλαξε. Το αποτέλεσμα είναι ένα patch: μια ακολουθία hunks, καθένα από τα οποία περιγράφει ένα συνεχόμενο τμήμα γραμμών πλαισίου, διαγραφών και προσθηκών. Αυτή είναι η μορφή που χρησιμοποιείται από το Unix diff, το Git και τα περισσότερα εργαλεία αναθεώρησης κώδικα.

Κοκκομετρία γραμμής, λέξης και χαρακτήρα
Η κοκκομετρία ενός diff καθορίζει τι μετράει ως μονάδα σύγκρισης. Το diff βάσει γραμμής είναι η προεπιλογή στα περισσότερα εργαλεία: κάθε γραμμή αντιμετωπίζεται ως ένα μόνο token. Αυτό είναι γρήγορο και παράγει αποτέλεσμα εύκολο να διαβαστεί στο πλαίσιο, αλλά σημειώνει ολόκληρη τη γραμμή ως αλλαγμένη ακόμα και αν άλλαξε μόνο μία λέξη σε αυτή. Το diff σε επίπεδο λέξης χωρίζει κάθε γραμμή σε λέξεις πριν εκτελέσει LCS. Αυτό δίνει μια λεπτομερέστερη εικόνα του τι άλλαξε μέσα σε μια γραμμή, που είναι χρήσιμο για πεζό κείμενο, τιμές ρύθμισης ή JSON. Το diff σε επίπεδο χαρακτήρα πηγαίνει παραπέρα και μπορεί να επισημάνει έναν μόνο αλλαγμένο χαρακτήρα μέσα σε ένα μεγάλο αναγνωριστικό. Ο χειρισμός κενών διαστημάτων προσθέτει θόρυβο. Μια γραμμή που τελειώνει σε CRLF και η ίδια γραμμή που τελειώνει σε LF θα εμφανιστούν διαφορετικές κάτω από αυστηρή σύγκριση bytes. Τα περισσότερα εργαλεία προσφέρουν επιλογή για κανονικοποίηση των τελειωμάτων γραμμής πριν το diff. Ομοίως, τελικά κενά, εσοχή με tab έναντι κενού και κενές γραμμές μπορούν να παράγουν παραπλανητική έξοδο diff. Η ενεργοποίηση κανονικοποίησης κενών είναι συνήθως η σωστή προεπιλογή κατά τη σύγκριση κώδικα από διαφορετικούς editors ή λειτουργικά συστήματα.
Ο κίνδυνος ιδιωτικότητας των online εργαλείων diff
Οι online υπηρεσίες diff και pastebin είναι βολικές: ανοίγετε μια URL, επικολλάτε δύο τμήματα, παίρνετε έξοδο με χρώματα. Το πρόβλημα είναι ότι το κείμενο που επικολλάτε μεταδίδεται σε διακομιστή τρίτου μέρους. Ανάλογα με την υπηρεσία, αυτό το κείμενο μπορεί να καταγραφεί, να ευρετηριαστεί, να αποθηκευτεί επ' αόριστον ή να κοινοποιηθεί σε παρόχους αναλύσεων. Αυτό έχει μεγαλύτερη σημασία όταν ο κώδικας περιέχει ευαίσθητο υλικό. Αυθεντικά credentials, εσωτερικά ονόματα host, ιδιόκτητη επιχειρηματική λογική ή προσωπικά αναγνωρίσιμα δεδομένα μπορούν όλα να καταλήξουν σε ένα paste. Ακόμα και χωρίς ρητά μυστικά, η δομή του εσωτερικού κώδικα μπορεί να αποκαλύψει αποφάσεις αρχιτεκτονικής που θα προτιμούσατε να κρατήσετε ιδιωτικές. Ο κίνδυνος δεν είναι υποθετικός. Ερευνητές ασφάλειας έχουν επανειλημμένα βρει credentials και εσωτερικά tokens σε δημόσια pastes. Ορισμένες υπηρεσίες διατηρούν pastes ακόμα και μετά τη διαγραφή τους από τον χρήστη, επειδή αντίγραφα υπάρχουν σε caches ή αντίγραφα ασφαλείας. Δεν υπάρχει τρόπος να επαληθεύσετε τι κάνει μια απομακρυσμένη υπηρεσία με το κείμενο μόλις φτάσει εκεί. Η μόνη αξιόπιστη μέθοδος μετριασμού είναι να κρατάτε το diff τοπικό, πράγμα που σημαίνει εκτέλεσή του σε ένα εργαλείο που δεν στέλνει ποτέ το κείμενο μέσω δικτύου.

Πρακτικές χρήσεις για τοπικό Diff
Το diff δεν είναι μόνο για αναθεώρηση κώδικα. Μερικές συνηθισμένες περιπτώσεις όπου ένα τοπικό diff είναι χρήσιμο: Αναθεώρηση επεξεργασιών σε έγγραφο ή αρχείο ρύθμισης πριν την υποβολή. Σύγκριση δύο εκδόσεων Dockerfile, ρύθμισης Nginx ή Kubernetes manifest για να κατανοήσετε ακριβώς τι άλλαξε μεταξύ αναπτύξεων. Έλεγχος απόκλισης ρύθμισης μεταξύ περιβαλλόντων. Αν οι ρυθμίσεις παραγωγής και staging υποτίθεται ότι είναι ίδιες εκτός από ονόματα host και μυστικά, ένα diff δείχνει αμέσως κάθε ακούσια απόκλιση. Σύγκριση αποκρίσεων API κατά τον εντοπισμό σφαλμάτων. Επικολλώντας δύο φορτία JSON από REST ή GraphQL API και εκτελώντας diff σε επίπεδο λέξης εντοπίζετε προστιθέμενα πεδία, αλλαγμένες τιμές ή αφαιρεμένα κλειδιά χωρίς να διαβάσετε εκατοντάδες γραμμές με το χέρι. Αναθεώρηση κώδικα που δημιούργησε γλωσσικό μοντέλο έναντι γραμμής βάσης. Όταν ένα μοντέλο ξαναγράφει μια συνάρτηση, ένα diff σε επίπεδο γραμμής δείχνει ποια λογική άλλαξε και ποια παρέμεινε ίδια, πιο γρήγορα από το να διαβάσετε και τις δύο εκδόσεις ανεξάρτητα. Σε όλες αυτές τις περιπτώσεις, το κείμενο που εμπλέκεται μπορεί να είναι ευαίσθητο, και η διατήρησή του εκτός απομακρυσμένου διακομιστή είναι η απλή επιλογή.
Στον browser, χωρίς μεταφόρτωση
Το εργαλείο text-diff σε αυτόν τον ιστότοπο εκτελεί ολόκληρο τον υπολογισμό diff στον browser σας χρησιμοποιώντας JavaScript. Επικολλάτε δύο κείμενα στα δύο πάνελ και το diff αποδίδεται αμέσως, γραμμή προς γραμμή, έως 3000 γραμμές ανά πλευρά. Τίποτα δεν αποστέλλεται σε διακομιστή. Το κείμενο δεν εγκαταλείπει ποτέ τη συσκευή σας. Η υλοποίηση χρησιμοποιεί έναν τυπικό αλγόριθμο βάσει LCS που λειτουργεί σε γραμμές: κάθε γραμμή είναι ένα token, και το εργαλείο υπολογίζει αν είναι αναλλοίωτη, προστιθέμενη ή αφαιρεμένη βρίσκοντας τη μεγαλύτερη κοινή υπακολουθία ανάμεσα στις δύο εκδόσεις. Οι αναλλοίωτες γραμμές αποδίδονται χωρίς επισήμανση, οι προστιθέμενες γραμμές σε πράσινο, οι αφαιρεμένες σε κόκκινο, δίπλα σε έναν τρέχοντα μετρητή προσθηκών και διαγραφών. Δεν υπάρχει σήμερα λειτουργία σε επίπεδο λέξης ή χαρακτήρα ούτε επιλογή κανονικοποίησης κενών, οπότε μια γραμμή που διαφέρει μόνο σε τελικά κενά ή στυλ τελειώματος γραμμής εξακολουθεί να εμφανίζεται ως αλλαγμένη. Επειδή ο υπολογισμός εκτελείται στην πλευρά του client, λειτουργεί offline. Δεν υπάρχει λογαριασμός, ιστορικό, διατήρηση. Μπορείτε να συγκρίνετε ένα τοπικό αρχείο ρύθμισης με πρότυπο, να αναθεωρήσετε ένα patch πριν την εφαρμογή του, ή να ελέγξετε δύο αποκρίσεις API χωρίς κανένα από αυτά τα κείμενα να φτάσει σε τρίτο μέρος.
Εργαλεία αυτού του άρθρου
Συχνές ερωτήσεις
Το diff βάσει γραμμής ή βάσει λέξης είναι καλύτερο για κώδικα;
Για τις περισσότερες εργασίες αναθεώρησης κώδικα, το diff βάσει γραμμής είναι το πρότυπο και το πιο εύκολο να διαβαστεί, επειδή ο κώδικας δομείται κατά γραμμές. Το diff βάσει λέξης μπορεί να βοηθήσει όταν οι γραμμές είναι μεγάλες και άλλαξε μόνο ένα μικρό μέρος, όπως σε μια τιμή JSON μίας γραμμής, αλλά αυτό το εργαλείο συγκρίνει μόνο σε επίπεδο γραμμής· σε αυτή την περίπτωση, χρησιμοποιήστε την επισημασμένη γραμμή ως δείκτη και εντοπίστε με το μάτι τη μικρότερη διαφορά μέσα σε αυτήν.
Γιατί τα online εργαλεία diff ενέχουν κίνδυνο ιδιωτικότητας ακόμα και αν χρησιμοποιούν HTTPS;
Το HTTPS προστατεύει το κείμενο κατά τη μεταφορά από υποκλοπή, αλλά δεν το προστατεύει μόλις φτάσει στον διακομιστή. Ο χειριστής της υπηρεσίας έχει πλήρη πρόσβαση στο επικολλημένο περιεχόμενο και μπορεί να το καταγράψει, αποθηκεύσει ή κοινοποιήσει. Το TLS αφορά την ασφάλεια μεταφοράς, όχι τι κάνει ο παραλήπτης με τα δεδομένα.
Αποθηκεύει το εργαλείο text-diff ιστορικό παλαιότερων συγκρίσεων;
Όχι. Το εργαλείο δεν έχει backend και δεν κάνει αιτήσεις δικτύου. Μόλις κλείσετε ή επαναφορτώσετε την καρτέλα, το κείμενο εξαφανίζεται. Δεν υπάρχει λογαριασμός, αποθηκευμένο ιστορικό και κανένα αρχείο καταγραφής στον διακομιστή.