Privacy Policy Cookie Policy Terms and Conditions Normierte Programmierung - Wikipedia

Normierte Programmierung

aus Wikipedia, der freien Enzyklopädie

Die normierte Programmierung beschreibt den Versuch einer standardisierten Ablaufsteuerung eines Datenverarbeitungsprogramms. Sie war in DIN 66220 genormt und wurde mit DIN 66260 in Richtung strukturierte Programmierung weiterentwickelt. Beide Ansätze unterstützten die modulare Programmierung.

Normierte Programmierung ist eine verallgemeinerte Programmablaufsteuerung, die die Teilaufgaben eines Stapelprogrammes wie Dateneingabe, Gruppenkontrolle, Verarbeitung, Ausgabe in ein einheitliches, logisch klares, funktionelles Schema gliedert. Dieses Schema lässt sich unabhängig von der Aufgabenstellung und unabhängig von der Programmiersprache für alle kommerziellen Computerprogramme anwenden.

Inhaltsverzeichnis

[Bearbeiten] Zielsetzung

Laut eines kleinen Lehrbuchs von 1971 eines großen BUNCH-Computerherstellers mit dem Titel „Logik der Programmierung, Normierte Programmierung“, mit dem damals angehende Programmierer und Systemanalytiker ausgebildet wurden, war das Ziel der normierten Programmierung Vereinheitlichung und Standardisierung der Programmerstellung, Verkürzung der Programmierzeit, Ausschaltung möglicher Fehlerquellen und damit Verkürzung der Testzeit und Senkung der Kosten für die Programmierer.

[Bearbeiten] Die normierte Programmierung

Kernstück der normierten Programmierung ist die Programmablaufsteuerung. Die normierte Programmierung erzwingt die logische und funktionelle Ordnung eines Programms durch eine vereinheitlichte Programmablaufsteuerung, die unabhängig vom jeweiligen Programmierer ist.

[Bearbeiten] Das Schema der Programmablaufsteuerung

Blockunterteilung der normierten Programmierung

Der Programmablauf ist in Blöcke unterteilt, wobei jeder Block einen funktional zusammengehörigen Teil eines Programmes darstellt. Die Unterteilung stellt sozusagen den "natürlichen" Aufbau eines kommerziellen Programms dar: Vor Beginn der eigentlichen Verarbeitung sind Anfangswerte zu setzen und Steuerinformationen auszuwerten, dann sind Eingabedaten zu lesen, der nächste Satz zur Verarbeitung ist auszuwählen, eventuell müssen Gruppenwechsel behandelt werden, schließlich ist der Datensatz zu verarbeiten und gegebenenfalls sind Daten auszugeben. Jeder block stellt eine in sich geschlossene Einheit dar. Ein Block kann zur besseren Übersicht aus mehreren Unterblöcken bestehen. Der abgebildete Programmablaufplan zeigt folgende Blöcke:

  • A: Vorprogramm für alle einmalig durchzuführenden Programmschritte
  • B: Eingabe; sie besteht aus soviel Unterblöcken wie es serielle Eingabedateien gibt. In jedem dieser Blöcke wird nicht nur die eigentliche Eingabe abgehandelt sondern auch Plausibilitätsprüfungen und Reihenfolgekontrolle.
  • C: Satzfreigabe; auch dieser Block ist entsprechend der Anzahl der Eingabedateienen in eine Reihe von Unterblöcken unterteilt. Im Block C wird der Satz ausgewählt, der als nächster zur Verarbeitung freigegeben werden muss.
  • D: Gruppenkontrolle und Aufruf der Gruppenwechsel-Unterprogramme für alle Gruppenstufen.
  • E: Einzelverarbeitung; sie ist wiederum entsprechend der Anzahl Eingabedateien in Unterblöcke unterteilt.
  • F: Schlussprogramm für alle einmalig nach dem eigentlichen Programmablauf zu durchlaufenden Programmbefehle.
  • G: Unterprogramme der Gruppenverarbeitung; es gibt soviel Unterprogramme wie es Gruppenstufen gibt, jeweils für Vorläufe und Wechsel getrennt.
  • H: Unterprogramme der Einzelverarbeitung; diese Unterprogramme sollten möglichst klein und übersichtlich sein.
  • J: Unterprogramme der sequentiellen Ausgabe und der wahlfreien Ein-/Ausgabe; für jede der genannten Dateien gibt es ein Unterprogramm.

[Bearbeiten] Die Datenzufuhrsteuerung

Zum besseren Verständnis der Problematik der Datenzufuhr muss man sich vergegenwärtigen, wie ein Programm in Stapelverarbeitung (und nur diese gab es zu Zeiten der Erfindung der normierten Programmierung Ende der 1960er Jahre) aussah: Es gab fast ausschließlich sequentielle Dateien, die in einer bestimmten Sortierfolge vorliegen mussten. Mehrere Eingabedateien mussten Satz für Satz seriell in der richtigen Reihenfolge eingelesen und mit den passenden Sätzen der anderen Dateien abgemischt, verarbeitet, bei sequentiellen Plattendateien eventuell aktualisiert und ausgegeben werden. Die Dateien konnten als Lochkartenstapel, als Magnetbanddatei, als sequentielle Plattendatei und eventuell als Lochstreifen vorliegen. Plattendateien mit wahlfreiem Zugriff kamen erst Anfang der 1970er Jahre auf.

[Bearbeiten] Gruppenbegriffsfelder

Gruppenbegriffsfelder Normierte Programmierung

Das wesentliche Merkmal der normierten Programmierung ist die Automatik der Datenzufuhr. Bei der seriellen Eingabe von Daten aus mehreren Dateien liegt das Problem in der Auswahl des nächsten zu verarbeitenden Satzes. Der zentrale Schlüssel für die Steuerung des Programmablaufs ist der Gruppenbegriff, der in jedem Satz der Eingabedateien enthalten sein muss. Da die Gruppenbegriffe an unterschiedlichen Positionen der Eingabedateien liegen können, werden bei der normierten Programmierung die Gruppenbegriffe aus den Datensätzen herausgeholt und in separaten dateibezogenen Gruppenbegriffsfeldern von rechts nach links nach Gruppenstufen aufsteigend abgespeichert. Es gibt für jede Eingabedatei ein solches, bei allen Dateien gleich großes Gruppenbegriffsfeld - deshalb dateibezogen. Im Beispiel besteht das Gruppenbegriffsfeld der Eingabedatei 2 von rechts nach links aus der Dateinummer L2D ("2"), den Gruppenbegriffen L21 (Untergruppenbegriff), L22 (Hauptgruppenbegriff, L23 (Übergruppenbegriff), L24 (ein nochhöherer Gruppenbegriff) und aus dem Feld L2S für den Dateistatus. Die Felder Ln1 bis Ln4 können gemeinsam als LnM zur Paarigkeitsprüfung herangezogen werden. Die Namen der Felder wurden in Anlehnung an die damals weit verbreitete Terminologie von RPG (Report Program Generator) vergeben (L für Level, Gruppenstufe).

Neben den dateibezogenen Gruppenbegriffsfeldern gibt es zwei weitere, dateineutrale Felder, die für die Gruppenkontrolle verwendet werden:

  • LA enthält den Gruppenbegriff des letzten verarbeiteten Satzes
  • LN enthält den Gruppenbegriff des nächsten zu verarbeitenden Satzes

Die Größe stimmt mit der Größe der dateibezogenen Felder L0, L1, ... voll überein. Lediglich die Definition der Felder ist aus Zweckmäßigkeitsgründen für die Gruppenkontrolle anders gewählt worden. Im Beispiel dient das Feld LN1 zur Kontrolle der Untergruppe, das feld LN2 der Kontrolle der Hauptgruppe usw.

[Bearbeiten] Die Datei-Nummer

Nach Eingabe eines Satzes von jeder Datei muss von allen Sätzen jener ausgewählt werden, der als nächstes verarbeitet werden soll. Bei unterschiedlichen Gruppenbegriffen ist die Lösung einfach, der satz mit dem kleinsten Grupenbegriff ist als nächster zu verarbeiten. Sind die Gruppenbegriffe jedoch gleich (paarig), muss entschieden werden, welche Datei die höhere Priorität hat, d. h. die Dateinummer bestimmt die Priorität. Bei dem klassischen Fall einer Gegenüberstellung von Stamm- (z. B. Teilestamm) und Bewegungsdaten (z. B. Lagerbewegungen) bestimmem die Bewegungsdaten, ob die Stammdaten bearbeitet werden müssen oder nicht, der Bewegungssatz muss also als erster verarbeitet werden. Die Dateinummer – eine Konstante – bestimmt bei Paarigkeit der restlichen Gruppenbegriffe über die Priorität, je kleiner die Dateinummer umso höher die Priorität.

[Bearbeiten] Der Datei-Status

Der Dateistatus unterscheidet vier Zustände:

  • 0 = Satz nachziehen
  • 1 = Satz nicht nachziehen
  • 2 = Datei abgeschlossen
  • 3 = Datei nicht vorhanden

Am Anfang stehen die Zustände aller Eingabedateien auf 0 ("Satz nachziehen"). Nach dem Nachziehen einer Datei wird ihr Status auf 1 gesetzt. Erst wenn sie zur Verarbeitung freigegeben wird, wird der Status wieder auf 0 gesetzt. Der Status 3 kann z. B. auf Grund von Vorlaufdaten Ablaufvarianten mit unterschiedlichen oder vorhandenen/nicht vorhandenen Dateien steuern.

[Bearbeiten] Der Steuerungsmechanismus

Die beiden Felder am rechten und linken Rand der Gruppenbegriffsfelder haben also eine besondere Bedeutung, die Dateinummer musste wohl überlegt sein, insbesondere bei seriell zu verarbeitenden sogenannten Update-Dateien wie Lesestanzern (Lochkartenleser und -stanzer in einem Gerät) oder Plattendateien. Ihnen gebührte die kleinste Priorität (= höchste Dateinummer), weil sie von allen anderen Sätzen der gleichen Gruppe eine Veränderung erfahren mussten.

[Bearbeiten] Der Aufbau der Blöcke

[Bearbeiten] Block A: Vorprogramm

Hier wurden sogenannte Vorlaufkarten gelesen, mit denen das Programm gesteuert wurde, Laufvarianten ausgewählt, das Laufdatum gesetzt, Dateien (mit dem Befehl OPEN) eröffnet, Tabellen geladen, Schalter gesetzt, kurz alle einmaligen Arbeiten vor Beginn des Programmzyklusses.

[Bearbeiten] Block B: Eingabe

Der Block B ist je nach der Anzahl der sequentiellen Eingabedateien in Unterblöcke B0, B1, B2, ... unterteilt, die nacheinander durchlaufen werden. Je nach Dateistatus wird ein Satz nachgelesen oder nicht. Nach der Eingabe erfolgt die Prüfung auf Dateiende. Falls nicht werden die dateispezifischen Gruppenbegriffsfelder beschickt und der Dateistatus auf "nicht nachziehen" gesetzt. Da man nicht sicher sein konnte, dass eine Eingabedatei auch wirklich in der richtigen Sortierfolge war (ein Stapel Lochkarten konnte dem Operator aus der Hand gefallen sein), erfolgte in diesem Block auch eine Reihenfolgekontrolle oder andere Plausibilitätsprüfungen.

[Bearbeiten] Block C: Satzfreigabe

Im Block C erfolgte auf Grund der Inhalte der Gruppenbegriffsfelder die Auswahl und Freigabe des nächsten zu verarbeitenden Satzes. Ab wann und wie lang (i. S. von Block G) Datensätze 'verfügbar' sind, hängt von der Verwendung dateibezogener Workbereiche ab und sollte in der Implementierung der Steuerungslogik genau festgelegt werden.

[Bearbeiten] Block D: Gruppenkontrolle

Die Gruppenkontrolle erfolgt mit Hilfe der dateineutralen Gruppenbegriffsfelder LN und LA. Zur Prüfung eines Untergruppenwechsels werden LN1 und LA1 verglichen, für eine Gruppenwechsel LN2 und LA2 usw. Bei Gruppenstufenwechseln werden Unterprogramme des Blocks G aufgerufen (G1, G2, G3, ...).

[Bearbeiten] Block G: Gruppenverarbeitung

Hier wird verarbeitet, was am Ende bzw. am Anfang eines jeden Gruppenbegriffs zu tun ist. Aufruf nur für die in Block D festgestellten Gruppenstufen, zuerst die Wechsel (von unten nach oben), dann die Vorläufe (von oben nach unten). Je Gruppenbegriff wird nach Gruppen-Vorlauf (Beispiel: Ausgabe einer Listen-Kopfzeile) und Gruppen-Wechsel (Beispiel: Ausgabe von Summen) unterschieden. Die Ausführung der Vorläufe und der Wechsel liegt zeitlich weit auseinander.

[Bearbeiten] Block E: Einzelverarbeitung

Im Block E erfolgt die Verarbeitung der einzelnen Sätze aus den steuernden Eingabedateien. Nachdem die Zuständigkeit des Unterblocks (E1, E2, ...) festgestellt ist werden je nach Satzart Daten zwischengespeichert, kumuliert, ausgegeben (durch Aufruf eines Unterprogrames des J-Blockes), Schalter zurückgesetzt (z. B. QL1, QL2, QG1, QG2, ... auf die Schalter der normierten Programmierung wird hier nicht eingegangen), usw.

[Bearbeiten] Block H: Unterprogramme der Verarbeitung

„Die häufige Verwendung von Unterprogrammen ist sehr zu empfehlen. Selbst wenn ein bestimmter Verarbeitungsteil im Programm nur einmal vorkommt, kann es sinnvoll sein, diesen Teil in ein Unterprogramm auszulagern, um die Ablauflogikdes Verarbeitungsprogramms entsprechend klar und übersichtlich herauszuarbeiten.“ ("Logik der Programmierung - Normierte Programmierung" SPERRY UNIVAC um 1970)

[Bearbeiten] Block J: Unterprogramme der seriellen Ausgabe und wahlfreien Ein-/Ausgabe

Es wurde dringend empfohlen, alles was zur Ausgabe im weitern Sinn gehört, in diese Unterprogramme auszulagern, also z. B. Druckbereiche löschen, bei Randomdateien die Satzadresse berechnen, Steueranweisungen für bestimmte Geräte absetzen usw.

[Bearbeiten] Block F: Schlussprogramm

Hierzu gehört das Schließen von Dateien, die Ausgabe von z. B. Schlusssummen und die Beendigung des Programms.

[Bearbeiten] Die besonderen Merkmale der normierten Programmierung

Die Programmierzeit wurde im Vergleich zur „wilden“ Programmierung wesentlich verkürzt, ebenso die Testzeit. Das System ist relativ einfach zu erlernen, ist unabhängig von Maschinentypen und Programmiersprachen und unabhängig von den jeweiligen Programmierern (entsprechend wurde es von "Künstlern" auch gerne abgelehnt). Jemand der die Methode der normierten Programmierung kennt, kann sich schnell in ein fremdes Programm, das dieser Methodik folgt, einarbeiten.

[Bearbeiten] Weitere Standardisierungen

Die Namensvergabe war ein weiteres Feld, bei dem Standardisierung angestrebt wurde, aber grundsätzlich haben wilde, auf den ersten Blick (oft auch noch beim dritten Blick) unsystematische Namen nichts mit Normierter Programmierung zu tun, genauso wenig wie Spaghettiprogramme oder gehäuft auftretende "GO TO"s. An einige Konventionen sollte man sich jedoch halten, zum Beispiel an die Namen für Schalter (QL1, QG1...), Blöcke (A-..., B1-..., E1-Personalstamm-..., etc), die Verwendung von verschiedenen Präfix für Konstanten (K...), Gruppenbegriffsfelder (L...), Schalter (Q...) usw.

[Bearbeiten] Kritik und Weiterentwicklungen

Die Einführung der normierte Programmierung in einem Unternehmen konnte dazu führen, dass Programme tatsächlich von mehreren Programmierern verstanden werden konnten, dass sie einfacher wartbar und erweiterbar waren. Man könnte behaupten, dass das Jahr-2000-Problem nicht entstanden wäre, wenn es keine normierte Programmierung gegeben hätte, denn die Programme wären bei weitem nicht so langlebig gewesen, weil ihre Wartbarkeit früher ein Ende gefunden hätte. Die Entwicklung ging weiter, leider nicht mit dem durchschlagenden Erfolg, den man sich damals wünschen konnte.

Ende der 1969er und in den 1970er Jahren drehte sich die Diskussion um Top-down-Vorgehensweise, schrittweise Verfeinerung und modulare Programmierung. Insbesondere die Vorschläge von E. W. Dijkstra zur strukturierten Programmierung wirken bis heute, konnten aber schon damals innerhalb von normierten Programmen realisiert werden. Einer schrittweisen Verfeinerung vor allem der Blöcke E, H und J stand die normierte Programmierung nicht im Wege. Die elementaren Grundstrukturen waren z. B. in COBOL verfügbar, ein „GO TO“-freies Programm mit normierter Programmierung war möglich, das Blockkonzept war also auch mit COBOL, ja sogar mit Assembler möglich. Der Lesbarkeit der Programme setzen bis heute die einzelnen Programmierer Grenzen, auch in C und Java, lediglich die Beschränkung der Datenverfügbarkeit war nur über separat kompilierte Programmmodule möglich.

THIS WEB:

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - be - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - closed_zh_tw - co - cr - cs - csb - cu - cv - cy - da - de - diq - dv - dz - ee - el - eml - en - eo - es - et - eu - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gd - gl - glk - gn - got - gu - gv - ha - haw - he - hi - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mg - mh - mi - mk - ml - mn - mo - mr - ms - mt - mus - my - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - rm - rmy - rn - ro - roa_rup - roa_tara - ru - ru_sib - rw - sa - sc - scn - sco - sd - se - searchcom - sg - sh - si - simple - sk - sl - sm - sn - so - sq - sr - ss - st - su - sv - sw - ta - te - test - tet - tg - th - ti - tk - tl - tlh - tn - to - tokipona - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu

Static Wikipedia 2008 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Static Wikipedia 2007:

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - be - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - closed_zh_tw - co - cr - cs - csb - cu - cv - cy - da - de - diq - dv - dz - ee - el - eml - en - eo - es - et - eu - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gd - gl - glk - gn - got - gu - gv - ha - haw - he - hi - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mg - mh - mi - mk - ml - mn - mo - mr - ms - mt - mus - my - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - rm - rmy - rn - ro - roa_rup - roa_tara - ru - ru_sib - rw - sa - sc - scn - sco - sd - se - searchcom - sg - sh - si - simple - sk - sl - sm - sn - so - sq - sr - ss - st - su - sv - sw - ta - te - test - tet - tg - th - ti - tk - tl - tlh - tn - to - tokipona - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu

Static Wikipedia 2006:

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - be - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - closed_zh_tw - co - cr - cs - csb - cu - cv - cy - da - de - diq - dv - dz - ee - el - eml - en - eo - es - et - eu - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gd - gl - glk - gn - got - gu - gv - ha - haw - he - hi - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mg - mh - mi - mk - ml - mn - mo - mr - ms - mt - mus - my - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - rm - rmy - rn - ro - roa_rup - roa_tara - ru - ru_sib - rw - sa - sc - scn - sco - sd - se - searchcom - sg - sh - si - simple - sk - sl - sm - sn - so - sq - sr - ss - st - su - sv - sw - ta - te - test - tet - tg - th - ti - tk - tl - tlh - tn - to - tokipona - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu