Kiedy użyteczne byłoby użycie języka skryptowego w większym programie?

70

Słyszałem o kilku sytuacjach osób używających powiedzmy, JavaScript lub Python (lub coś takiego) w programie napisanym w C #. Kiedy użycie języka takiego jak JavaScript do zrobienia czegoś w programie C # byłoby lepsze niż po prostu zrobienie tego w C #?

Toby Person
źródło
1
Dlaczego ktoś miałby głosować za tym pytaniem? IMHO to dobre pytanie.
KK.
28
Jest to bardzo przydatne do tworzenia absurdalnie skomplikowanych programów, które wymagają drogich konsultantów, aby je utrzymać, szczególnie gdy język skryptowy jest okropny.
whatsisname
2
Nie mam „odpowiedzi”, powiedzmy, ale Pragmatic Programmer ma rozdział na ten temat (# 12 - Domain Languages). Może zapewnić ci pewien wgląd.
Craige
1
Istnieje kilka dobrych odpowiedzi na podobne pytanie dotyczące rozwoju gier: gamedev.stackexchange.com/questions/2913/…
celion
6
Czasami jeszcze lepiej jest mieć duży system w języku skryptowym - nazywa się to „ sposobem uniksowym ”. Możesz skleić wiele różnych podsystemów, używając niewielkiej warstwy skryptowej. Ta architektura jest znana jako bardzo solidna i skalowalna.
SK-logic

Odpowiedzi:

66

Gdy masz zachowanie, którego nie chcesz rekompilować w celu zmiany. Właśnie dlatego tak wiele gier używa Lua jako języka skryptowego / modującego.

użytkownik16764
źródło
42
A także, aby użytkownicy mogli sami dodawać funkcje. W pewnym sensie to sugerowałeś, ale myślę, że jest to wystarczająco ważne, aby zasługiwać na większe podkreślenie.
2
Również piaskownica. Spójrz na integrację Pythona w blenderze.
meawoppl
@meawoppl ... lub w celu dodania funkcjonalności do programu. Spójrz na integrację Pythona przez IDA (nazwaną IDAPython)
Cole Johnson
Dlaczego nie uczynić tego tak, aby trzeba było ponownie skompilować tylko jedną bibliotekę (np. Z określonymi elementami logiki gry)?
Den
Jeśli spojrzysz na inne narzędzia, takie jak AutoCAD, Sparx Enterprise Architect, MS Word, nie musisz ich przekompilować w celu skryptu w C #.
Pete Kirkham
28

Technikę tę można zastosować do zaimplementowania podstawowej logiki, którą można łatwo przenosić między różnymi środowiskami językowymi. Na przykład mam symulator kalkulatora, w którym cała logika kalkulatora wewnętrznego jest zaimplementowana w 100% JavaScript. Kod interfejsu użytkownika jest oczywiście różny dla każdej platformy:

  • Przeglądarka internetowa (JavaScript)
  • iOS (Objective-C)
  • Windows (C ++ z Qt)
  • Mac OS X (C ++ z Qt)
  • Java Swing (Java)

Dzięki takiemu rozwiązaniu tworzenie wersji mojego programu dla różnych środowisk operacyjnych, a zwłaszcza aktualizowanie ich, jest znacznie prostsze.

Greg Hewgill
źródło
18

Bardzo ogólnie istnieją dwie sytuacje, w których zastosowałbyś ten wzór:

  1. Jest to wykorzystywane wewnętrznie w celu zwiększenia jakości języka osadzonego.
  2. Służy to do programowania zewnętrznego.

Wewnętrznie

  • Zazwyczaj język osadzony jest interpretowany, co umożliwia szybkie wprowadzanie i testowanie zmian bez ponownej kompilacji.
  • Język osadzony może być bardziej wyrazisty niż język, w którym napisana jest Twoja podstawowa aplikacja, co ponownie pozwala na szybszy rozwój.
  • Język ten może lepiej pasować do określonej domeny w porównaniu z językiem ogólnego przeznaczenia.
  • Z tego języka korzystają użytkownicy wewnętrzni, którzy potrzebują „prostszego” języka / środowiska programowania. Krótkie programy są pisane przez osoby, które nie są programistami używającymi stosunkowo prostej składni / interfejsu API.

Przykładem może być Lua zastosowana w Adobe Lightroom.

Więc to, co robimy z Luą, to zasadniczo cała logika aplikacji, od uruchomienia interfejsu użytkownika do zarządzania tym, co faktycznie robimy w bazie danych. Prawie każdy fragment kodu w aplikacji, który można opisać jako podejmowanie decyzji lub wdrażanie funkcji, znajduje się w Lua, dopóki nie przejdziesz do surowego przetwarzania, które jest w C ++. ( Wywiad z Mark Hamburgiem: Adobe Photoshop Lightroom )

Zewnętrznie

  • Zezwól użytkownikom na rozszerzenie działania aplikacji bez konieczności posiadania specjalnych narzędzi i / lub bibliotek i / lub dostępu do kodu źródłowego.
  • Zapewnij tym użytkownikom dobrze zdefiniowany interfejs API i środowisko izolowane. Można to również zrobić w języku aplikacji, ale osadzenie interpretera może to ułatwić.

IBM z powodzeniem stosował języki skryptowe w systemie operacyjnym VM-CMS na komputerze mainframe . EXEC , EXEC / 2 i później Rexx były używane w całym systemie zarówno wewnętrznie, jak i zewnętrznie. Różne aplikacje (np. XEDIT ) były skryptowalne przy użyciu tych samych języków, a wewnętrzne aplikacje / narzędzia (np. E-mail) zostały napisane w języku skryptowym i wykorzystały ścisłą integrację z systemem operacyjnym i innymi narzędziami. Klienci stworzyli i udostępnili wiele skryptowych narzędzi i aplikacji. DEC dostarczył również DCL . Później Microsoft obsługiwał VBscript jako język skryptowy w większości swoich aplikacji, a ostatnio PowerShell(także pliki wsadowe MS / DOS ). Powłoki Unix mają również skrypty .

Obecnie wydaje się, że trend ujawnia interfejsy API i pozostawia wybór języka skryptowego użytkownikom, którzy mogą korzystać z różnych powiązań lub innych sposobów uzyskiwania dostępu do interfejsu API.

Guy Sirton
źródło
9

Przykłady rzeczywiste obejmują:

  • Większość przeglądarek internetowych, które będą obsługiwać osadzony JavaScript.

  • Microsoft Office Suite - Excel Word itp. Wszystkie obsługują osadzone skrypty VBA.

  • Wiele routerów sieciowych zawiera interfejsy API skryptów w różnych językach TCL, Perl, Lua.

Wiele wbudowanych urządzeń jest implementowanych przy użyciu bardzo małego zestawu podstawowych funkcji C, które są sklejane za pomocą języka skryptowego, takiego jak Lua. Masz więc zestaw małych, szybkich funkcji C, które współdziałają ze sprzętem, a także większość logiki sterowania w elastycznym, łatwym do zmiany języku skryptowym.

James Anderson
źródło
@ antony.trupe. Nazwa powszechnie używana w odniesieniu do ECMAscript - en.wikipedia.org/wiki/ECMAScript
James Anderson
4

Czasami skrypty są osadzone w aplikacji, ponieważ są sposobem na rozszerzenie aplikacji hosta przez innych programistów. Aby uchwycić jak najszerszy zakres umiejętności programowania, host może obsługiwać wiele języków skryptowych. Na przykład w JVM można osadzić całą gamę języków zgodnych z JSR-223 , w tym Python, Ruby, JavaScript itp.

Innym niewymienionym jeszcze powodem jest to, że język osadzony ma jedną lub więcej wyróżniających się funkcji, których języka hosta nie można łatwo powielić. Przykładem może być Parse lub bezproblemowe tworzenie DSL (specyficzny dla domeny język / dialekt), które można znaleźć w języku takim jak Rebol.

Adrian
źródło
3

Jest jeden interesujący sposób użycia języka skryptowego w aplikacji, o którym inni jeszcze nie wspominali.

Jeśli Twój język hosta ma bogate, refleksyjne środowisko wykonawcze, często przydatne jest osadzenie prostego języka z REPL w swoich aplikacjach, zaczepienie go w gnieździe i zapewnienie dostępu do całego systemu.

Może być używany do interaktywnego debugowania (i jest naturalnie znacznie potężniejszy niż zwykły debugger), łatania kodu, różnych celów monitorowania, a nawet backdoorów (jeśli nie jesteś dobry).

Logika SK
źródło
Oczywiście o wiele potężniejszy niż zwykły debugger? W jaki sposób? W jaki sposób „prosty zewnętrzny język skryptowy” bez wewnętrznej znajomości idiomów języka hosta, modelu pamięci, modelu obiektowego, podstawowych typów danych itp. Może zapewnić użyteczne funkcje, których debugger zaprojektowany do pracy z tym językiem nie mógłby?
Mason Wheeler
@MasonWheeler, czy możesz zmienić kod za pomocą zwykłego debuggera? Czy możesz wykonać dowolne złożone programowalne zapytania dotyczące stanu środowiska wykonawczego? Czy możesz wykonywać skomplikowane kontrolowane eksperymenty? I mylisz się, zakładając, że język skryptowy nie ma „wewnętrznej wiedzy na temat idiomów języka gospodarza ...”. Jeśli zarówno host, jak i język skryptowy działają na tej samej maszynie wirtualnej (.NET, JVM, V8, cokolwiek), masz pełny dostęp do wszystkich elementów z twojego języka skryptowego.
SK-logika
1

Moja szczególna sytuacja, gdy korzystam z interpretowanego języka skryptowego w dużej aplikacji:

Istnieje urządzenie zewnętrzne, które wykonuje kilka funkcji. Pomiary, kontrola, odczyty. Sam jest dość „głupi” i wymaga precyzyjnej kontroli krok po kroku, w tym wielu stanów oczekiwania i doraźnego podejmowania decyzji po stronie mechanizmu kontroli.

Różne funkcje urządzenia są wymagane w różnych punktach głównej aplikacji, w różnych momentach, często na żądanie. Główna aplikacja nie dopuszcza stanów oczekiwania jako takich, wszystko musi być zrobione za pomocą skończonych maszyn stanu.

Teraz, kto napisał maszynę skończonego stanu, wie, że realizacja stanu oczekiwania ma efektywnie co najmniej dwa, często trzy lub cztery wewnętrzne stany maszyny. Wdrożenie dwudziestu stanów oczekiwania dla różnych funkcji (i oczekiwanie na ich reakcje i odpowiednie reagowanie) urządzenia zewnętrznego byłoby bardzo, bardzo frustrującym doświadczeniem.

Zatem zamiast tego istnieją stany: „wykonuj funkcję bez czekania”, „wykonaj funkcję blokującą”, „wykonaj funkcję rozgałęzienia / warunkowego / skoku” w maszynie stanów skończonych, może łącznie sześć stanów. Istnieją skrypty sterujące, które są planowane do wykonania, a następnie wykonywane przez interpretera sterującego urządzeniem zewnętrznym, a ich wyniki są umieszczane tam, gdzie są wymagane.

Podsumowując, aplikacja: w RTOS użycie wewnętrznego interpretowanego języka skryptowego może ogromnie zmniejszyć złożoność wykonywania zadań obficie występujących w stanach oczekiwania (funkcje blokujące).

SF.
źródło
1

Z mojego doświadczenia wynika, że ​​kiedyś opracowaliśmy dużą aplikację, która przepisuje kod źródłowy „starożytnego” języka, aby był zgodny z Unicode. Dokonano tego w języku C #. Skończyło się na tym, że napisałem tylko silnik (który tworzy model danych i zapewnia środki do wykonania kroków niezbędnych do procesu przepisywania) w C # - „kod kleju” do faktycznego wykonywania rzeczy jest wykonywany w IronPython.

Największy punkt dla zintegrowanego IronPython: Załóżmy, że załadowałeś duży model danych (czas ładowania około godziny). Następnie chcesz - ręcznie - zebrać informacje i wyszukać rzeczy. Robienie tego za pomocą skryptu Python z interaktywnej konsoli jest o wiele lepsze niż klikanie w model danych za pomocą debuggera (a ponadto można go odtwarzać).

użytkownik82229
źródło
-2

Jest kilka powodów.

  • Krzywa uczenia się. Praktycznie każdy może uczyć się i pisać w javascript.
  • Bezpieczeństwo. Trudno kontrolować kontekst bezpieczeństwa kodu skryptu w C # lub Javie. Javascript jest do tego idealny. Autor skryptu nigdy nie może uzyskać dostępu do dysku ani nigdzie, jeśli nie pozwala na to. Podstawowy silnik javascript to tylko zaawansowany kalkulator.
  • Jakość. Nakładasz bardzo gruby limit na kod skryptowy. Poziomy „kodu spaghetti” są bardzo różne dla Javascript lub C # / Java. (Co uniemożliwia ci otwarcie bram piekieł)
  • Wpisz bezpieczeństwo. C # / Java to środowisko bezpieczne dla typu, w większości nie preferujesz go w środowisku skryptowym. Wyrażenie takie jak „12” + 3 daje „123” w javascript, ale C # / Java nawet się nie skompiluje. Autorzy skryptów w większości nie mają nawet tego, co jest „typem”
  • Dynamiczny. Każdy obiekt może zawierać dowolną właściwość / metodę i może zmieniać swój typ w czasie. Na przykład mógłbym dostarczyć obiekt proxy C # do środowiska skryptowego, które udostępnia węzły XML jako właściwości.
  • Wydajność. Zwykle pisanie skryptu jest znacznie łatwiejsze niż C # / Java. Nie jest wymagana kompilacja ani „rejestracja wtyczek”. Możesz bezpośrednio edytować zawartość skryptu w aplikacji z natychmiastowymi wynikami.
  • Zarządzający. Korzystanie z C # / Java wymaga, aby SDK był łącznikiem we wtyczkach, które wystawiają klasy wewnętrzne na świat. Ta architektura wtyczek wymaga „kompatybilności wstecznej” dla starych wersji SDK. Ta architektura zmusza do tworzenia „wirtualnych” obiektów domeny, które zapewniają wewnętrzny mechanizm aplikacji w kontekście domeny. Jest łatwiejszy w zarządzaniu / elastyczny niż udostępnianie interfejsu API.
ertan
źródło
3
Pomija to sedno pytania o osadzanie skryptów w większym programie. Na przykład, dlaczego programista miałby dodać skrypt-fu do gimpa? A może modowanie Civ V za pomocą lua - dlaczego deweloper miałby dodawać skrypty do aplikacji?
-3

Kiedy? Pomiędzy 1948 a 2008 rokiem - początkowo skompilowane języki zajmowały dużo czasu na skompilowanie i połączenie, więc powszechnym było tworzenie języka skryptowego, który umożliwiałby dostosowanie i konfigurację użytkownika. Jeśli spojrzysz na historię AutoLisp, odpowiedź jest początkowo dostarczana z programem AutoCAD z językiem skryptowym, ale zostało to wycofane na korzyść udostępnienia skryptowego interfejsu VBA, a następnie .net.

Dzięki CLR włączenie programu C # lub wywołania programu Lua do istniejącego systemu nie różni się znacząco pod względem kosztów rozwoju, a środowisko uruchomieniowe .net jest dostarczane z narzędziami do generowania i kompilacji w locie.

Nie musisz już mieć języka skryptowego w większym programie, ale zamiast tego narażasz większy program na funkcje skryptowe środowiska wykonawczego.

W środowiskach, które nie oferują generowania i kompilacji kodu w locie i pożądane jest oferowanie języka automatyzacji ogólnego przeznaczenia zamiast języka specyficznego dla domeny, nadal będziesz otrzymywać skrypty Lua lub Python. W przypadku narzędzi oferujących interfejs COM językiem skryptowym będzie C # lub VB.net (MS Office, Sparx Enterprise Architect). Posiadanie języka skryptowego dla programu napisanego w języku, który sam w sobie jest tak prosty, że może być językiem skryptowym, nie jest konieczne.

Pete Kirkham
źródło
Wyszukiwarka Google dla gier XNA z skryptami Lua nie wyświetla zerowych wyników.
user16764
@ user16764, a wyszukiwanie w Google rowerów z bezy okazało się sześć milionów.
Pete Kirkham