Jakie problemy mogą wynikać z emulacji pojęć z innych języków?

12

Wiele razy czytałem w Internecie, że jeśli twój język nie obsługuje niektórych pojęć, na przykład orientacji obiektowej, a może wywołań funkcji, i jest uważany za dobrą praktykę w tym innym kontekście, powinieneś to zrobić.

Jedyny problem, jaki widzę teraz, to to, że inni programiści mogą uznać twój kod za inny niż zwykle, co utrudnia im programowanie. Jak myślisz, jakie inne problemy mogą z tego wyniknąć?

Julio Rodrigues
źródło
3
Ludzie będą się z ciebie śmiać, po pierwsze :-)
Karl Bielefeldt,
Przetłumaczyłem raz parser funkcji zagnieżdżonych z D na Javę, ale przyznaję, że nie jest to najczystszy fragment kodu, jaki kiedykolwiek napisałem (jedna duża funkcja z interfejsem i kilka klas implementujących ją w sobie)
ratchet maniak

Odpowiedzi:

23

Jednym z problemów jest to, że możesz napisać dużo kodu, aby wyrazić coś w sposób, który zrobisz w innym języku, podczas gdy istnieje prostszy sposób w języku, którego używasz.

Na przykład w odpowiedzi na temat przepełnienia stosu wyjaśniłem, w jaki sposób kontrakty kodowe, koncepcja stosowana w .NET Framework, mogą być częściowo emulowane w PHP, który ich nie obsługuje. Skończyło się na tym, że napisałem dużo kodu za darmo, ponieważ to samo można zrobić z prostymi tablicami.

Mówiąc bardziej ogólnie, każdy język ma swoją kulturę, własne najlepsze praktyki, swój styl.

  • Gdybym zaczął pisać kod C # tak, jakby to był C, byłoby to brzydkie.

  • Jeśli pojmę Haskella jako programistę Java, który był zmuszony używać Haskella, ale nie chcę zrozumieć jego mocnych stron i po prostu chcę sklonować koncepcje Javy, kod, który napisałbym, ucierpi.

  • itp.

Nie ma nic złego w próbie ulepszenia języka (na przykład poprawienie C # poprzez wprowadzenie jednostek miary jak w F #), ale jeśli robisz to za dużo, powinieneś wybrać inny język, który faktycznie odpowiada twoim potrzebom.

Arseni Mourzenko
źródło
+1 Dobra odpowiedź i dziękuję za dodatkowe wyszukiwane hasła z dodaniem jednostek miary do C # jak w F #.
2
Jako ten, który kiedyś rzucił pracę z powodu zmuszania do korzystania z Javy, moje 2 centy: nie można zmusić się do korzystania z Haskell, zakochuje się w nim, a potem wciąga cię do punktu, w którym nie ma powrotu. Haskell jest jak jedna urocza czarna dziura, w którą chcesz wpaść - i w przeciwieństwie do prawdziwej, wciąż żyjesz, aby opowiedzieć tę historię :)
Cetin Sert
powinieneś wybrać inny język ... chyba że nie masz wyboru, na przykład JavaScript po stronie klienta. (Mimo to brak wyboru nie jest usprawiedliwieniem dla implementacji opartej na klasach emulacji OOP w języku prototypowym. O wiele skuteczniej jest po prostu nauczyć się, jak działa ten język.)
kojiro
@kojiro: lub inna praca. Sam miałem ten sam problem, gdy byłem zmuszony używać PHP i ciągle próbowałem modyfikować język, w tym pisać własny kompilator. Mniej szalonym rozwiązaniem była zmiana mojej pracy i rozpoczęcie pracy tylko nad projektami, które nie używają PHP.
Arseni Mourzenko
1
@Cetin Sert: zgadzam się, Haskell to doskonały język. Ale jeśli ktoś nie chce się tego nauczyć i nie rozumie programowania funkcjonalnego, trudno byłoby docenić Haskella.
Arseni Mourzenko
10

Spadek czytelności sam w sobie jest wystarczającym problemem: drastycznie zmniejsza liczbę osób, które mogłyby potencjalnie utrzymać Twój projekt bez intensywnego szkolenia z twojej strony.

Dodatkowo,

  • Wdrożenie zagranicznego paradygmatu może kosztować więcej niż potencjalne oszczędności z jego wykorzystania
  • Dostosowanie zagranicznej funkcjonalności może być wadliwe, co zwiększa koszty utrzymania
  • Dostosowanie zagranicznej funkcjonalności może pchnąć stos technologii do granic wykraczających poza te wymagane przez natywną implementację.
dasblinkenlight
źródło
2
Kiedyś musiałem emulować dynamiczne wysyłanie C ++ (tabele wirtualne itp.) W waniliowej C i napotkałem dokładnie ten problem: programiści C, którzy nie rozumieli dynamicznego wysyłania, nie byli w stanie wnieść wkładu w projekt ani utrzymywać go.
comestorm
4

To nie jest tak dobry pomysł, jak się wydaje na papierze.

Przykład 1: Jeśli jesteś wystarczająco stary, możesz pamiętać dni, kiedy C był nowym dzieckiem w mieście. Programiści Pascala i Ady nie lubili krótkich nawiasów klamrowych typu C. Zdefiniowali begini endotworzyli klamrę i zamknęli klamrę i voila! CAda! Niefortunny wynik był brzydki z punktu widzenia Ady lub C.

Przykład 2, osobisty: Jedną z rzeczy, które bardzo mi się podobały w systemie Common Lisp Object System, są metody przed, po i wokół nich. Mogą być bardzo przydatne w wielu miejscach. Więc emulowałem tę koncepcję w C ++ w kilku wybranych miejscach. Jedynym sposobem na emulację tych konstrukcji w C ++ jest wymaganie od twórcy klasy pochodnej wywołania metody klasy nadrzędnej o tej samej nazwie we właściwym miejscu w kodzie. To wymagało od programistów, którzy wywodzili się z moich klas, co było nieco obce programowaniu w C ++, a być może wbrew ziarnom programowania w C ++. Bez względu na to, jak dobrze udokumentowano to wymaganie, ludzie po prostu nie przestrzegali wytycznych, ponieważ nie pasowało to do paradygmatu C ++.

David Hammen
źródło
2

Jakie problemy mogą wynikać z emulacji pojęć z innych języków?

Nieszczelne abstrakcje.

Jim G.
źródło
Przydałoby się podać więcej szczegółów w odpowiedzi. Artykuł dotyczy przypadku, w którym abstrakcja nie uwzględnia znaczącej optymalizacji wydajności, ale powiedziałbym, że większe problemy wynikają z niespójnego zachowania w rogu i niespójnych gwarancji; przykładem tego drugiego może być próba emulacji outparametrów w środowisku, które tak naprawdę ich nie obsługuje; C # zakłada, że ​​każda funkcja zawsze zapisuje wszystkie swoje outparametry, ale metody inne niż C # wywoływane metodami C # nie dają takiej gwarancji.
supercat
1

To może być wyjątkowo trudne. Wyobraź sobie, że próbujesz zaimplementować LINQ z C # w swojej aplikacji Java. A może po prostu dodać leksykalne zamknięcia do języka? Będziesz musiał napisać nowy kompilator, który da ci zupełnie nowy język.

Lub, w przypadkach, w których nie musisz implementować własnego języka, wyobraź sobie, że próbujesz zaimplementować metody zbierania przy użyciu funkcji wyższego rzędu (takich jak map) w języku, który nie ma bloków kodu lub funkcji lambda, zamknięć lub funkcji jako pierwsze obiekty klasy. Każda funkcja wyższego rzędu musi być zadeklarowana jako interfejs i jawnie zaimplementowana, a wszystkie stany, które zostałyby uchwycone w zamknięciu, muszą być jawnie zapisane w klasie implementującej. Jest o tyle dodatkowe pisanie i o wiele trudniejsze do odczytania, że ​​często nie jest tego warte.

psr
źródło