Zachowaj kompatybilność wstecznego języka programowania z naprawianiem jego wad

56

Po pierwsze, jakiś kontekst (rzeczy, które i tak większość z was zna):

Każdy popularny język programowania ma wyraźną ewolucję, przez większość czasu oznaczoną jego wersją: masz Java 5, 6, 7 itd., PHP 5.1, 5.2, 5.3 itd. Wydanie nowej wersji udostępnia nowe interfejsy API, naprawia błędy, dodaje nowe funkcje, nowe ramy itp. Podsumowując: to dobrze.

Ale co z problemami języka (lub platformy)? Jeśli i kiedy coś jest nie tak w języku, programiści albo go unikają (jeśli mogą), albo uczą się z tym żyć.

Teraz programiści tych języków otrzymują wiele informacji zwrotnych od programistów, którzy ich używają. Dlatego wydaje się sensowne, że w miarę upływu czasu (i numerów wersji) problemy w tych językach będą powoli, ale z pewnością znikną. Cóż, nie za bardzo. Dlaczego? Dlatego kompatybilność wsteczna. Ale dlaczego tak jest? Przeczytaj poniżej, aby uzyskać bardziej konkretną sytuację.


Najlepszym sposobem na wyjaśnienie mojego pytania jest użycie PHP jako przykładu:

PHP jest kochany i nienawidzony przez tysiące ludzi. Wszystkie języki mają wady, ale najwyraźniej PHP jest wyjątkowy. Sprawdź ten post na blogu . Ma bardzo długą listę tak zwanych wad w PHP. Teraz nie jestem programistą PHP (jeszcze nie), ale przeczytałem to wszystko i jestem pewien, że duża część tej listy to naprawdę prawdziwe problemy. (Nie wszystko, ponieważ jest to potencjalnie subiektywne).

Teraz, gdybym był jednym z facetów, którzy aktywnie rozwijają PHP, z pewnością chciałbym rozwiązać te problemy, jeden po drugim. Jeśli jednak to zrobię, kod oparty na określonym zachowaniu języka ulegnie awarii, jeśli zostanie uruchomiony w nowej wersji. Podsumowując w 2 słowach: zgodność wsteczna.

Nie rozumiem tylko: dlaczego powinienem zachować kompatybilność wsteczną PHP? Jeśli wydam PHP w wersji 8 z naprawionymi wszystkimi problemami, czy nie mogę po prostu ostrzec jej, mówiąc: „Nie uruchamiaj starego kodu w tej wersji!”?

Istnieje coś takiego jak deprecjacja. Mieliśmy to od lat i działa. W kontekście PHP: zobacz, jak obecnie ludzie aktywnie zniechęcają do korzystania z mysql_*funkcji (zamiast tego polecają mysqli_*i PDO). Amortyzacja działa. Możemy to wykorzystać. Powinniśmy go użyć. Jeśli działa dla funkcji, dlaczego nie miałby działać dla całych języków?

Powiedzmy, że ja (programista PHP):

  • Uruchom nową wersję PHP (powiedzmy 8) ze wszystkimi tymi wadami
  • Nowe projekty zaczną korzystać z tej wersji, ponieważ jest ona znacznie lepsza, jaśniejsza, bezpieczniejsza itp.
  • Jednak, aby nie rezygnować ze starszych wersji PHP, wciąż publikuję aktualizacje, naprawiam problemy bezpieczeństwa, błędy itp. Ma to sens z powodów, których nie wymieniłem tutaj. Jest to powszechna praktyka: spójrz na przykład, w jaki sposób Oracle aktualizuje MySQL w wersji 5.1.x, mimo że głównie koncentruje się na wersji 5.5.x.
  • Po około 3 lub 4 latach przestaję aktualizować stare wersje PHP i zostawiam je na śmierć. To dobrze, ponieważ w ciągu tych 3 lub 4 lat większość projektów i tak przejdzie na PHP 8.

Moje pytanie brzmi: czy wszystkie te kroki mają sens? Czy byłoby to tak trudne? Jeśli można to zrobić, to dlaczego nie jest zrobione?

Tak, wadą jest to, że łamiesz wsteczną kompatybilność. Ale czy nie jest to cena, którą warto zapłacić? Zaletą jest to, że za 3 lub 4 lata będziesz mieć język, w którym naprawiono 90% jego problemów ... język o wiele przyjemniejszy w pracy. Jego nazwa zapewni jej popularność.

EDYCJA : OK, więc nie wyraziłem się poprawnie, kiedy powiedziałem, że za 3 lub 4 lata ludzie przejdą do hipotetycznego PHP 8. Miałem na myśli: za 3 lub 4 lata ludzie będą używać PHP 8, jeśli zaczną nowy projekt.

Radu Murzea
źródło
31
PHP jest złym przykładem tego konkretnego pytania, ponieważ najczęściej nie wybierasz wersji, z którą będziesz pracować. Większość stron PHP jest wdrażanych na współdzielonych serwerach, a właściciel serwera wybiera wersję, a nie ty. Wiele rzeczy jest naprawianych w każdej nowej wersji ( mysql_*na przykład przestarzałe w wersji 5.5), ale nie ma to znaczenia, jeśli większość dostawców hostingu ma jedną lub nawet dwie wersje z powrotem (5.3 - niestety - wciąż jest tym, co większość oferty dostawców).
yannis
5
... Myślę też, że nie doceniasz ilości kodu, który powinien zostać przeniesiony, ilości rzeczy, które mogłyby się zepsuć, ilości zależności stron trzecich do dostosowania itp.
Dagnelies
12
Ten świetny wpis na blogu joelonsoftware.com/items/2008/03/17.html Joela Spolsky'ego na temat „zestawów marsjańskich” powinien być obowiązkowy dla każdego programisty, który nie docenia znaczenia wstecznej kompatybilności.
Doc Brown
3
Ponadto PHP powoli przestaje działać z każdą kolejną wersją - w rezultacie wiele rzeczy się psuje. Niestety, PHP utknęło w trudnym miejscu, gdzie mają trudności z wyświetlaniem ostrzeżeń o wycofaniu w sposób, który programiści zobaczą, że i tak nie spowoduje to zakłócenia działania witryn.
puszysty
20
python 2.x => python 3.x jest przełomową zmianą z jednego dobrze zaprojektowanego języka na inny, nieco lepiej zaprojektowany język, który ma własne wsparcie dla automatycznej zmiany wielu niekompatybilnych konstrukcji. Przenoszenie kodu między nimi jest tak proste, jak to możliwe, aby dokonać zmiany między dwoma językami. Py3k wciąż bardzo powoli zdobywa popularność.
Phoshi,

Odpowiedzi:

25

Brzmi dobrze, ale rzadko sprawdza się w praktyce; ludzie bardzo niechętnie zmieniają działający kod, a nawet w przypadku nowych projektów typu green-field bardzo niechętnie zmieniają język / wersję, którą już znają.

Zmiana istniejącego, działającego kodu, który „działa dobrze”, nie jest czymś, co zajmuje wysokie miejsce na liście priorytetów każdego projektu. Zamiast wkładać wysiłek w sprawy, za które menedżerowie sądzili, że już za to zapłacono, tylko po to, aby móc uaktualnić do nowej wersji języka lub platformy, zdecydują, że programiści powinni po prostu pozostać przy starej wersji „na razie”. Możesz spróbować zachęcić użytkowników wspaniałymi funkcjami dostępnymi tylko w nowej wersji, ale jest to hazard, w którym ryzykujesz zmniejszeniem bazy użytkowników bez wyraźnego zysku dla języka; fajne, nowoczesne funkcje nie mogą być łatwo porównane z ceną rozdrobnionej bazy instalacyjnej w powszechnej opinii, a Ty ryzykujesz, że zyskasz reputację „uaktualnionej bieżni”

(Oczywiście, większość tego nie dotyczy projektów napisanych przez hobbystów tylko dla ich własnej przyjemności. Jednak (tutaj bądź płomień ...) PHP jest nieproporcjonalnie rzadko wybierany przez hakerów, ponieważ pisanie z taką przyjemnością jest przede wszystkim przyjemnością. )

Kilian Foth
źródło
65

Nie doceniasz wpływu wstecznej kompatybilności; twoje szacunki, że wszystkie aktywne projekty migrowałyby za 3 lub 4 lata, są zdecydowanie zbyt optymistyczne.

Załóżmy, że jestem programistą PHP. PHP ma wady, ale wiem, jak sobie z nimi poradzić - to jeden z powodów, dla których zarabiam jako programista PHP. Załóżmy teraz, że PHP 8 wychodzi i naprawia te wady, ale nie jest kompatybilny wstecz. W rezultacie:

  • Muszę poświęcić czas na aktualizację kodu dla PHP 8. To czas, w którym mógłbym odpowiadać na prośby klientów, wdrażać nowe funkcje, nadążać za konkurencją.
  • Nawet po zrobieniu tego istnieje duża szansa, że ​​przeoczyłem jakiś przypadek narożny lub nieprzewidziany problem ze zgodnością, wprowadzając błędy w moim kodzie.

Biorąc to pod uwagę, istnieje silna zachęta, aby nigdy nie migrować do PHP 8, nawet jeśli jest to „lepsze, wyraźniejsze, bezpieczniejsze itp.” Szacuje się, że wciąż są miliardy linii COBOL (!) - chociaż są oczywiście dostępne znacznie lepsze technologie, koszt aktualizacji w połączeniu z ryzykiem błędów, po prostu nie jest tego wart.

Po drugie, nawet jeśli zdecyduję się na migrację własnego kodu, każda nietrywialna aplikacja zależy od bibliotek stron trzecich i nie ma gwarancji, że migrują biblioteki stron trzecich. Na przykład Python 3 został wydany w grudniu 2008 roku, ale Django (prawdopodobnie wiodący framework sieciowy Python) nie miał stabilnej, gotowej do produkcji obsługi Python 3 przez prawie pięć lat (patrz tutaj i tutaj ).

Josh Kelley
źródło
8
Jest zaskakująco duża liczba otwartych pozycji COBOL, szczególnie w przypadku starszych firm ubezpieczeniowych Oo
Chad Harrison
1
@Josh Kelley: Zgadzam się z tobą, ale myślę, że te problemy dotyczą tylko języków, w których nie można wyraźnie oddzielić starszego kodu od nowego kodu, np. Python, PHP, ponieważ musisz dołączyć biblioteki i C ++ (szablony). Języki z innym modelem kompilacji (np. Java, Scala, Clojure) pokazują, że można dodać nowy kod (np. W Clojure) do starszego kodu (np. W Javie), nawet jeśli oba języki nie są kompatybilne na poziomie kodu źródłowego.
Giorgio
2
Nie wiem, czy powinienem to opublikować jako osobne pytanie czy jako komentarz. Ale dlaczego nie mogli stworzyć języka programowania, który przenosi migrację kodu do koncepcji pierwszej klasy? W Javie znajduje się adnotacja @Deprecated, która tylko ostrzega. Być może inny język może faktycznie udostępnić makro, które zastępuje stary kod poprawnym nowym kodem. Jeśli używasz najnowszej wersji, wywoływanie przestarzałego kodu jest błędem, ale stary kod jest konwertowany na nowy, nieaktualny kod. Po prostu spitballin '
Daniel Kaplan
7
@tieTYT - Niektóre języki programowania to robią - patrz Python's 2to3 lub Go's gofix ( talks.golang.org/2012/splash.slide#68 ). Z pewnością pomaga to w przestarzałych starych funkcjach, ale istnieją ograniczenia dotyczące tego, jak dobrze oprogramowanie może rozumieć i aktualizować inne oprogramowanie, gdy zmienia się semantyka języka.
Josh Kelley,
3
@hydroparadise Moja ciotka pracuje jako programista w bankach i firmach ubezpieczeniowych, aw czasach kryzysu niektórzy klienci jej firmy postanowili wrócić do COBOL, ponieważ oprogramowanie jest tańsze! Nawet ekonomia może wpływać na tempo, w jakim firmy przechodzą na nowsze języki / wersje.
Bakuriu
17

Robisz wiele założeń na temat ludzkiego zachowania. Jeśli zmienisz to zbyt mocno, ludzie ocenią twoich konkurentów, ponieważ i tak będą musieli spędzić znaczny wysiłek. W przypadku języków open source ludzie po prostu rozwidlają starą wersję.

Spójrz na przykład na python. 3.x jest dostępny od czterech lat i nadal nie jest powszechnie stosowany. Ludzie próbują go używać do zupełnie nowych projektów, ale myślę, że nie doceniasz, ile pracy zajmuje kod.

Oczywiście większość ludzi nie uważała Pythona za „wadliwy”. Nie mieli skarg takich jak użytkownicy php. Php znajduje się w znacznie bardziej niepewnej sytuacji, ponieważ wiele osób trzyma się go tylko z powodu dużej istniejącej bazy kodu. Jeśli utraciłeś kompatybilność wsteczną, wiele osób skorzystałoby z okazji, na którą czekali, aby przejść do Pythona.

Karl Bielefeldt
źródło
Myślę, że masz dobry punkt (+1). Myślę, że wsteczna kompatybilność to fałszywy problem, szczególnie w przypadku języków skompilowanych, w których można używać osobnej kompilacji (zobacz, jak zintegrować Scalę i Clojure z Javą lub C # z C ++). Ale utrzymanie poczucia, że ​​nowy język jest po prostu zaktualizowaną wersją starego, jest bardzo ważne, aby uniknąć rozwidlenia lub że ludzie po prostu migrują do innego języka. Myślę, że te powody są znacznie silniejsze niż radzenie sobie ze starszym kodem.
Giorgio
1
@Giorgio Fałszywy problem? Powiedz to wszystkim pisarzom bibliotek, którzy muszą obsługiwać jednocześnie więcej wersji języka.
svick
@svick: Dzięki osobnej kompilacji nie musisz obsługiwać różnych wersji języka. Zobacz np., Jak Scala może korzystać z bibliotek Java, które nie zostały skompilowane dla Scali.
Giorgio
9

W przypadku każdego języka innego niż PHP powiedziałbym: tak, to absolutnie ma sens! Właśnie to robi Python, przechodząc na Python 3.

Jednak problem z PHP polega na tym, że istnieje zbyt wiele wad w samym projekcie języka, dlatego to, co nazywacie „PHP 8”, byłoby zupełnie innym językiem. A jeśli musiałbyś przejść na inny język, dlaczego miałbyś trzymać się nowego PHP, zamiast żadnej z obecnie istniejących i stabilnych alternatyw?

Również społeczność PHP bardzo wolno dostosowuje cokolwiek nowego. Zobacz, ile czasu zajęło pozbycie się register_globals. Wiadomo, że stanowi zagrożenie dla bezpieczeństwa od 2000 roku. Ostatecznie został usunięty dopiero 12 lat później. Kolejny przykład, kiedy wprowadzono PHP5, było to ogromne ulepszenie w stosunku do PHP4, ale społeczność go nie dostosowała. Zajęło mi 4 lata i masowe działania, takie jak GoPHP5, aby przyspieszyć adopcję. I to nawet nie miało znaczącej liczby niezgodnych wstecz zmian.

vartec
źródło
5

Oświadczenie: Zarządzam grupą użytkowników ColdFusion.

ColdFusion ma te same problemy: kochany przez wielu, pogardzany przez wielu. Ponadto, mnóstwo ton FUD opartych na wersjach wcześniejszych niż Java. ColdFusion 10 ukazał się w zeszłym roku, jest ogromnym sprzedawcą, aw zeszłym tygodniu zapisałem się, aby przetestować przedpremierową wersję 11. Ponadto istnieją dwie główne alternatywy open source, jedna jest wspierana przez JBoss.

Istnieje mnóstwo nowych funkcji w CF10, które chciałbym wdrożyć, ale migracja z CF 7 lub 8 może być trudna w zależności od wielkości bazy kodu, liczby nadchodzących projektów i zasobów, które musisz regresować, testując wszystko są na najnowszej wersji. Natknąłem się na kilka drobnych różnic składniowych między 8 a 9, a także przypadki brzegowe, w których kod nie kompiluje się w ten sam sposób. Po znalezieniu udokumentowałem je w naszych standardach kodowania, aby nie były wykorzystywane w przyszłych projektach ani przez nowych programistów.

To powiedziawszy, jeśli ColdFusion 11 (lub jakikolwiek język programowania) całkowicie zdezaktualizuje niektóre funkcje i składnię, poziom wysiłku w znalezieniu i zastąpieniu funkcjonalności może być ogromny. Wysiłek testowy może być gigantyczny. Czy firmy zapłacą swoim programistom, kontroli jakości i kierownikom projektów za znalezienie, zastąpienie i przetestowanie tych przestarzałych rzeczy? Wątpliwy.

Jeśli najnowsza wersja języka jest wstecznie kompatybilna, ale wprowadza wzrost wydajności bez zmian kodu (CF9 jest o około 30% szybszy niż CF8 i CF10 jest znacznie szybszy niż CF9), kogo obchodzi zmiana wywołań funkcji, jeśli nadal działają?

Jako firma musimy martwić się o zadowolenie naszych klientów i zaspokajanie ich potrzeb w celu rozliczania usług, budowania biznesu i rekrutowania większej liczby klientów.

FWIW, chciałbym w pewnym momencie wprowadzić nas do najnowszej wersji jQuery, ale ponieważ niektóre funkcje zostały przestarzałe w kilku wersjach po tym, czego używamy, a biorąc pod uwagę ilość JavaScript, którą mamy w systemie, nie wiem jak zamierzamy to zrobić.

Adrian J. Moreno
źródło
4

Tu jest kompromis; niektóre błędy NAPRAWDĘ wymagają naprawy, ale niektórych rzeczy nie można zmienić bez zerwania gdzieś kodu. Wydaje mi się, że pamiętam kogoś, kto jako „regułę” twierdzi, że każda poprawka zakłóci czyjś projekt, bez względu na to, jak niejasny lub oczywiście zepsuty jest błąd, ktoś będzie go używał do czegoś. Taka jest natura programistów.

Jest to (moim zdaniem) różnica między głównymi wydaniami, drobnymi wydaniami i wersjami. Zasadniczo:

  • Zakłada się, że główne wydania zawierają przełomowe zmiany.
  • Drobne wersje mogą nieznacznie zmienić zachowanie.
  • Wersje powinny być w zasadzie kompatybilne krzyżowo.

Na przykład, jeśli piszę coś w v2.3 języka, nie spodziewałbym się zauważenia żadnej różnicy, jeśli uaktualnię do v2.3.2. Jeśli zaktualizuję do wersji 2.4, to może się zmienić kilka rzeczy - drobne poprawki składniowe, niektóre funkcje zachowują się trochę inaczej, więc muszę dostosować logikę itp. Jeśli zaktualizuję do wersji 3.0, nie byłbym zaskoczony, gdyby się zepsuł całkowicie - przestarzałe lub brakujące funkcje, operacje nieobsługiwane lub zmieniane tak bardzo, że nie mogę po prostu dostosować go z powrotem do linii, w rzeczywistości muszę przepisać niektóre funkcje, aby uwzględnić nowe zmiany.

Edytować:

Artykuł Steve'a Vance'a „ Zaawansowane strategie rozgałęziania SCM” mówi:

Zazwyczaj istnieją dwa do trzech poziomów wydania, nazwane liczbami związanymi z kropkami (np. 1.2.3). [...] W tej strukturze pierwszy numer jest powiązany z wersją główną, co wskazuje, że ma znaczące ulepszenia funkcji i funkcjonalności z poprzedniego; mogą również występować znaczące niezgodności wymagające migracji. Druga liczba reprezentuje mniejszą wersję, która zawiera mniejsze ulepszenia funkcji i funkcji, znaczną liczbę poprawek błędów i brak niezgodności. Trzecia liczba odnosi się do poziomu łaty, co oznacza prawie wyłącznie zbiór poprawek; żadne funkcje lub ulepszenia funkcji i niezgodności nie są dozwolone między poziomami łatek.

Jedyną zmianą, którą wprowadzę w tym zakresie, jest wspomniana zasada, że ​​programiści często znajdują sposoby na „wykorzystanie” błędów, więc niewielka wersja z „znaczną liczbą poprawek błędów i brakiem niezgodności” może być trudna, ponieważ prawdopodobne jest, że te błędy albo uszkodzą coś, co ich użyło, albo spowodują, że obejście stanie się niepotrzebne i zacznie powodować problemy.

anaksymander
źródło
Spodziewałbym się, że 2.3-> 2.4 doda funkcjonalność, ale jej nie usunie.
Donal Fellows
1
Przypadkowo natrafiłem ostatnio na odpowiedni cytat. Trochę za długo na komentarz, więc zredaguję swoją odpowiedź.
anaximander
2

To naprawdę zależy od tego, jaki jest cel języka - jakie typy aplikacji mają być budowane za pomocą języka.

Na przykład ignorując Androida, Java jest najczęściej używana w dużych systemach korporacyjnych i oprogramowaniu pośrednim; tego rodzaju aplikacje stają się bardzo duże zarówno pod względem wielkości, jak i czasu. Ma to pewne implikacje; wyobraź sobie system z 500K + LoC, w którym pracownik 50+ inżynierów jest w fazie rozwoju. Zazwyczaj ten typ systemu wchodzi w utrzymanie po powiedzmy 10 programistów; teraz, jeśli język się zmieni, a zmiany nie są kompatybilne wstecz, projekt nie może być łatwo migrowany do nowej wersji, ponieważ programiści, którzy napisali niektóre części, znikają i nikt nie chce ich dotykać. Jest to mniejszy problem, większy problem polega na tym, że dostosowanie aplikacji 500 LoC do nowych ograniczeń językowych jest dość kosztowne. Na przykład, jeśli nie wprowadzono generycznych z usuwaniem typu iList list = new List(); nie skompilowalibyśmy milionów wierszy kodu, które musiałyby zostać przepisane - co jest ogromnym kosztem.

Z drugiej strony PHP jest używane w Internecie do prostszych aplikacji; zwykle jest rozwijany przez jednego programistę lub mały zespół. Chodzi o to, że programiści całkiem dobrze znają cały projekt i mogą łatwiej zintegrować zmiany językowe. Ma również na celu szybkie zbudowanie strony, a im szybciej, tym lepiej, więc jeśli nowa funkcja językowa może to zrobić lepiej, to jest implementowana nawet przy pewnych kosztach kompatybilności wstecznej.

m3th0dman
źródło
1

Można argumentować, że Microsoft dokonał podobnej zmiany w przypadku ASP.NET (jako następcy klasycznej ASP) lub VB.NET (chociaż zrobili tyle ustępstw w stosunku do tego ostatniego, że większość korzyści z „ponownego uruchomienia” języka została utracona).

W każdym razie, jeśli ktoś pamięta koszmar migracji kodu VB6 do VB.NET, nawet przy pomocy narzędzia do migracji, od razu zgodzi się, że narzędzia do migracji języka nie działają zbyt dobrze w przypadku dużych aktualizacji języka.

Platforma może być możliwa do przodu, ale nadal należy zapewnić obsługę „przestarzałych” interfejsów API przez co najmniej kilka wersji.

Michael Brown
źródło
1

Wiele „wad”, o których ludzie krzyczą w popularnych językach programowania, nie są, są one ulubioną zabawką krzyczącego tego dnia, że ​​brakuje tego języka, Z TYM tego języka jest zasadniczo wadliwy, ponieważ go brakuje.
Nadchodzi kolejny szum, język jest nagle wadliwy, ponieważ nie jest zgodny z tym szumem.

Brak zamknięć w Javie jest klasycznym przykładem. W ogóle nie jest to żadna wada, a zmiana języka (co niestety jest w porządku obrad), aby je uwzględnić, IMO zasadniczo go sparaliżuje lub przynajmniej utrudni jego czytanie i zrozumienie.

Zbyt wielu ludzi traci z oczu to, że każdy język ma swoje mocne i słabe strony, i że próba stworzenia czegoś, co łączy w sobie mocne strony wszystkiego, unikając każdej słabości, stworzy tylko całkowicie niezdatnego do użytku potwora, który jest dobry w niczym, niewiarygodnie niewiarygodny, niemożliwy do używać skutecznie.

Dodaj, jak zauważyli inni, że zgodność z poprzednimi wersjami jest niezbędna do utrzymania istniejących użytkowników, z których wielu NIE wyda tysięcy godzin i milionów dolarów / euro na modernizację swoich milionów baz kodowych do tego, co uważasz za „lepsze” niż wersja języka, którego używają od lat, i masz mnóstwo bardzo dobrych argumentów, aby zostawić wystarczająco dobrze w spokoju, a jeśli chcesz zagrać z jakimś nowym przesadzonym pomysłem, który jest prawdopodobnie kolejnym „zabójcą java” d lepiej bawić się tą zabawką, niż krzyczeć, że „Java jest ded”, chyba że „zostanie naprawiona”, aby być klonem tej zabawki.

jwenting
źródło
1

Sugerowałbym, że nowsze wersje języka powinny dążyć do tego, aby 99,99999% kodu, który kompiluje się zarówno w starej, jak i nowej wersji języka, działało identycznie w obu, chyba że jest to specjalnie zaprojektowane, aby tego nie robić, i że przez większość czasu kiedy nowa wersja odrzuca kod skompilowany zgodnie ze starą wersją, dzieje się tak, ponieważ kod był - w najlepszym razie - niejasny i powinien był zostać napisany w inny sposób, który skompilowałby się zarówno w starym, jak i nowym kompilatorze.

Na przykład, gdybym projektował nowy język podobny do Java lub C #, zabroniłbym konwersji typu niejawnego w niektórych kontekstach, w których te języki na to pozwalają. Podany jako prosty przykład w języku C #

int someInt;
double someDouble;

wyrażenie someInt.Equals(someDouble)ma gwarancję, że zwróci fałsz, niezależnie od zawartości zmiennych. Kompiluje się, ponieważ doublemożna go przekonwertować Object, i intma Equalsprzeciążenie dla tego typu, więc kompilator dokonuje konwersji i wykonuje wywołanie. Gdybym projektował nową wersję C # i .NET Framework, kazałbym jej zabronić konwersji bokserskiej, ponieważ nie może ona zrobić nic pożytecznego. Możliwe, że jest jakiś program, który dokonuje takiego porównania w sposób bezużyteczny, ale nieszkodliwy, a odrzucenie przez kompilator takiego kodu może uszkodzić ten program, ale poprawienie lub usunięcie takiego niepotrzebnego kodu byłoby ulepszeniem.

Jako nieco mniej jasny przykład załóżmy

float f=16777216f;
int i=16777217;

i rozważ wyrażenie f==i. Jest możliwe, że jakiś kod robi unosić porównań / całkowite i działa poprawnie, ale kod powinien być przepisany jako albo f==(float)i, (double)f==i;albo (double)f==(double)i;[ intdo doublepromocji jest bezstratna, więc dwa ostatnie byłoby równoznaczne]. Niektóre programy, które bezpośrednio porównuje floati integerwartości mogą zawsze do czynienia z liczbami, które są na tyle małe, że floati doubleporównania będzie zachowywać się identycznie, ale kompilator na ogół nie może wiedzieć, że; kod powinien wyjaśniać, jakiego rodzaju porównanie jest potrzebne, zamiast mieć nadzieję, że reguły języka będą zgodne z intencją programisty.

supercat
źródło
1

Najlepiej nigdy nie zerwać z kompatybilnością wsteczną.

Microsoft zastąpił język programowania VB6 nowym językiem, który całkowicie złamał kompatybilność. Tak więc nawet dzisiaj 16-letni VB6 jest nadal bardziej popularny niż wersja dotNet (indeks Tiobe z sierpnia 2014 r.). Gartner szacuje, że wciąż jest w użyciu 14 miliardów linii kodu VB6.

W 2014 r. Microsoft ponownie ogłosił, że nie zaktualizuje ani nie otworzy VB6 pomimo wymagań społeczności programistów Visual Basic. Ale rozszerzyli obsługę VB6 do „co najmniej” 2024 i działa dobrze w Windows 7 i 8. To będzie ponad 26 lat wsparcia dla tej samej wersji VB6.

Dlaczego istniejące oprogramowanie powinno być przepisywane, nawet Microsoft nigdy nie „aktualizuje” pakietu Office, aby korzystać z dotNet?

Programowanie VB6
źródło
wydaje się, że nie oferuje to nic istotnego w porównaniu do poprzednich 14 odpowiedzi
komara
1

Istnieje kilka różnych problemów z łamaniem wstecznej kompatybilności. Niektóre problemy wynikają z faktu, że większość języków programowania to także platformy (tłumacze / środowiska wykonawcze), inne problemy wynikają z założenia natury ludzkiej.

A. Kod napisany w starszych wersjach nie zyskałby korzyści z nowych wydań poprawiających wydajność, bezpieczeństwo lub funkcje. Możesz złagodzić ten problem, obsługując wiele głównych wersji kompilatora / interpretera, ale jest to ogromny drenaż zasobów (tj. Jest kosztowny lub zajmuje dużo czasu i jest uciążliwy).

B. Kod napisany dla nowszych wersji może nie być zgodny z kodem napisanym w starszych wersjach. Możesz obejść ten problem, mając interpretera / kompilatora, który może obsługiwać wiele głównych wersji języka, ale jest to bardziej problem w dupie niż obsługa oddzielnych tłumaczy / kompilatorów (obejście dla A).

C. Poważne zmiany, jeśli zdarzają się zbyt często / szybko, po prostu utrudniają używanie języka, ponieważ musisz się więcej nauczyć i oduczyć. Zmiany w języku mogą zmusić ludzi do przejścia na nowy język lub spowodować, że ludzie będą nadal używać przestarzałych wersji języka i nigdy nie będą przełączać się na nową wersję (tak jak stało się z Pythonem). Z drugiej strony zmiany mogą również przyciągać nowych użytkowników i ekscytować starych.

D. Nowa dokumentacja musi być przechowywana i utrzymywana. Zawsze jest dość mylące przeszukiwanie rzeczy w Google i stwierdzenie, że czytasz dokumenty w innej wersji niż obecnie.

Ogólnie rzecz biorąc, jeśli tworzysz język programowania, w którym moduły zewnętrzne nie muszą dbać o używaną wersję, zerwanie wstecznej kompatybilności z właściwych powodów (aby naprawić poważne wady w języku) jest prawie zdecydowanie właściwym rozwiązaniem . Jest prawdopodobne, że głównym powodem, dla którego nie zostało to zrobione, jest to, że projektanci języków programowania przeceniają ( aby zaprzeczać czyjejś odpowiedzi ) koszty łamania kompatybilności, szczególnie na początku. Faktem jest, że problemy związane z łamaniem kompatybilności mogą być obejrzane lub rozwiązywane przez użytkowników tego języka. Dotyczy to nie tylko języków programowania; dotyczy to interfejsów API, interfejsów użytkownika - naprawdę każdego interfejsu w każdej sytuacji.

Facebook denerwuje ludzi, gdy zmienia interfejs użytkownika lub interfejsy API dla programistów. W przeszłości platforma utrudniała obsługę. W niektórych przypadkach interfejsy API po prostu przestały działać na niebiesko. Ale ludzie nadal go używali, a teraz interfejsy API i interfejsy użytkownika są lepsze niż przed 5 laty. Ludzie będą narzekać na zmianę, czy jest to dla nich dobra, czy zła, ale to (narzekanie) nie jest dobrym powodem do rezygnacji z tej zmiany. Niestety, programiści języków programowania wykorzystują to jako powód do utrzymania problemów z nienaruszonym językiem.

Kolejnym powodem, dla którego języki nie dokonują przełomowych zmian w celu poprawy siebie, są:

E. Programiści języków uważają, że obawa użytkowników przed zmianą jest dobrym powodem do stagnacji języka

F. Twórcy języków lubili swój język, kiedy go stworzyli, i prawdopodobnie uważają, że jest w porządku z jego wadami.

G. Języki, gdy się starzeją, zwykle przestają mieć niewielką grupę programistów i stają się bestiami stworzonymi przez komitety. Oznacza to, że decyzje dotyczące tych języków są powolne, często konserwatywne i mało kreatywne.

H. Ostatnim powodem jest to, że niektóre przełomowe zmiany wymagają znaczącej ponownej oceny decyzji projektowych podjętych dla interpretera / środowiska wykonawczego. Czasami ulepszenia języka wymagają po prostu zbyt wiele pracy, aby było to możliwe. Sądzę, że jest to rzadszy problem niż większość.

Często projektanci języków niekoniecznie są projektantami narzędzi, więc nie myślą o dobrych rozwiązaniach tego problemu lub nie wykonują ich dobrze. Oto kilka rozwiązań, które mogę wymyślić, aby rozwiązać problem przełomowych zmian:

  1. Przestarzałe rzeczy na długo przed ich usunięciem.

  2. Zapewnij dobre , standardowe narzędzie do konwersji. Python dostarczył narzędzie 2to3, ale nie było dobrze reklamowane, nie było standardowo z Pythonem 3, jak pamiętam, i nawet nie działało bardzo dobrze (pamiętam konieczność ręcznego przeglądania programów generowanych przez 2to3, aby rozwiązać problemy nie naprawiono). To narzędzie konwertera może nawet zostać uruchomione automatycznie, jeśli Twój kompilator / interpreter wykryje starszą wersję. Co może być łatwiejszego?

BT
źródło
Problem z analogią Facebooka polega na tym, że nie jest w użyciu Legacy Facebooka. Nie ma wyboru. Albo używasz bieżącej wersji Facebooka, albo w ogóle go nie używasz. Tymczasem wciąż jest mnóstwo ludzi używających Python 2siedem lat po wydaniu, Python 3ponieważ nadal istnieje - gdyby nie, narzekaliby, ale przenieśliby się Python 3.
Kevin
Nie sądzę, żeby to był problem z analogią, o to właściwie miałem na myśli. Facebook wybrał trasę „naprawiania wad” i w większości zrezygnował z trasy „kompatybilności wstecznej”. Dlatego nie mają starszej wersji interfejsu API. To doskonały przykład jednej skrajności.
BT
Zerwanie wstecznej kompatybilności w językach programowania doprowadzi do tego, że ludzie będą nadal używać i / lub rozwiązywać starą wersję. Stara wersja Facebooka już nie istnieje; Przypuszczam, że można stworzyć klon, który obsługiwałby stare API, ale nikt by go nie używał, ponieważ Facebook to marka z ogromną bazą użytkowników.
Kevin,
Zaletą Facebooka jest to, że podczas aktualizacji poprzednie wersje zasadniczo już nie istnieją. Języki programowania nie są takie, a to istotna różnica - możesz użyć przestarzałej wersji języka programowania, na przykład Python 2, ponieważ wciąż istnieje.
Kevin
Rozumiem co masz na myśli. Nadal uważam, że to jeden koniec dwóch skrajności. Jeśli poważne wady pojawią się w nieobsługiwanej wersji języka, może to oznaczać, że ta wersja przestaje istnieć, ponieważ nikt nie będzie chciał z niej korzystać.
BT
0

Nie wiem, czy jest to problem z kodem PHP, ale w wielu językach stary kod nie jest aktualizowany po latach, a czasem nawet dekadach, ponieważ działa, jest krytyczny dla prowadzącej go firmy i jest zbyt duży (powiedzmy miliony SLOC), więc przepisanie go nie miałoby sensu. To jest powód, dla którego java uczyniła kompatybilność wsteczną niemalże religijną kwestią, pomimo znanych starych problemów, szczególnie w bibliotekach (nawet jeśli łatwiej je zaktualizować). Wydaje mi się, że wiele kodu z jądra Linuksa również nie było aktualizowane przez dziesięciolecia, pomimo przyjęcia standardów takich jak C99 i C11.

Nawet w językach mniej „przedsiębiorczych” łamanie starego, funkcjonalnego kodu może stanowić problem. Tak stało się z Pythonem 2 -> 3. Cała biblioteka i skrypty systemowe były stabilne i nie były już utrzymywane, nie dlatego, że zostały porzucone, ale dlatego, że były stabilne i wykonywały swoją pracę. Ich dostosowanie zajmuje kilka lat. Tak więc, jako programista, niekoniecznie musisz przejść do Pythona 3, jeśli twoja ulubiona biblioteka jeszcze się nie przeprowadziła, więc twój własny kod również nie będzie działał w Pythonie 3, co spowoduje fragmentację społeczności.

Fabien
źródło
-1

Problem leży w kwestii kompatybilności wstecznej. Większość wykonywanych przeze mnie skryptów PHP działa na starszym serwerze RedHat. Gdybym miał użyć nowszej wersji języka dla przyszłych skryptów, musiałbym zaktualizować PHP na tym serwerze - i ryzykować zepsucie moich starszych skryptów / konieczność przepisania całego starego kodu za pomocą godzin nowy standard. Ponadto wszyscy moi programiści są przyzwyczajeni do tego, że PHP reaguje w określony sposób (niezależnie od tego, czy ten sposób jest „zepsuty”, czy nie). Jeśli nie reaguje już w ten sposób, może to stanowić poważną przeszkodę dla wydajności, ponieważ programiści mogą być zmuszeni do samodzielnego uczenia się PHP.

Brandon
źródło