View
2
Download
0
Category
Preview:
Citation preview
WAST
WittgensteinAdvancedSearchToolsDokumentation(Stand01/2014)(—WORKINPROGRESS—)
Dr.MaxHadersbeck&DanielBruder,M.A.,CIS,LMU
260CHAPTER34.SEMINARPLAN
TomPreston-Werner.2013.“SemanticVersioning2.0.0.”http://semver.org/.
uscilab.2014.“cerealDocs-Main.”http://uscilab.github.io/cereal/.
visionmedia.2014.“git-Extras.”https://github.com/visionmedia/git-extras.
Volos,Lyudmyla.2013.“DisambiguierungvonPartikelverb–Konstruktio-nenUndVerbpräpositional–KonstruktionenImBigTypescriptvonLudwigWittgenstein.”
2 259
Maurice, Gross. 1997. “The Construction of Local Grammars.” Finite-StateLanguageProcessing: 329–354.Meyers, Scott. 2005. Effective C 55 Specific Ways to Improve Your Programsand Designs. - Includes Index. Upper Saddle River NJ: Addison-Wesley.MongoDB. 2014. “MongoDB.” http://www.mongodb.org/.node. 2014. “node.Js.” http://nodejs.org/.Node API. 2014. “Addons Node.Js V0.10.25 Manual & Documentation.” http://nodejs.org/api/addons.html#addons_wrapping_c_objects.Pichler, Alois. 2010. “„Towards the New Bergen Electronic Edition“.” Wittgen-stein After His Nachlass. Edited by Nuno Venturinha: 157–172.Pichler, Alois, H.W. Krüger, D.C.P. Smith, T.M. Bruvik, A. Lindebjerg, and V.Olstad. 2009. “Wittgenstein Source Bergen Facsimile Edition (BTE).” Wittgen-stein Source. Bergen: WAB, Wittgenstein Source.R. Martinho Fernandes. 2013. “Rule of Zero @ Flaming Dangerzone.” http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html.Rothhaupt, Josef G. F. 2006. “Zur Dringend Notwendigen Revision Des „Stan-dard View“ Der Genese Der ‘Philosophischen Untersuchungen’.” Gasser, Georg/ Kanzian, Christian / Runggaldier, Edmund (Hg.): Cultures: Conflict - Anal-ysis - Dialogue. Papers of the 29th International Wittgenstein Symposium 2006,Kirchberg 2006: S. 278–280.Rothhaupt, Josef G. F. 1996. “Farbthemen in Wittgensteins Gesamtnach-laß. Philologisch-Philosophische, Untersuchungen Im Längsschnitt Und inQuerschnitten.” PhD thesis, Weinheim.Schiller, Anne, Christine Thielen, and Simone Teufel. 1999. “StuttgartTübinger Tagset (STTS).” http://www.ims.uni-stuttgart.de/forschung/ressourcen/lexika/TagSets/stts-table.html.Schmid, Helmut. 1994. “Probabilistic Part-of-Speech Tagging Using DecisionTrees.” Proceedings of International Conference on New Methods in LanguageProcessing, Manchester, UK.Seebauer, Patrick. 2012. “Verbesserung Der Suche Im Wittgenstein-Nachlass.Suche in Alternierenden Texten.”Strutynska, Olga. 2012. “Nachlass von Ludwig Wittgenstein: OptimierungEines Digitalen Lexikons Und Semantische Kodierung Der Nomen. EvaluationDes Lexikons Mit Hilfe von Konkordanzanalysen.”“Substitution Failure Is Not an Error.” 2014. Wikipedia, the Free Encyclope-dia. http://en.wikipedia.org/w/index.php?title=Substitution_failure_is_not_an_error&oldid=581401656.TEI Consortium. 2009. “Guidelines for Electronic Text Encoding and Inter-change.” TEI Consortium.
Contents
IWAST9
1WittgensteinAdvancedSearchTools11
1.1AbstractdesKurses.........................11
1.2SoftwarearchitekturundProjektmanagementamBeispielvonWAST–theoretischeGrundlagenundpraktischeÜbungen....11
1.3Projektstruktur............................13
1.4Projektstrukturextern:beteiligteInstitutionenundPersonen..13
1.5WASTProjektstrukturintern....................13
1.6Komponenten.............................16
IIwittfind17
2wittfind19
2.1Zweck.................................20
2.2Kurzvorstellung............................20
2.3Funktionen..............................20
2.4BeschreibungderverwendetenTechnologien............20
2.5Umfang,WertundGrößederCodebase..............20
2.6Mitwirkende..............................20
2.7Import/ExportausPaper......................20
3
258CHAPTER34.SEMINARPLAN
expressjs.2014.“Express-Node.JsWebApplicationFramework.”http://expressjs.com/.Fink,Florian.2013.“ProgrammingoftheRule-BasedWf.”Gaston,Gross.1991.“LaFormd’unDictionnaireElectronique.”LADL-Report.Laboratoired’AutomatiqueDocumentaireEtLinguistique.Gerdjikov,Stefan,StoyanMihov,PetarMitankin,andKlausU.Schulz.2013.“GoodPartsFirst-aNewAlgorithmforApproximateSearchinLexicaandStringDatabases.”arXiv:1301.0722[Cs](January).http://arxiv.org/abs/1301.0722.“Git-Submodules.”2014.http://git-scm.com/book/en/Git-Tools-Submodules.Gitlabcisgroup.2014.“GitlabCisGroup/Gitlab.”GitlabCisGroup/Gitlab.Google.2014.“AngularJS—SuperheroicJavaScriptMVWFramework.”http://angularjs.org/.Gotscharek,Annette,UlrichReffle,ChristophRinglstetter,KlausU.Schulz,andAndreasNeumann.2011.“TowardsInformationRetrievalonHistori-calDocumentCollections:theRoleofMatchingProceduresandSpecialLex-ica.”InternationalJournalonDocumentAnalysisandRecognition(IJDAR)14(2):159–171.doi:10.1007/s10032-010-0132-6.http://dx.doi.org/10.1007/s10032-010-0132-6.Grassi,Marco,ChristianMorbidoni,MicheleNucci,SimoneFonda,andFrancescoPiazza.2013.“Pundit:AugmentingWEBContentsWithSeman-tics.”LiteraryandLinguisticComputing.SpecialIssue“DigitalHumanities2012:DigitalDiversity:Cultures,LanguagesandMethods”.EditedbyPaulSpence,SusanBrownandJanChristophMeister28(4)(December).Guenthner,Franz,andPetraMaier.1994.“DasCISLEXWörterbuchsystem.”CIS-Bericht-94-76.Inenaga,Shunsuke,HiromasaHoshino,AyumiShinohara,MasayukiTakeda,andSetsuoArikawa.2001.ConstructionoftheCDAWGforaTrie.Krey,Angela.2013.“SemantischeAnnotationvonAdjektivenImBigType-scriptvonLudwigWittgenstein.”Langer,Stefan,andDanielSchnorbusch(Hrsg.).2005.SemantikImLexikon.Tübingen:Narr.Lindinger,Matthias.2013.“HighlightingvonTreffernDesToolsWiTTFindImZugehörigenFaksimile.”MarcoRogers.2013.“MarcoRogers:CreatingNodeAddons,C/C++ExtensionsforFunandProfit.”http://www.youtube.com/watch?v=q1ri36UI5GA&feature=youtube_gdata_player.MartinMoene.2013.“martinmoene/Lest·GitHub.”https://github.com/martinmoene/lest.
4 CONTENTS
III SIS 29
3 SIS: Symmetric Index Structures 31
3.1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.2 Zweck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3 Kurzvorstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.4 Verwendung auf der Kommandozeile . . . . . . . . . . . . . . . . 32
3.5 Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.6 Ebenen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
IV Feedback 69
4 feedback 71
4.1 Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.2 Application-Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
V Weitere Komponenten 75
5 wab2cis 77
5.1 Einbindung als git-submodule . . . . . . . . . . . . . . . . . . . . 77
6 WIndex 79
7 Patrick’s Teil: Ausformulierung von Alternativen 81
VI Toolchain 83
8 gitlab 85
9 Continuous Integration 87
9.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
9.2 CI@CIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
9.3 Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Bibliographie
Abrahams, David, and David Gurtovoy. 2005. C++ Template Metapro-gramming: concepts, Tools, and Techniques from Boost and Beyond. Boston:Addison-Wesley.Alexandrescu, Andrei. 2000. Modern C++ Design: applied Generic Program-ming and Design Patterns. Boston, MA; London: Addison-Wesley.Arseny Kapoulkine. 2014a. “pugixml.” pugixml. http://pugixml.org/.———. 2014b. “zeux/Pugixml.” GitHub. https://github.com/zeux/pugixml.Blumer, A., J. Blumer, D. Haussler, R. McConnell, and A. Ehrenfeucht. 1987.“Complete Inverted Files for Efficient Text Retrieval and Analysis.” J. ACM34 (3) (July): 578–595. doi:10.1145/28869.28873. http://doi.acm.org/10.1145/28869.28873.boost.org. 2014a. “Boost Test Library.” http://www.boost.org/doc/libs/1_55_0/libs/test/doc/html/index.html.———. 2014b. “Serialization.” http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html.C++1y Standard Committee. 2014. “xdbr/Cpp-Make-Unique.” GitHub. https://github.com/xdbr/cpp-make-unique.Daniel Bruder. 2012. “SIS – Symmetric Index Structures.” PhD thesis, LMUMünchen. www.cip.ifi.lmu.de/~bruder/ma/MA/sis/MA-SIS-DB.pdf.———. 2014. “xdbr/Cmake-Module-Submodule.Cmake.” GitHub. https://github.com/xdbr/cmake-module-submodule.cmake.Daniel Bruder, Florian Fink. 2014. “xdbr/Cpp-Generic-Serialize / GitHub.”https://github.com/xdbr/cpp-generic-serialize.“Day 1 Keynote - Bjarne Stroustrup: C++11 Style.” 2012. http://www.youtube.com/watch?v=0iWb_qi2-uI&feature=youtube_gdata_player.Di Gennaro, Davide. 2012. Advanced C++ Metaprogramming. S.l.: s.n.].Emscripten Authors. 2013. “Home · Kripken/Emscripten Wiki · GitHub.”https://github.com/kripken/emscripten/wiki.
257
CONTENTS5
10BuildSysteme91
10.1make..................................92
10.2cmake.................................92
10.3rake..................................96
10.4gyp...................................97
11Web99
11.1Web-Applikationen..........................99
11.2MEAN-Stack.............................102
11.3Jade..................................105
12XML107
12.1TEI..................................107
12.2XPath.................................107
13Dokumentation109
13.1pipelinemitgpp,ppp&pandoc...................109
14UnifiedDeployment113
14.1wast-infrastructure..........................113
14.2userwastd...............................116
VIITechniken119
15C++121
15.1WrappingvonCnachC++.....................121
15.2PolicybasedDesign.........................125
15.3Typetraits..............................127
15.4TemplateMetaProgrammierung..................129
15.5SFINAE................................129
15.6SilentDegredation..........................130
15.7StaticDispatching/Tagdispatch..................132
15.8Detail-Beschreibung.........................133
256CHAPTER34.SEMINARPLAN
SitzungDatumThemenHausaufgabeVorbereitungfürnächsteSitzung
409.05.2014Serialisierung:SerialisierunginC++/VerschiedeneLibrarieszurSerialisierung/Verwendungvon“cerealzurSerialisierung/ZweistufigeSerialisierunginSIS
Übung5:Serial-isierung
Web-Apps/MEAN-Stack/Techniken:Node-Wrapping
5(16.05.2014)–Betriebsausflug–
623.05.20147(30.05.2014)806.06.2014913.06.201410(20.06.2014)1127.06.20141204.07.20141311.07.2014
Table34.1:Seminarplan
6 CONTENTS
15.9 Bemerkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
15.10Wrapping von C++ nach Javacript (Node) . . . . . . . . . . . . 134
16 Serialisierung 135
16.1 Methoden zur Serialisierung . . . . . . . . . . . . . . . . . . . . . 135
16.2 Formate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
16.3 Klassische Verfahren: Binärformat und byte-layout . . . . . . . . 137
16.4 APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
17 Node Wrapping 145
17.1 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
17.2 Node Addon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
17.3 Schematische Darstellung . . . . . . . . . . . . . . . . . . . . . . 146
17.4 Demonstration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
18 Design Patterns 155
18.1 MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
18.2 MVVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
18.3 MV* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
18.4 (Teile aus SIS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
VIII Best Practices 157
19 Test Driven Development 159
19.1 Motivation und Vorteile . . . . . . . . . . . . . . . . . . . . . . . 159
19.2 Arten von Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
20 Bug tracker 165
20.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
20.2 WAST-Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
21 Versionierung 171
21.1 git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Chapter 34
Seminarplan
Sitzung Datum Themen HausaufgabeVorbereitung für nächsteSitzung
1 11.04.2014 Einführung /WAST:Projekt-Landschaft /Seminarplan /Hinweise zurDokumenta-tion
Übung 1:git
Techniken-Kapitel zumThema Wrapping von Cnach C++ / C-WrappingBeschreibung in SIS
N/A 18.04.2014 Stunde findetnicht statt
2 25.04.2014 C-Wrapping Übung 2:C-Wrapping
cmake, TDD
3 02.05.2014 Build-Systeme /Test DrivenDevelopment
Übung 3:cmake +Übung 4:cmake
Einschlägige Kapitel zuSerialisierung
255
CONTENTS7
22SemanticVersioning189
22.1Versions-Schema...........................189
23Lizenzen191
23.1GNUGPL...............................192
23.2MIT..................................192
23.3CreativeCommons..........................192
23.4WTFPL................................192
24Mailingliste193
IXÜbungen195
25Übungen197
25.1Übung1:gitundKollaboration...................199
25.2Übung2:C-Wrapping........................201
25.3Übung3:cmake...........................203
25.4Übung4:TDD–TestDrivenDevelopment............205
25.5Übung5:Serialisierung.......................207
25.6Übung6:Node-Wrapping......................209
25.7Übung7:TemplateMetaProgrammierung............211
25.8Übung8:TypeTraits........................213
25.9Übung9:Web-ProgrammierungmitdemMEAN-Stack.....215
XAppendix217
26Disclaimer219
27Dank221
28Überblickstabellen223
28.1Komponenten,Maintainer,Dependencies.............223
28.2Mitwirkende..............................227
254CHAPTER33.DEFINITIONEN
SFINAESubstitutionFailureIsNotAnError
RAIIResourceAcquisitionIsInitialization
8 CONTENTS
29 Workflows 231
29.1 git branching model workflow . . . . . . . . . . . . . . . . . . . . 231
29.2 Continuous Integration Workflow . . . . . . . . . . . . . . . . . . 231
29.3 WAST pipeline . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
29.4 bug tracking workflow . . . . . . . . . . . . . . . . . . . . . . . . 231
30 Hinweise 237
30.1 History Visualisierung (gource) . . . . . . . . . . . . . . . . . . . 237
31 next steps 239
31.1 E2E-Tests für Feedback, SIS, wittfind-web . . . . . . . . . . . . . 239
31.2 Integration-Tests und Projekt-Organisation . . . . . . . . . . . . 239
31.3 Integration von SIS und Feedback in wittfind-web . . . . . . . . . 239
31.4 Integration der restlichen 5000 Facsimile Seiten und Transkrip-tionen (in SIS und wf) . . . . . . . . . . . . . . . . . . . . . . . . 239
31.5 Erweiterung von WAST auf *AST: Öffnung und Aufbereitung fürandere Editionsprojekte. . . . . . . . . . . . . . . . . . . . . . . . 239
32 Ressourcen 241
32.1 UML Legende . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
32.2 Literatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
32.3 Kontakt, Ansprechpartner . . . . . . . . . . . . . . . . . . . . . . 243
33 Definitionen 253
34 Seminarplan 255
Bibliographie 257
Chapter 33
Definitionen
Deploy Defintion von Deploy
WAST Wittgenstein Advanced Search Tools
SPA Single Page Applicationaktuell modernste Variante von Web-Applikationenladen immer nur bestimmte Teile der Seite neu und es gibt keinen kom-pletten Refresh der Seiten
Fat Client innerhalb von MVC Applikationen deutliche Verschiebung vonBusiness-Logik vom Controller hin zum Clientkann Server-Kosten senkensiehe auch AngularJS
MVC Pattern für Applikationen: Model View Controller
AngularJS ein Web-Framework mit MVVM- bzw. MV*-Ansatzweicht bewusst den als zu starr empfundenen MVC-Ansatz auf (besondersausgeprägt bei Ruby on Rails)favorisiert Fat Client-Architektur
VCS version control system (z.B. svn)im Gegensatz zu DVCS
DVCS distributed version control system (z.B. git)im Gegensatz zu VCS
CTOR Constructor
DTOR Destructor
253
PartI
WAST
9
252LISTOFTABLES
List of Tables
3.1 Serialisierungsmöglichkeiten für DocumentIndexingAutomaton . . 58
20.1 Prioritäten bei Bugs . . . . . . . . . . . . . . . . . . . . . . . . . 167
34.1 Seminarplan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
251
Chapter1
WittgensteinAdvancedSearchTools
Inhalt1.1AbstractdesKurses....................111.2SoftwarearchitekturundProjektmanagementam
BeispielvonWAST–theoretischeGrundlagenundpraktischeÜbungen....................11
1.3Projektstruktur......................131.4Projektstrukturextern:beteiligteInstitutionenund
Personen..........................131.4.1DasCISunddieWittgensteinAdvancedSearchTools131.4.2WAB–WittgensteinArchiveBergen.........13
1.5WASTProjektstrukturintern..............131.5.1VerwaltenvonKomponenteninWAST........15
1.6Komponenten.......................16
1.1AbstractdesKurses
1.2SoftwarearchitekturundProjektmanage-mentamBeispielvonWAST–theoretischeGrundlagenundpraktischeÜbungen
DiesesHauptseminarerklärtGrundlagenderSoftwarearchitekturunddesProjektmanagementsamkonkretenBeispielvonWAST,denWittgenstein
11
250LISTOFFIGURES
29.1gitbranchingmodel.........................232
29.2ContinuousIntegration........................233
29.3WASTDataWorkflow........................234
29.4BugTrackingWorkflow.......................235
32.1UMLLegende:Class.........................241
32.2UMLLegende:SimpleAssociation.................242
32.3UMLLegende:Cardinality.....................242
32.4UMLLegende:DirectionalAssociation...............243
32.5UMLLegende:Aggregation.....................244
32.6UMLLegende:Composition.....................245
32.7UMLLegende:Inheritance.....................245
32.8UMLLegende:InterfaceInheritance................246
32.9UMLLegende:Dependencies....................246
32.10UMLLegende:Interface.......................247
32.11UMLLegende:ClasswithDetails..................247
12 CHAPTER 1. WITTGENSTEIN ADVANCED SEARCH TOOLS
Advanced Search Tools, das am CIS in Kooperation mit dem WittgensteinArchiv in Bergen (WAB) aktiv entwickelt wird.
Dabei richtet sich der Fokus zunächst auf die Architektur dieser Plattform, unddie Erklärung der einzelnen Komponenten sowie ihres Zusammenspiels. Desweit-eren werden die Schnittstellen und die Projektinfrastruktur an diesem konretenProjekt erläutert und die Prinzipien dahinter vorgestellt.
Begleitet wird das Seminar von praktischen (kleinen) Beispiel-Übungen, diehelfen, die wesentlichen Schritte tatsächlich selbst nachzuvollziehen und mod-erne Technologien und Frameworks kennenzulernen.
Besprochen und praktisch probiert werden in diesem Seminar: die Versionsver-waltung git und das am IFI angebotene gitlab als Web-Oberfläche zur Soft-wareverwaltung sowie Kollaboration mit anderen Entwicklern; das Wrappenvon Libraries, die in C geschreiben wurden in C++; das Erweitern derselbenC-Libraries mit neuen Funktionalitäten; das Einbinden der entstandenen C++-Libraries in Javascript, und damit in einem nächsten Schritt in den Browser;die Architektur von modernen Webseiten (auch als Single Page Applications –SPA – bekannt) in Form von Server/Client-Kommunikation; die Verwendungdes sogenannten MEAN-Stacks zur Umsetzung von Single Page Applications,d.h. das Zusammenspiel von MongoDB + ExpressJS + AngularJS + NodeJS.
Erwartet werden nicht zwingend Kenntnisse in allen vorgestellten, o.g. Tech-nologien und Frameworks, dafür aber ein hohes Maß an Willen, Belastbarkeit,Spielfreude, generellen, gut-bis-sehr-guten Programmierkenntnissen und, nichtzuletzt, die spielerische Neugierde, die leidenschaftliche Software-Entwicklerantreibt (nicht zuletzt diejenigen, deren Technologien wir verwenden). Dazugehört auch das exakte Lesen von Aufgaben-Spezifikationen und Programm-Dokumentation.
Als Lohn des dicht gepackten, umfangreichen Programms des Seminars mit,z.T. bedeutenden Sprüngen von Woche zu Woche, erhält man einen praktis-chen und einen theoretischen Einblick in konkrete, existierende Frameworks undStrukturen, sowie die Antwort auf die Frage: ich habe eine Kommandozeilen-Applikation in C++ – wie kann ich diese nun in den Browser transportierenund der Welt zugänglich machen?
List of Figures
1.1 WAST Projektstruktur . . . . . . . . . . . . . . . . . . . . . . . . 14
1.2 Die Landschaft von WAST . . . . . . . . . . . . . . . . . . . . . 15
3.1 SIS Schichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.2 Klassenarchitektur von SIS . . . . . . . . . . . . . . . . . . . . . 39
3.3 DocumentIndexingAutomaton UML . . . . . . . . . . . . . . . . 41
3.4 DocumentIndexingAutomatonAbstract UML . . . . . . . . . . . 42
9.1 Continuous Integration . . . . . . . . . . . . . . . . . . . . . . . . 88
10.1 Autotools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
11.1 Web Apps Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
13.1 Der Typesetting Process . . . . . . . . . . . . . . . . . . . . . . . 111
15.1 Adapter Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
16.1 Beispiel für ein Byte-Layout . . . . . . . . . . . . . . . . . . . . . 138
17.1 Node Wrapping Pattern . . . . . . . . . . . . . . . . . . . . . . . 147
20.1 Bug Tracking Workflow Status . . . . . . . . . . . . . . . . . . . 168
21.1 Git overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
28.1 WAST Komponenten und Dependencies . . . . . . . . . . . . . . 228
249
1.3.PROJEKTSTRUKTUR13
1.3Projektstruktur
1.4Projektstrukturextern:beteiligteInstitu-tionenundPersonen
1.4.1DasCISunddieWittgensteinAdvancedSearchTools
DieWittgensteinAdvancedSearchTools(WAST)sindeineKollektionvonver-schiedenenAnwendungendesCIS,diespezifischaufdasKorpusdesArchivsinBergen,Norwegen(WAB)entwickeltwurde.
WASTistentstandenauseinerzunehmendgewachsenenKooperationmitdemdesWABArchivsinBergen(vertretendurchAloisPichler)undMaxHadersbeck(CIS).
FürdieZusammenarbeitspielenfolgendeAspekteeinewesentlicheRolle:
•begrenztesMaterial•sehrreichhaltigaufbereitetes,sehrsauberes(kontrolliertesMaterial)
WittgensteinwiederumisteinSubteildesehemaligen(?)europäischenProjektsunterderLeitungvonPaoloD’Iorio(darunter,u.a.)
1.4.2WAB–WittgensteinArchiveBergen
1.5WASTProjektstrukturintern
DieTool-LandschaftvonWASTbestehtauszweiDingen:
a)Komponentenb)ToolsundProjektstruktur
ZudenKomponentenzählenalleDinge,die…,darunter:
•wittfind•SIS:SymmetricIndexStructures•feedback•wab2cis•WIndex
248CHAPTER32.RESSOURCEN
14 CHAPTER 1. WITTGENSTEIN ADVANCED SEARCH TOOLS
Figure 1.1: WAST Projektstruktur
Zu den Tools zählen alle Dinge, die …, darunter:
• wast-infrastructure• bug tracker• Versionierung• git• wiki
Die WAST-Infrastruktur (siehe Abschnitt 14.1 ab Seite 113) erlaubt es, dendeploy-Prozess und den Versionierungs-Prozess zu abstrahieren, indem alle Kom-ponenten unter einem Dach versammelt sind.
Zum Beispiel kompiliert und startet man dann die feedback-Komponente folgen-dermaßen:
./wast build wast-feedback-app && ./wast start wast-feedback-app
Die weiteren Komponenten funktionieren dann alle gleich und es ist wesentlicheinfacher, den Überblick zu behalten.
Alle von der WAST-Infrastruktur verwalteten Komponenten findet man ganzeinfach heraus, indem man
32.3. KONTAKT, ANSPRECHPARTNER 247
Figure 32.10: UML Legende: Interface
Figure 32.11: UML Legende: Class with Details
1.5.WASTPROJEKTSTRUKTURINTERN15
Figure1.2:DieLandschaftvonWAST
./wast
ohneArgumentestartet.HierbeiwerdensowohlalleKomponentenalsauchAktionenangezeigt.
1.5.1VerwaltenvonKomponenteninWAST
Komponenten-MaintainerkönnenihreKomponenteindieGruppecis(Gitlabcisgroup2014)überführenlassen–dazuistdanneineMailanThomasnotwendig(glaubeich).Vorteiledaraus:
a)dasProjektwirdimgitlabnichtmehrgegendaspersönlicheProjektlimitbeiderRBGgezählt
b)dasProjektistweniger“personenbezogen”undkannbesservonNachfol-gern“geerbt”werden
Komponenten-Maintainer,dieihreKomponenteindieWAST-Infrastrukturhinzufügenwollen,machenfolgendes:
1.Zunächst,dieKomponentealsgit-submodule[link:http://git-scm.com/book/en/Git-Tools-Submodules]adden:
gitsubmoduleaddgit@gitlab.cip.ifi.lmu.de:cis/wf.gitcomponents/wf
246CHAPTER32.RESSOURCEN
Figure32.8:UMLLegende:InterfaceInheritance
Figure32.9:UMLLegende:Dependencies
16 CHAPTER 1. WITTGENSTEIN ADVANCED SEARCH TOOLS
2. Am besten direkt die Remote-Bezeichnung[link: http://git-scm.com/book/en/Git-Basics-Working-with-Remotes] origin in upstream umbenennen (derEinheitlichkeit halber)git remote rename origin upstream
3. Im eigenen Projekt die wesentlichen Dateien anlegen (oder die, die manfür nötig hält):
• wast.build• wast.check• wast.start• wast.stop• wast.restart
Beispiele hierzu finden sich hier:https://gitlab.cip.ifi.lmu.de/cis/wast-feedback/tree/master
1.6 Komponenten
In den folgenden Teilen werden die wichtigsten Komponenten wittfind (Kapitel 2ab Seite 19), SIS (Kapitel 3 ab Seite 31), feedback (Kapitel 4 ab Seite 71),wab2cis (Kapitel 5 ab Seite 77) und WIndex (Kapitel 6 ab Seite 79) besprochen.
32.3. KONTAKT, ANSPRECHPARTNER 245
Figure 32.6: UML Legende: Composition
Figure 32.7: UML Legende: Inheritance
PartII
wittfind
17
244CHAPTER32.RESSOURCEN
Figure32.5:UMLLegende:Aggregation
32.3. KONTAKT, ANSPRECHPARTNER 243
Figure 32.4: UML Legende: Directional Association
• express manual
+++ END DEPRECATED +++
32.3 Kontakt, Ansprechpartner
• Max• Flo• Daniel• Patrick• Bug-Tracker• Webseite• irc
Chapter2
wittfind
Inhalt2.1Zweck............................20
2.2Kurzvorstellung......................20
2.3Funktionen.........................20
2.4BeschreibungderverwendetenTechnologien.....20
2.5Umfang,WertundGrößederCodebase.......20
2.6Mitwirkende........................20
2.7Import/ExportausPaper................20
2.7.1ResourceText:TEIP5conformXML........20
2.7.2ResourceLexicon:Electronicfull-formLexicon...21
2.7.3ThefinderApplicationsuite“.............21
2.7.4Implementationaspectsof...............22
2.7.5Lemmatizedandinvertedlemmatizedword-search.23
2.7.6Word-FormSearchandPart-of-SpeechTagging...23
2.7.7SemanticLexicalClassification............24
2.7.8SentencestructureandWildcards...........26
2.7.9Rule-basedlinguisticsearchwithPart-of-SpeechTag-ging(POS-tagging)...................26
2.7.10SearchwithoutAlternatives..............27
2.7.11SearchResultLayoutwiththeFacsimile.......27
19
242CHAPTER32.RESSOURCEN
Figure32.2:UMLLegende:SimpleAssociation
Figure32.3:UMLLegende:Cardinality
20 CHAPTER 2. WITTFIND
2.1 Zweck
2.2 Kurzvorstellung
2.3 Funktionen
2.4 Beschreibung der verwendeten Technologien
2.5 Umfang, Wert und Größe der Codebase
sloccount [link: http://www.dwheeler.com/sloccount/]
2.6 Mitwirkende
2.7 Import/Export aus Paper
The web-based frontend WiTTFind consists of several web programs which offeran easy to use interface to query Wittgenstein’s Nachlass and presents all searchresults as HTML-transformation of the edited text together with an excerptfrom the original facsimile of Wittgenstein’s remark. For the texts available onWittgenstein Source1, every result is linked to Wittgenstein Source as well asto the Semantic web annotation tool Pundit Grassi et al. (2013 ˆ7) (see Figure[fig:search])
2.7.1 Resource Text: TEI P5 conform XML
The XML-Transcription of Wittgenstein’s Nachlass Pichler (2010), which wasdeveloped at WAB in Bergen, annotates the texts in greatest detail. All dele-tions and substitutions etc. of Wittgenstein are annotated in the XML-texts.The latter is too detailed in order to be used by WAST and thus a new TEI P5TEI Consortium (2009) compatible and reduced XML-Format (CISWAB) wasdefined. This text format is an optimal base for the cooperation between theWittgenstein researchers and programmers in the field of computational linguis-tic. The CISWAB texts are extracted via XSLT-transformation from WAB’sXML-transcriptions of Wittgenstein’s Nachlass Pichler et al. (2009).
1http:/www.wittgensteinsource.org
Chapter 32
Ressourcen
32.1 UML Legende
Figure 32.1: UML Legende: Class
32.2 Literatur
<#startdeprecated>
• Daniel Bruder, SIS – Symmetrische Indexstrukturen, Magisterarbeit, CIS,LMU, 2012, [webadresse]
• Stroustrup• Di Gennaro• Herb Sutter• Alexandrescu• gitlab manual• git manual• git extras• node manual• angular manual
241
2.7.IMPORT/EXPORTAUSPAPER21
2.7.2ResourceLexicon:Electronicfull-formLexicon
Successfultextsearchescruciallyrelyontheavailabilityofanelectronicfull-formlexicon.FortheworkonWittgenstein’sNachlass,weusedCISLEXGuenthnerandMaier(1994),oneofthebiggestelectronicGermanfull-formlexica,whichhasbeendevelopedatCISoverthelast20years.WeextractedallwordsfromthetextsavailableonWittgensteinSource,thewordinformationfromCISLEXandextendedittothespeciallexicon,calledWiTTLex.Eachword-entryinWiTTLexisformattedaccordingtotheDELAformat,definedattheLab-oratoired’AutomatiqueDocumentaireetLinguistique(LADL),ParisGaston(1991).Thelexiconentriescontaintheword’sfull-form,lemma,lexicographicalwordform,inflectionandsemanticinformation.SearchqueriestoWiTTFindcanbegrammaticallyprocessedwiththehelpofWiTTLex.Figure[fig:dic]showsashortexcerptfromthelexicon.
[H]
Advokat,Advokat.N+HUM:neMgesagt,sagen.V:OZgesamte,gesamt.ADJ+NUM:aeFxp:aeFyp:aeFzp:aeNyp:\amUxp:neFxp:neFyp:neFzp:neMyp:neNyp:nmUxpdagestanden,dastehen.V+#2glänzende,glänzend.ADJ+ER+COL+GlanzFermat,.ENFermatsche,Fermat'sch.ADJ+ENrot,rot.ADJ+COL+Grundfarberötlicher,rötlich.ADJ+COL+Zwischenfarbe+KOMP:\deFxp:geFxp:gmUxp:neMxp:neMzp
[fig:dic]
2.7.3ThefinderApplicationsuite“
Inordertoprovideextendedlinguisticsearchcapabilitiesforexplorationsfromnon-technicalandnon-linguisticbackgrounds,asuiteoftoolswasdevelopedatCISSeebauer(2012;Krey2013;Fink2013;Volos2013).Withamixtureofimplicitandexplicitconversionsweareabletoprovideadvancedlinguisticsearchcapabilitiestoresearchersfromdifferentfieldsofthehumanities.Thenextsectionprovidesabottomupoverviewontheprogramsuite“,onesectionoutofWAST,thatisusedtofindtext,i.e.tofindutterancesofWittgenstein.
Everyqueryto“isinternallytransformedtoalocal-grammar-search-graphofthesearchtermsMaurice(1997).Initssimplestformthesegraphsareachainofthesearchterms.Butingeneralsearch-graphscancontainanarbitrarynumberofloopsandbranchestoexpresscomplexsearchpatternsFink(2013).
240CHAPTER31.NEXTSTEPS
22 CHAPTER 2. WITTFIND
The system uses various strategies to match tokens in the text. It is able touse i.a. string-based matching, regular expressions, semantic and morphologicalinformation from dictionaries and arbitrary annotations from the searched textitself.
In order to provide a simple interface to the user and hide much of the com-plexities involved, queries from the user are automatically converted to local-grammar-search-graphs. A simple query language enables the user to search forsequences of arbitrary length or combine tokens with boolean operators Fink(2013). Furthermore, the system applies implicit conversions on the queries togenerate more natural search results.
2.7.4 Implementation aspects of
The tool is implemented in a client-server architecture. There are three maintools involved in the processing of queries: A server-, a client- and a display-tool. The client merely takes queries from the user and applies some very basictransformation to them before sending the actual query to the server. Thesetransformations mostly convert convenient wildcard expressions to valid morecomplex regular expressions.
On the server side each query is parsed and then transformed to a local-grammar,that is applied asynchronously to the different documents the query wishes tosearch. One running server instance is able to provide parallel searches over avarious set of different documents. All results are then send back to the client.
The third tool is a simple displaying tool, that is able to output the result of thequeries in different formats2. Together these three tools provide the backendto present query results, that are further used by the WiTTFind front end topresent the final results of queries.
[H]
[tab:wfbenchmark]
Query type Median (seconds)
strict 0.082word phrase 0.080lemma-based 0.088
inverted lemma-based 0.088sentence 0.169
local grammar (particle verbs) 0.214
2At the time being, there are only two formats supported; one format for the web-service,and another format for the terminal.
Chapter 31
next steps
31.1 E2E-Tests für Feedback, SIS, wittfind-web
31.2 Integration-Tests und Projekt-Organisation
31.3 Integration von SIS und Feedback inwittfind-web
31.4 Integration der restlichen 5000 FacsimileSeiten und Transkriptionen (in SIS und wf)
31.5 Erweiterung von WAST auf *AST: Öffnungund Aufbereitung für andere Editionspro-jekte.
239
2.7.IMPORT/EXPORTAUSPAPER23
Table[tab:wfbenchmark]listsaviewbenchmarkingresultsofdifferentquerytypestoaserverinstancerunningonamoderndesktopPC3.Thenumberseachshowthemedianof10differentqueriestothetextoftheBigTypescriptAllquerieswherelimitedtoamaximumof100hits4.Itshouldbenoted,thatthelasttwolinesshowtheresultsofcomplexqueries,thatgenerateveryfewhits.Thesequeriestakealotmoretimetofinish(morethantwiceaslong),sincethewholedocumenthastobeprocessedandlocalgrammarsareusedtodisambiguate.
2.7.5Lemmatizedandinvertedlemmatizedword-search
Theelectronicfull-formlexiconWiTTLexallowstoperformlemmatizedqueriestotheNachlass.Forexample,thesearchfortheworddenken(think)returnsallsentenceswhichcontainmorphologicalvariantsoftheword,likedachte,gedacht.WealsoimplementedwiththehelpofWiTTLexaninvertedlemmatizedsearchwhereweusedthelemmaofthequeriedwordtoproduceallmorphologicalvariantsofit.Theworddachteleadstothelemmadenkenagain,fromwhichallwordvariantsarederived.
2.7.6Word-FormSearchandPart-of-SpeechTagging
Inthefull-formlexicon,WiTTLex,everywordisstoredtogetherwithitslexicalwordformasitisdefinedintheGermanCISLEX(seeTable[tab:tags]).
[H]
[tab:tags]
NameTagTranslation
Nomen<N>nounAdjektiv<ADJ>adjectiveVerb<V>verb
Determinativ<DET>determinerAdverb<ADV>adverbPartikel<PART>particle
Präposition<PREP>prepositionPräposition+Artikel<PDET>preposition+article
Konjunktion<KONJ>conjunction
3Intel2.90GHzQuadcore4Onthewebthelimitissetto25forunregisteredusers.
238CHAPTER30.HINWEISE
24 CHAPTER 2. WITTFIND
Name Tag Translation
Interjektion <INTJ> interjectionVerbpartikel <VPART> verb particleEigenname <EN> proper name
The finder allows for the use of word forms as placeholders for words in a query.For example, the query Die <ADJ> Farbe finds all sentences that contain the nom-inative feminine definite article Die, followed by an adjective, which precedesthe noun Farbe (colour) as in sentence ([ex:farbe]).
[ex:farbe]
[ex:farbe:q] Die <ADJ> Farbe [ex:farbe:a] Ich könnte Dir die genaue Farbe derTapete zeigen, wenn hier etwas wäre was diese Farbe hat.5
To further reduce the syntactic ambiguity of the word forms in the text, weadditionally tagged the data with the Part-of-Speech (POS) treetagger Schmid(1994). The finder permits POS-tags to be used as placeholders for the selectionof syntactic word forms, as defined in the Stuttgart-Tübingen-Tagset Schiller,Thielen, and Teufel (1999). The user can decide to search for a lexical wordform (e.g. <ADJ>) or the syntactic word-form within the sentence (e.g. [ADJ*]).
2.7.7 Semantic Lexical Classification
In WiTTLex we classified nouns Strutynska (2012) and adjectives Krey (2013)semantically. According to the work by Langer and Schnorbusch Langer and(Hrsg.) (2005) we defined eleven classes for nouns (see: Table [tab:semnoun])and eleven classes for adjectives (see: Table [tab:semadj]).
[H]
[tab:semnoun]
Name Tag Translation Occurrences
Menschen <HUM> humans 140Tiere <T> animals 96
Pflanzen <PF> plants 26Objekte <OBJ> objects 1402Ereignisse <ER> events 589
5I could show you the exact colour of the wallpaper if there was anything around that hasthis colour.
Chapter 30
Hinweise
30.1 History Visualisierung (gource)
Es ist nicht nur schön anzusehen, sondern oft auch aufschlussreich, sich dieVisualisierung der history per gource [webhinweis] anzusehen, um zu verstehenwie ein Projekt gewachsen ist
237
2.7.IMPORT/EXPORTAUSPAPER25
NameTagTranslationOccurrences
Zustände<ZU>states51Eigenschaften<EIG>pproperties236Temporalia<TEMP>time49Eigennamen<EN>propernames60Numeralia<NUM>number47Diversa<SONST>other713
NameTagTranslationOccurrences
Farben<COL>colour974Numeralia<NUM>number1258Relation<REL>relation2517
Eigennamen<EN>propernames17Temporalia<TEMP>time619Evaluation<EVAL>evaluation1732Zustände<ZU>states6629
Komparativa<KOMP>compariative2080Stilistika<STIL>style1917
Eigenschaft<EIG>property382Ereignisse<ER>proppperty187
InourinvestigationsinWittgenstein’sBigTypescript(BT)6,wefoundthatthereareabout1800nounsoutofall46000wordsinthedata(see:Table[tab:semnoun]and[tab:semadj]).AlltheTagsfromtheTablescanbeusedinWiTTFind.Forexample,thequery<EN>und<EN>returnsthesentence([ex:frege])inwhichthetwopropernamesFregeschenandRussellschenarejoinedbythecoordinatingconjunctionand.
[ex:frege]
[ex:frege:q]<EN>und<EN>[ex:frege:a]UnzulänglichkeitderFregeschenundRussellschenAllgemeinheitsbezeichnung.7
6http://www.wittgensteinsource.org/Ts-213_n7ShortcomingsofthedenominationofuniversalitymadebyFregeandRussell.
236CHAPTER29.WORKFLOWS
26 CHAPTER 2. WITTFIND
In cooperation with the Faculty of Philosophy, Philosophy of Science and theStudy of Religion, at the University of Munich (Rothhaupt Rothhaupt (1996)),we implemented a first semantic classification of Wittgenstein’s colour vocabu-lary together with a special HTML-interface for querying colours in the Nachlass.We found, that five different categories for colours are optimal for Wittgen-stein’s Nachlass: Grundfarbe (primary colour), Zwischenfarbe (intermediatecolour), Transparenz (transparency), Glanz (gloss) and Farbigkeit (colourness)Krey (2013). Table [tab:sem] shows the different labels for colours and thenumber of their occurrences in the text.
In the web-frontend WiTTFind, the user can select between different colourcategories (see: Table [tab:sem]), view statistics and query Wittgenstein’s Nach-lass.
2.7.8 Sentence structure and Wildcards
For the Wittgenstein researchers it is very important to take the sentence struc-ture into account. To enable users to specify the sentence structure withinqueries, we introduced sentence structuring tags in queries, such as <BOS> (thebeginning of a senctence), <EOS> (the end of a sentence) and <PUNCT> for punc-tuation characters. The wildcard operator * can be used as placeholder forarbitrary character sequences. The query: <BOS> Ich meine nur <PUNCT> * ** <PUNCT> <EOS> would return all sentences that consist of six words startingwith the sequence of three tokens Ich meine nur followed by a punctuationcharacter as in example ([ex:sage])
[ex:sage]
[ex:sage:q] <BOS> Ich meine nur <PUNCT> * * * <PUNCT> <EOS> [ex:sage:a] Ichmeine nur, was ich sage.8
[tab:sem]
|c|c|p2.0cm|c| Name & Tag & Translation & OccurrencesGrundfarbe & <Grundfarbe> & basic colour & 454Zwischenfarbe & <Zwischenfarbe> & intermediate colour & 301Transparenz & <Transparenz> & transparency & 105Glanz & <Glanz> & gloss & 2Farbigkeit & <Farbigkeit> & colourness & 29
2.7.9 Rule-based linguistic search with Part-of-SpeechTagging (POS-tagging)
To enrich the number of found verbs concerning a search query, we implementedan automatic particle-verbs detection and distinction. Particle-verbs are marked
8I only mean, what I say.
29.4. BUG TRACKING WORKFLOW 235
Figure 29.4: Bug Tracking Workflow
2.7.IMPORT/EXPORTAUSPAPER27
intheirlexicalentryanddividedintoverbandparticle.IntheBigTypescriptwefoundalmost750verbswithseparatedparticles.Todisambiguatetheseparatedparticlesfromprepositions,weusePart-of-Speechtaggingandlocalgrammars.Forexample,thequerywiththeparticleverbdastehenwouldextractinstancesas:stehtklarda…inwhichtheverbparticleda,whichmayoccurinGermanseparatelyfromtheverbstehen,isrecognizedassuchandnotasapreposition(see:Figure[fig:dastehen]).
2.7.10SearchwithoutAlternatives
OnecharacteristicfeatureofWittgenstein’sNachlassis,thatWittgensteinchangedhistextsveryoftenandasaresulttheNachlassoffersalotofdifferentreadings.Toenablethefindingofremarksinallofthelatter,inabackgroundprocessofthefinderapplication,wegeneratealldifferentreadings,whichareprocessedsimultaneouslySeebauer(2012).
2.7.11SearchResultLayoutwiththeFacsimile
LudwigWittgenstein’sNachlassishighlyheterogeneous.Itconsistsofalargenumberoftexts,someofthemhandwritten,withnumerouspassageseditedfromtheauthorhimself.Theresearcherscanonlyappreciatethefoundremarkstothefullestwithallitseditions,errorsandoverallform,iftheyseenotonlytheHTML-transformationoftheedition,butaswelltheiroriginalfacsimilewhichshouldbedisplayedsimultaneouslyRothhaupt(2006).Onlythiscom-binedviewprovidesthepossibilityforcomparisonandanalysisoftheoriginalmaterial,whichcarriesthecompletesetofinformation.Inordertoimplementthislayout,itwasnecessarytoOCRallfacsimileofWittgenstein’sNachlass,ex-tractthecoordinatesofhisremarksandlinkthemtothesearchresultaccordingtotheirsiglumGotschareketal.(2011).AlltheworkwasdonewithABBYYFineReaderandadditionallydevelopedPERLprograms.ThehighlightinginthedisplayofthefacsimileisdonewithCSStechniqueswithintheHTMLPageLindinger(2013).
234CHAPTER29.WORKFLOWS
Figure29.3:WASTDataWorkflow
28 CHAPTER 2. WITTFIND 29.4. BUG TRACKING WORKFLOW 233
Figure 29.2: Continuous Integration
PartIII
SIS
29
232CHAPTER29.WORKFLOWS
Figure29.1:gitbranchingmodel
Chapter 29
Workflows
29.1 git branching model workflow
In der Entwicklung der WAST-Landschaft arbeiten wir mit dem sehr bekanntenund verbreiteten git branching model von dieser Seite1 — Abbildung 29.1 aufSeite 232 fasst den git branching model workflow an dieser Stelle kurz zusam-men.
29.2 Continuous Integration Workflow
Abbildung 29.2 auf Seite 233 verdeutlicht den Workflow einer CI, für mehrInformationen siehe auch das Kapitel Continuous Integration.
29.3 WAST pipeline
Abbildung 29.3 auf Seite 234 gibt einen Überblick, wie die WAST-pipeline (inzunehmender Kombination mit dem Unified Deployment-Prozess) aussieht:
29.4 bug tracking workflow
Graphik Abbildung 29.4 auf Seite 235 fasst noch einmal als Überblick den BugTracking Workflow zusammen – für eine insgesamte Beschreibung siehe auchKapitel [Bug Tracker][].
1http://nvie.com/posts/a-successful-git-branching-model/
231
Chapter3
SIS:SymmetricIndexStructures
Inhalt3.1Einführung.........................323.2Zweck............................323.3Kurzvorstellung......................323.4VerwendungaufderKommandozeile.........323.5Überblick..........................36
3.5.1Projektstruktur.....................363.5.2Schichten........................373.5.3Klassen.........................37
3.6Ebenen...........................423.6.1C++-Ebene.......................423.6.2Web-Ebene.......................613.6.3NodeAddon.......................673.6.4NächsteSchritte....................67
SIS(undseinWeb-Teil)bestehtausmehrerenSchichtenunddemineinander-greifenverschiedenerTechnologienundFrameworks.
AlledieseTeilewerdenindennächstenKapitelnbesprochen:
•DieVerwendungaufderKommandozeileabSeite32•DieSchichtenderC-,C++-undWeb-EbeneabSeite37•SpezielleTechnikenderC++-ProgrammierungabSeite42
31
230CHAPTER28.ÜBERBLICKSTABELLEN
32 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
3.1 Einführung
SIS, die Symmetrischen Index Strukturen sind Endliche Automaten in Formvon SCDAWGs (Symmetric Compacted Directed Acyclic Word Graphs), welchees erlauben, Texte zu indexieren und während des Lookups Vorschläge undVervollständigungen sowohl klassisch nach-rechts als auch nach links zu geben.
Diese werden detailliert in (Daniel Bruder 2012) besproche, welches aufbaut auf(Gerdjikov et al. 2013), und dieses im Wesentlichen mit (Blumer et al. 1987)verknüpft.
Die Grundidee hinter SIS ist folgende: Man nehme zwei nicht-symmetrischeCDAWG-Automaten – in linearer Zeit und auf linearem Raum direkt, on-lineerstellt (Inenaga et al. 2001) –, und befülle einen mit einem Text in “normaler”,links-nach-rechts-Richtung (left to right, LTR), und den anderen in umgekehrterRichtung (RTL). Dann identifiziere man die identischen States dieser beidenAutomaten (Gerdjikov et al. 2013). Daraufhin annotiere man die Automatenmit den Hinweisen auf die Dokumente, für welche sie stehen ((Daniel Bruder2012))
3.2 Zweck
3.3 Kurzvorstellung
3.4 Verwendung auf der Kommandozeile
Die ausführbare Datei sis (im Verzeichnis build/bin/sis) erlaubt zwei ver-schiedene Modi: einmal zum Indexieren eines vorhandenen Korpus (sis index)und zum anderen zur Suche auf einem bestehenden Index (sis context).
Ein erster Versuch auf Kommandozeile ergibt folgendes Ergebnis:
> bin/sisThis is SIS. Please see `sis --help' for available commands and options
You can get additional help using `sis <COMMAND> --help'
Available COMMANDs are:contextindex
Und der Aufruf der Hilfe ergibt folgendes:
28.2. MITWIRKENDE 229
Komponente Teil Personen Von Bis
SIS alle 4 Schichten Daniel Bruder 01/2012 dato
3.4.VERWENDUNGAUFDERKOMMANDOZEILE33
>bin/sis--help
sis---
Usage:sis[GENERALOPTIONS]COMMAND[COMMANDOPTIONS]...
Allowedgeneraloptions:-h[--help]showhelpmessage-v[--version]showversion--commandsshowavailablecommands-i[--input]arginputfiles
SISfunktioniertalsoähnlichwiegitmitdemHauptbefehlsisunddenUnter-Kommandosindexundcontext.
ZujedemUnterkommandogibtesnunnocheineweitereHilfe,welchediespeziellenArgumenteerklärt–hierfürsisindex:
>bin/sisindex--helpOptionsforcommand'index':-o[--output]argoutputname-f[--thefile]argfilelistinginputfiles
Undhierfürsiscontext:
>bin/siscontext--helpOptionsforcommand'context':-w[--width]arg(=10)lr-contextwidth-q[--query]argquerystring-p[--print-filename]printthefilenames
BeideSub-Kommandoserwartenalso(lautdengeneraloptions)mindestenseinInputfilemit--inputbzw.-i:
bin/sisindex-iINPUTFILEbin/siscontext-iINPUTFILE
FürdasSub-KommandoindexwirdalsInputfileentweder
a)mit-ieineAuflistungvonDateienerwartet:
•bin/sisindex-ifile1-ifile2
228CHAPTER28.ÜBERBLICKSTABELLEN
Figure28.1:WASTKomponentenundDependencies
34 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
b) mit -f eine Datei, welche die Input-Dateien auflistet (falls die Input-Dateien mit -i zu viele werden):• bin/sis index -f file.list
Die Input-Dateien für sis index müssen folgendermaßen beschaffen sein:
a) entweder alle Dateien sind XML-Dateien (nach dem CISWAB-TEI-Standard)
b) alle Dateien sind plain-text-Dateien
(Um hier mehr Flexibilität anbieten zu können müssen noch mehr features füreinen Importer geschrieben werden, siehe https://gitlab.cip.ifi.lmu.de/bruder/sis3/issues/93; desweiteren werden bei plain-text Dateien die Dateinamen alsSiglum interpretiert).Solange die Importer noch nicht komplett vollendet sind, gibt es eine Zwischen-lösung, plain text Dateien herzustellen:Man kann die Testdaten aus src/features/data/Ts-213 und den Extractorunter src/features/data/Ts-213/extract.sh verwenden um plain-textDateien herzustellen.Der Extractor liefert die Dateien in das Verzeichnis work/ aus, man ist aberselbst dafür zuständig, dieses frei zu halten (also gegebenenfalls zu löschen vorder nächsten Extraktion).
> ./extract.shUsage:./extract.sh [7bit|utf8]
(results will be written to work/)(make sure you erase work/ before)
Der Extractor ist, wie gesagt, nur eine Zwischenlösung lässt sich aber verwenden.Der Befehl …
> ./extract.sh utf8
… wird plain text Dateien nach work/ extrahieren, welche sich für bin/sisindex -i file1 -i file2 verwenden lassen.Idealerweise legt man eine Datei allfiles.list o.ä. an …
> find ../src/features/data/Ts-213/work/utf8 \-type f \-iname '*.satz' \-exec echo `pwd`/{} \; \> Ts-213.allfiles.list
28.2. MITWIRKENDE 227
* [gpp](http://files.nothingisreal.com/software/gpp/gpp.html)* [ppp-typesetting-pipeline](https://github.com/typesetters/p5-App-pandoc-preprocess)
* [dot](http://www.graphviz.org/Documentation.php)/[neato](http://www.graphviz.org/pdf/neatoguide.pdf)* [rdfdot](RDF::Trine::Exporter::GraphViz)* [ditaa](http://ditaa.sourceforge.net/)
* [Image::Magick](http://www.imagemagick.org/) (image manipulation)* [rsvg-convert](http://live.gnome.org/LibRsvg)
* [yuml](https://github.com/wandernauta/yuml) (install as python module using `pip install https://github.com/wandernauta/yuml/zipball/master` or `easy_install https://github.com/wandernauta/yuml/zipball/master`)* [plantuml](http://plantuml.sourceforge.net/)
28.1.2 Links
[^wf]: <https://gitlab.cis.lmu.de/wast/wf>[^SIS-backend]: <https://gitlab.cis.lmu.de/wast/sis3/tree/master/src>[^SIS-frontend]: <https://gitlab.cis.lmu.de/wast/sis3/tree/master/web>[^wittfind-web]: <https://gitlab.cis.lmu.de/wast/wittfind-web>[^feedback]: <https://gitlab.cis.lmu.de/wast/wast-feedback>[^feedback-link]: <http://wastfeedback.cis.uni-muenchen.de/>[^e2e]: <https://gitlab.cis.lmu.de/wast/wittfind-web/tree/development/tests>[^reader]: <https://gitlab.cis.lmu.de/wast/wittfind-web/>[^cmake]: <http://www.cmake.org/>[^lest]: <https://github.com/martinmoene/lest>[^node]: <http://nodejs.org/>[^npm]: <http://nodejs.org/>[^expressjs]: <http://expressjs.com/>[^angularjs]: <https://angularjs.org/>[^bower]: <http://bower.io/>[^phantomjs]: <http://phantomjs.org/>[^casperjs]: <http://casperjs.org/>[^turn.js]: <http://www.turnjs.com/>[^doxygen]: <http://doxygen.org/>[^sis-link]: <http://sis.cis.lmu.de/>[^wf-link]: <http://wittfind.cis.lmu.de/>[^wittfind-link]: <http://wittfind.cis.lmu.de/>[^helppage]: <https://gitlab.cis.lmu.de/wast/wittfind-web>
28.1.3 Dependency Graph (experimental)
28.2 Mitwirkende
3.4.VERWENDUNGAUFDERKOMMANDOZEILE35
…umdieseineinemStückfütternzukönnen:
>bin/sisindex-fTs-213.allfiles.list-oallfiles.index
LetztererBefehlerstellteinenIndexfüralleDateien,dieinTs-213.allfiles.listgelistetsindundlegt–wegenderzweistufigenSerialisierung(siehedaszuge-hörigeKapitel)–,zweiSerialisierungsdateienan:allfiles.indexfürdenC++-TeildesAutomatenundallfiles.index.cfürdenC-TeildesAutomaten(esseiandieserStellekurzdaraufhingewiesen,dasssichallfiles.index.cauchmitderexecutablederC-Schicht,unterbin/cautverwendenlässt,ohnedenC++-Teilzubenötigen):
>ls-lhallfiles.index*-rw-r--r--1dbruderstaff6,1M11Mär13:26allfiles.index-rw-r--r--1dbruderstaff12M11Mär13:26allfiles.index.c
NachdemalsoderIndexangelegtist,lässtsichaufdiesemSuchen–hierbeifungiertdervorhergehendeOutput(-oallfiles.index)diesmalalsInputfürbin/siscontext:
>bin/siscontext-iallfiles.index-qerstAutomatonloadedsizeis5548results.size()=599'odererinnerstDuDicha''ErinnerstDuDichd''oranerinnerstDuDich?''everifizierstDudas??''daßmanerstahnungslo''ichdocherstaufbauen;'[...]
LautderHilfezusiscontext(bin/siscontext--help)lässtsichunteranderemdieBreitederausgeschnittenenErgebnisseeinstellen(-wWIDTH):
>bin/siscontext-iallfiles.index-qerst-w20Automatonloadedsizeis5548results.size()=599'sgesagt;odererinnerstDuDichandieStim''ErinnerstDuDichdaran,daß''“WoranerinnerstDuDich?—''WieverifizierstDudas?—dannwe''nichtso,daßmanerstahnungslosist,und'
226CHAPTER28.ÜBERBLICKSTABELLEN
*[^bower]*client-seitigedependencieswerdendurch[^bower]installiert
*[^npm]*server-seitigedependencieswerdendurch[^npm]installiert
*MongoDB
28.1.1.7E2E
Component:E2EDescription:End-to-endtestsfürwittfind-web:kompletteUser-SzenariendurchspielenMaintainer:bruder@cis.lmu.de,TBDLinkexternal:---Repository:gitlab.cis.lmu.de/wast/wittfind-web/tree/development/testsDependencies:
*[^node]/[^npm]*[^casperjs]
*[^phantomjs]
28.1.1.8Reader
Component:ReaderDescription:Reader-ApplikationfürFacsimileMaintainer:lindinger@cip.ifi.lmu.de(etal.?)Linkexternal:---Repository:gitlab.cis.lmu.de/wast/wittfind-web/tree/development/testsDependencies:
*PHP(Version?)*[^turn.js]*...(?)
28.1.1.9wast-doc
Component:wast-docDescription:DokumentationfürWASTMaintainer:bruder@cis.lmu.de/TBDLinkexternal:www.cip.ifi.lmu.de/~bruder/wast/Repository:https://gitlab.cis.lmu.de/wast/wast-docDependencies:
*[make](https://www.gnu.org/software/make/manual/make.html)*[pandoc](johnmacfarlane.net/pandoc/)
36 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
'rt müßte ich doch erst aufbauen; oder: von''gen: Ein Satz folgt erst aus ihm, wenn er da''ch mir vielmehr nun erst ausrechnen. '' an, die deren Sinn erst bestimmen; was nich'[...]
3.5 Überblick
Im Folgenden ein Überblick über die Projektstruktur von SIS, die Schichten,aus welchen SIS sich zusammensetzt, und die wichtigsten Klassen innerhalb vonSIS.
3.5.1 Projektstruktur
Hier ein Überblick und eine Beschreibung der wichtigsten Teile der Projektstruk-tur:
.|-- build # Out-of-source dir für cmake / Kompilierung| |-- bin # Platz für die gebildeten exeucatables| |-- lib # --- " --- libraries| `-- src # --- " --- *.o|-- cmake # cmake-module für Makefile-Generation|-- etc # Test-Daten und anderes|-- src # C++-Sources| |-- adapter # Alle Adapter-Klassen (wrappen vendor/cautomata)| | |-- VoidSequence| | `-- inenagaCDAWG| |-- features # Tests| | `-- data # Test-Daten| `-- indexer # Indexer-Klassen|-- vendor # 3rdparty libs (eingebunden als git submodules)| |-- cautomata # C-Schicht von Petar Mitankin, Sofia| |-- make_unique # wurde im C++11-Standard schlicht vergessen| |-- pugixml # XML-Modul| |-- serialization # ...| `-- testing`-- web # Web-Schicht: MEAN-Stack
|-- bower_components # Client-seitige Javascript-Bibliotheken|-- build # hier wird das node-addon gebildet|-- cpp # Hier liegen die Klassen, die src/ nach JS wrappen|-- node_modules # Server-Seitige Module|-- public # Client-Seite| |-- javascripts| `-- stylesheets|-- routes # Server-Seite: Routes`-- views # Client-Seite: Views
`-- partials
28.1. KOMPONENTEN, MAINTAINER, DEPENDENCIES 225
* git-submodules* lest
* boost* ... (?)
28.1.1.4 Alternativen-Suche
Component: "Alternativen-Suche"Description: Ausformulierung von AlternativenMaintainer: seebauerp@cip.ifi.lmu.de / lindinger@cip.ifi.lmu.de / TBDLink external: wittfind.cis.lmu.deRepository: gitlab.cis.lmu.de/wast/wittfind-webDependencies:
* perl-module (?)* XML-Twig (?)* ... (?)
* ... (?)
28.1.1.5 Helppage
Component: HelppageDescription: Beispiel-Anfragen und Hilfe für wittfindMaintainer: kreya@cip.ifi.lmu.deLink external: wittfind.cis.lmu.de/help.phpRepository: gitlab.cis.lmu.de/wast/wittfind-webDependencies:
* PHP (Version?)* ... (?)
* ... (?)
28.1.1.6 Feedback
Component: FeedbackDescription: Bug Reports für AussenstehendeMaintainer: bruder@cis.lmu.de, TBDLink external: wastfeedback.cis.lmu.deRepository: gitlab.cis.lmu.de/wast/wast-feedbackDependencies:
* curl* gitlab user token / "FeedbackBot"-User* MEAN-Stack
* [^node] / [^npm]* [^expressjs]* [^angularjs]
3.5.ÜBERBLICK37
3.5.2Schichten
•Schicht1:C1
–BereitstellungvonSCDAWG-AutomatenfüreinzelneWörter/Wörterbücher
•Schicht2:C++(11)2
–ErweiterungderSCDAWGsausderC-Schicht,umdiesefürdieSucheinnerhalbvonDokumenten(stattWörtern)verwendbarzumachen
•Schicht3:Web3mit:
–Serverseite
*Nodejs+ExpressJS*nodeaddonalsWrapperderC++-Automaten(ermöglichtdasEinbindenvonC++-ObjekteninJavascriptcode)4
–Client-Seite
*AngularJS5
3.5.3Klassen
ZunächsteinÜberblick:
ImFolgendeneineKurz-Besprechungder(wichtigsten)Klassen,ihresZwecksundihrergrundlegendenEigenschaftenausderC++-Schicht,welchediestructsausderC-SchichtwrappenunddokumentindexierendeEigenschaftenzurVerfügungstellen:
3.5.3.1*Adapter
Jedem*AdapterliegteinC-Structzugrunde,vergleichedasentsprechendeKapi-telzumgrundlegendenWrapping-Pattern
1zufindeninvendor/cautomata2zufindeninsrc/3zufindeninweb/4http://nodejs.org/api/addons.html5http://angularjs.org/
224CHAPTER28.ÜBERBLICKSTABELLEN
*wf*PHP*Apache*E2E-dependencies:
*[^node]/[^npm]*[^casperjs]
*[^phantomjs]
28.1.1.3SIS
SIS-frontend
Component:SIS(frontend)Description:Maintainer:bruder.cis.lmu.deLinkexternal:sis.cis.lmu.deRepository:gitlab.cis.lmu.de/wast/sis3/tree/master/webDependencies:
*MEAN-Stack*[^node]/[^npm]*[^expressjs]*[^angularjs]*[^bower]
*client-seitigedependencieswerdendurch[^bower]installiert
*[^npm]*server-seitigedependencieswerdendurch[^npm]installiert
*MongoDB
SIS-backend
Component:SIS(backend)Description:Maintainer:bruder@cis.lmu.deLinkexternal:sis.cis.lmu.deRepository:gitlab.cis.lmu.de/wast/sis3/tree/master/srcDependencies:
*`gcc>4.7`*cmake*(doxygen)*git
38 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
Figure 3.1: SIS Schichten
3.5.3.2 Document
Ein sis::Document stellt die grundsätzliche Basis dessen dar, was letztendlichvon einem DocumentIndexingAutomaton verarbeitet und indexiert wird.
Es hat zwei wesentliche members:
• filename_ und• contents_
wobei filename das Siglum darstellt und contents den tatsächlichen Inhalt.
In einem Stück wie diesem etwa…
<s n="Ms-115,3[2]_1" ana="facs:Ms-115,3 abnr:7 satznr:22">“Was heißt es: ‘dieser Gegenstand ist mir<lb/> wohlbekannt?’”
</s>
entspräche:
• filename == Ms-115,3[2]_1• und contents == “Was heißt es: ‘dieser Gegenstand ist mir
wohlbekannt?’”
Chapter 28
Überblickstabellen
28.1 Komponenten, Maintainer, Dependencies
28.1.1 Komponenten, Beschreibungen, Maintainer
28.1.1.1 wf
Component: wfDescription:Maintainer: flo@cis.lmu.deLink external: wittfind.cis.lmu.deRepository: gitlab.cis.lmu.de/wast/wfDependencies:
* `gcc > 4.7`* boost
* ... (?)* cmake* (doxygen)
28.1.1.2 wittfind-web
Component: wittfind-webDescription:Maintainer: maximilian@cis.lmu.de et al.Link external: wittfind.cis.lmu.deRepository: gitlab.cis.lmu.de/wast/wittfind-webDependencies:
* git* git-submodules
223
3.5.ÜBERBLICK39
Figure3.2:KlassenarchitekturvonSIS
222CHAPTER27.DANK
40 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
Hinweise
• Document ist hinsichtlich des string-Typs templatisiert: damit lässt sichbesser mit dem unterliegenden string-Typ der C-Schicht, VoidSequenceumgehen.
• Die C-Schicht verlangt unbedingt, dass zu einem gegebenen Zeitpunkteinmal das Makro mSetEndianness() aufgerufen wird. Anonstenpassieren können sehr böse Dinge während der Serialisierung geschehen(bytes können falsch herum eingelesen werden, da die Endianness nichtrichtig definiert ist) und damit nur sehr schwer nachvollziehbare Fehlerentstehen. Daher ruft der Konstruktor von Document dieses Makro auf.
• Die contents eines Document werden aus Platzgründen nicht serialisiert.Schlussendlich sind diese Inhalte in automaton()->data_ verfügbar(welches serialisiert wird) und über entsprechende VoidSequenceAdapter::iteratorsrekonstruierbar (in Zusammenarbeit mit DocumentIndex )
3.5.3.3 DocumentCollection
DocumentCollection ist im wesentlichen eine Liste von Documents.Ihm können auch XML-Dateien als Input gegeben werden und er erstelltdaraus “virtuelle” Dokumente (durch die Methode import()), als wären dieeinzelnen Documents in tatsächlichen Dateien vorgelegen (s.o. das Beispiel mitSiglum/Contents im Kapitel Document).Die Methode import() verwendet pugixml(Arseny Kapoulkine 2014a), ein ex-ternes Modul aus dem vendor-Teil des Projekts (als git submodule von (ArsenyKapoulkine 2014b)).
3.5.3.4 DocumentIndex
Ein DocumentIndex ist eine std::map die Documents und ihre Positionen ver-waltet:
typedef Document<StringType> key_type;typedef DocumentPos<StringType> value_type;typedef std::map<key_type, value_type> docinfo_t;/// @todo rename: value_type -> mapped_type (do this everywhere)
Document und ihre DocumentPos werden im index-ing-Schritt des DocumentIndexingAutomatonangelegt:
• zu jedem Document gehört ein sinkstate im Automaten, d.h. ein Final-State
Chapter 27
Dank
• Viele• viele
– sehr– sehr– viele
221
3.5.ÜBERBLICK41
Hinweise
•Esfindensichz.T.nochveralteteAPIsinnerhalbdieserKlasse,diefürdenVorgängervonDocumentPos,DocumentPositionsgedachtwaren.DiesewerdenStückfürStückentferntwerden,sindabermitdeprecatedgekennzeichnet.
3.5.3.5DocumentIndexingAutomaton
DerDocumentIndexingAutomaton(Abbildung3.3aufSeite41istdiekomplex-esteKlassehinsichtlichseinerMember.EristdiezentraleStelle,anderalleInformationenzusammenlaufen:
•HinzufügenvonDocumentszudenC-Automatenundentsprechendes•IndexingdieserDokumente,d.h.
–verwaltendersinkstates–undderDocuments
•RetrievalundSucheaufdenAutomaten,unddabei
–“Ausschneiden”vonpassendenErgebnissen–undAuslieferungderselbenandieClients
Figure3.3:DocumentIndexingAutomatonUML
220CHAPTER26.DISCLAIMER
42 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
3.5.3.6 DocumentIndexingAutomatonAbstract
Die Basis-Klasse für DocumentIndexingAutomaton (Abbildung 3.4 auf Seite 42)
Figure 3.4: DocumentIndexingAutomatonAbstract UML
3.5.3.7 DocumentInformation
3.5.3.8 DocumentPositions
3.5.3.9 FindResult
3.5.3.10 TEIReader
3.6 Ebenen
SIS setzt sich aus mehreren Ebenen bzw. Schichten zusammen, welche im fol-genden besprochen werden:
• C-Ebene• C++-Ebene• Web-Ebene
3.6.1 C++-Ebene
• TDD: Test Driven Development [link: http://www.agiledata.org/essays/tdd.html]bzw. [link: späteres tdd kapitel]
Chapter 26
Disclaimer
Diese Dokumentation ist ein Work-in-Porgress-Produkt und daher:
a) in manchen Teilen noch nicht fertigb) in anderen Teilen schon deprecated.
Da die Dokumentation auch in einer kollaborativen Team-Arbeit erstellt undgepflegt werden soll, bitte bei Fehlern diese unbedingt korrigieren undper gitlab als Änderungen anbieten, danke!
219
3.6.EBENEN43
–lest(MartinMoene2013)
•make_unique(C++1yStandardCommittee2014)•GitSubmodules(“Git-Submodules”2014):gitsubmodulesincmake
(DanielBruder2014)•anderevendor-submodulesaufzählen•TemplateMeta-Programmierung6
–[TMPvorstellen]
•Serialization(siehemehrzumThemaSerialisierungallgemeinimKapi-telSerialisierungundwieSerialisierunginSISgemachtwirdimKapitelZweistufigeSerialisierung)
–cereal(uscilab2014)–[zweiSerializationModulevorstellen]–[link:cereal]–[link:boostserialization]
3.6.1.1DetaillierterWalk-throughdurchspezielleTeile
Automatentheorie:SCDAWGS,BijektiveAbbildung
Automatenkonstruktion
Dokumenterweiterung
WrappingvonC-StruktureninC++-Klassen
WarumCStrukturenWrappen?
Beispiele(CodeWalkThrough)HiereinBeispielfüreinC-Header-File,daseinstructbeschreibt.
1#ifndef_HEADER_FILE_COMPRESSED_AUTOMATON_2#define_HEADER_FILE_COMPRESSED_AUTOMATON_3
4#definemCompressedAutomatonGetStatesStored(aut)((aut)->statesTransitions->seqStored)5
6#definemCompressedAutomatonGetTransitionsStored(aut)((aut)->transitionsStart->seqStored)7
8typedefstructtCompressedAutomaton{9UINTinitialState;
10UINTSequence*statesTransitions;
6link:späteresKapitel(infussnote)
44 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
11 UINTSequence * statesNumberOfTransitions;12 UINTSequence * statesEnd;13 UINTSequence * transitionsStart;14 UINTSequence * transitionsTo;15 VoidSequence * data;16 TarjanTable * tt;17 } CompressedAutomaton;18
19 extern CompressedAutomaton * CompressedAutomatonInit( UINT symbolSize );20 extern void CompressedAutomatonAddState( CompressedAutomaton * aut, UINT state );21 extern void CompressedAutomatonAddTransition( CompressedAutomaton * aut, UINT stateFrom, UINT start, UINT stateTo );22
23 // ...
Und hier die wrappende C++-Klasse mit “sauberen” Konstruktoren (CTORs)und (automatischen) Desktruktoren (DTORs)
1 /// @brief Adapter for CompressedAutomaton2 template<class StringType>3 struct CompressedAutomatonAdapter4 : virtual public CompressedAutomatonAbstract<StringType>5 {6
7 using CompressedAutomatonAbstract<StringType>::traits::string_type;8 using CompressedAutomatonAbstract<StringType>::traits::symbol_size;9
10 protected:11 using adaptee_handle =12 std::unique_ptr< CompressedAutomaton, decltype(&::CompressedAutomatonFree)>;13 adaptee_handle adaptee_;14
15 public:16 explicit CompressedAutomatonAdapter()17 : adaptee_ { ::CompressedAutomatonInit(symbol_size), &::CompressedAutomatonFree }{}18 virtual ~CompressedAutomatonAdapter() {}19
20
21 //——————————————————————————————————————————————————————————————————————————//22 // M A P P I N G I N T E R F A C E (AutomatonAbstract) //23 //——————————————————————————————————————————————————————————————————————————//24 public:25 virtual void shrink() override;26 virtual void write(FILE * fp) const override;27
28 // ....29
30 //——————————————————————————————————————————————————————————————————————————//31 // M A P P I N G I N T E R F A C E (CompressedAutomaton) //32 //——————————————————————————————————————————————————————————————————————————//33 public:34 virtual void add_state(UINT state) override;35 virtual void add_transition(UINT stateFrom, UINT start, UINT stateTo) override;
Template Meta Programmierung in C++-Automaten (Vergleicheauch das Kapitel Techniken/TMP)
Part X
Appendix
217
3.6.EBENEN45
WieimKapitel[Techniken/TMP]ausgeführt,erlaubtesTemplateMetaPro-grammierung,oderkurz:TMP,bestimmteEntscheidungenundBerechnungenzurCompile-Zeitauszuführen,bzw.dieseindieCompile-Zeitzuverlagern.
DaskanneinerseitserhöhteTyp-Sicherheitgewährleisten(beiwenigerCode-Aufwand),schlichtZeitersparen,oder,wieindiesemFall,dieKonstruktion,oderbesser:die“Zusammenstellung”vonKlassenübernehmen.
Konkretverstandenwerdensollunter“Zusammenstellung”indiesemFall,dassdurchdieTechnikderTMPeinekohärenteKlassegeschriebenwird,diesichjenachInstantiationunterschiedlich“verhält”.
GanzgezieltwirddieseTechnikinFormderAutomaten–kurzgesagt–,auffolgendeWeisegenutzt:
DasC-structwird,wieimvorhergehendenBeispielmiteinersymbolSizekon-struiert.DieUINTsymbolSizewirdanderswodefiniertundkann(bzw:soll)zweiunterschiedlicheunsignedint-Werteannehmen:
•1,um7-bitStringszuverarbeiten•4,umUTF-8zuverarbeiten
VergleichefolgendeCode-TeileausderC-Schicht:
1//typical.h2typedefunsignedcharU8;3typedefunsignedshortintU16;4typedefunsignedintU32;5typedefunsignedlonglongU64;6
7typedefcharS8;8typedefshortintS16;9typedefintS32;
10typedeflonglongS64;11
12typedefU32UINT;13typedefS32SINT;
undfolgendenTeilausvoidsequence.h:
1//voidSequence.h2#defineENCODING_PLAIN(0)3#defineENCODING_UTF8(1)
und–nichtzuletzt–,folgendenTeilauscompressedAutomaton.c:
1//compressedAutomaton.c2CompressedAutomaton*CompressedAutomatonInit(UINTsymbolSize){3CompressedAutomaton*aut;4
5aut=Malloc(1,sizeof(CompressedAutomaton));6aut->initialState=NO;
216CHAPTER25.ÜBUNGEN
46 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
7 aut->statesTransitions = UINTSequenceInit2( 1024, 1024 );8 aut->statesNumberOfTransitions = UINTSequenceInit2( 1024, 1024 );9 aut->statesEnd = UINTSequenceInit2( 1024, 1024 );
10 aut->transitionsStart = UINTSequenceInit2( 1024, 1024 );11 aut->transitionsTo = UINTSequenceInit2( 1024, 1024 );12 aut->data = VoidSequenceInit2( symbolSize, 1024, 1024 );13 aut->tt = NULL;14 return aut;15 }
Das Problem mit diesem Code nun gestaltet sich folgendermaßen:
a) Zum einen muss der Anwender der Klasse wissen, was mit UINT symbolSizegemeint sein soll
b) Der Anwender der Klasse muss wissen, welche Werte UINT symbolSizeannehmen darf. Es ist nicht definiert, was passiert, sollte ein Anwenderden Wert 3 hineingeben
Anders ausgedrückt verstößt dieser Code gegen mehrere Richtlinien für“sauberen” Code:
a) Scott Meyers (Effective C++): Machen Sie es dem Anwender so einfachwie möglich, Ihre Klasse richtig zu verwenden und so schwer wie möglich,sie falsch zu verwenden (Meyers 2005)
b) Stroustrup (“Day 1 Keynote - Bjarne Stroustrup: C++11 Style” 2012):“Strong typing”. Als Apollo 11 (oder 13?), ein millionen- (oder milliarden-?) schweres Projekt hart abgestürzt. Warum? Weil eine Methode einenWert float übernehmen sollte, die die Verzögerungsgeschwindigkeitanzeigen sollte. Dabei war nicht klar, ob in km/h oder in meile/hangegeben sollte. Mit strong typing und Verwendung von Klassen, dieSI-Einheiten darstellen, wäre so etwas nicht passiert, da ein Objekt km/hnicht in eine Methode hineingegeben werden kann, das meile/h verlangt.Vergleiche hierzu unbedingt das Kapitel über SI-Einheiten in Stroustrups“the C++-Language” für C++11
Zurück zu unserem Code:
Um es so einfach wie möglich zu machen die Wrapper-Klassen richtig zu be-nutzen, und so schwer wie möglich, diese falsch zu benutzen (und dabei auchnoch Platz und Größe zu sparen), benutzen die Wrapper-Klassen Template-Meta-Programmierung, die folgendes erreicht:
a) Eine class CompressedAutomatonAdaptermit der Definition template<class StringType> struct CompressedAutomatonAdapterist templatisiert, wobei ein Template-Parameter erwartet wird, der:
i) entweder ein std::string istii) ein std::wstring ist
25.9. ÜBUNG 9: WEB-PROGRAMMIERUNG MIT DEM MEAN-STACK215
25.9 Übung 9: Web-Programmierung mit demMEAN-Stack
Schreiben Sie eine Komponente für LaaS, die “linguistics as a service”-Webapplikation.
Gehen Sie dazu wie folgt vor:
• clonen sie den code von https://gitlab.cip.ifi.lmu.de/bruder/claas• schauen Sie sich die Routen server.js und in lib/controllers/api.js
an, und versuchen Sie zu verstehen, was hier passiert – letztendlich werdennur Daten vom Frontend (also von der Client-Seite entgegengenommenund ein Shell-Befehl ausgeführt und die dadurch gewonnen Daten an dieClient-Seite zurückgegeben)
• schauen Sie sich einen Controller der Client-Seite an und versuchen Siezu verstehen, wie dieser die Daten an die Server-Seite gibt und die Ergeb-nisse von der Server-Seite entgegennimmt. Betrachten Sie beispielsweiseapp/scripts/controllers/tokenize.coffee
• schauen Sie sich eine View auf der Client-Seite an und versuchen Sie zuverstehen, wie die Daten entgegengenommen und die Ergebnisse von derServer-Seite präsentiert werden, z.B: app/views/partials/tokenize.jade
• Nun schreiben Sie ein kleines Modul selbst! Suchen Sie sich dabei frei aus,wwas sie umsetzen möchten, hier ein paar Ideen: uppercase, lowercase,camelCase, CamelCase to snake_case, strip, Spracherkennung,reverse, wordcount, …
3.6.EBENEN47
iii)odereine(egalwelche)vonstd::stringabgeleiteteKlassedarstellt
b)DabeierreichtdietemplateclassCompressedAutomatonAdapter,dass:
i)dieunterliegende,adaptierteKlasseCompressedAutomatonmitgenaudemrichtigenWertfürUINTsymbolSizeaufgerufenwird
ii)keine“falsche”Instantiierungvorgenommenwerdenkann(strongtyp-ing)
iii)mandieKlassenichtfalschverwendenkann(durchstatic_assert),bzw.schonzurCompile-ZeitübereinefalscheVerwendung(mitentsprechenderFehlermeldung)aufgeklärtwird–undderCodegarnichterstkompiliert(stattspäterohneWarnungin“undefinedbe-havior”hineinzurennen)
KonkretwirddieserreichtundumgesetztdurchfolgendenCode:
ZunächstnocheinmaldieKonstruktionderadaptiertenKlasse:
1///@briefAdapterforCompressedAutomaton2template<classStringType>3structCompressedAutomatonAdapter4:virtualpublicCompressedAutomatonAbstract<StringType>5{6
7usingCompressedAutomatonAbstract<StringType>::traits::string_type;8usingCompressedAutomatonAbstract<StringType>::traits::symbol_size;9
10protected:11usingadaptee_handle=12std::unique_ptr<CompressedAutomaton,decltype(&::CompressedAutomatonFree)>;13adaptee_handleadaptee_;14
15public:16explicitCompressedAutomatonAdapter()17:adaptee_{::CompressedAutomatonInit(symbol_size),&::CompressedAutomatonFree}{}18virtual~CompressedAutomatonAdapter(){}
Bemerkungen:
•StringTypeinZeile2istlediglichdeskriptiv,abernichtpräskritiptiv:sieistlediglichdazugeeignet,demLeserzusagen,washiererwartetwird,prüftdiesabernicht(oderkanndiesohneConcepts,dieerstinC++14kommenwerden,garnicht)
•konstruiertwirdderadaptee_miteinersymbol_size,dievonCompressedAutomatonAbstract<StringType>::traits::symbol_sizegeliefertwird
•CompressedAutomatonAbstract<StringType>wiederumisteingemein-samesInterface,dasalleAutomatenteilenwerden
HiermitalsozurBetrachtungdesInterfacesCompressedAutomatonAbstract<StringType>
214CHAPTER25.ÜBUNGEN
48 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
1 /// @brief interface for CompressedAutomaton2 template<class StringType>3 struct CompressedAutomatonAbstract4 : virtual public AutomatonAbstract<StringType>5 {6
7 using AutomatonAbstract<StringType>::traits::string_type;8 using AutomatonAbstract<StringType>::traits::symbol_size;9
10 virtual UINT get_symbol_size() const = 0;11 virtual CompressedAutomaton * read( FILE * fp ) = 0;
Dinge, die man hier erkennen kann:
• Das Interface für CompressedAutomaton beruft sich auf ein noch grundle-genderes Interface: AutomatonAbstract<StringType> und “erbt” dessenclass traits
• Das Interface für CompressedAutomaton deklariert pure virtuals für alleerbenden Klassen und zeichnet sich damit durch folgendes aus:
– sie ist eine abstrakte, nicht instantieerbare Klasse– verlangt von allen erbenden Klassen, diese Methoden zu implemen-
tieren, andernfalls, bleiben diese ebenfalls abstrakt– definiert dadurch ein gemeinsames Interfaces aller erbenden (nicht-
abstrakten) Klassen, auf das man sich berufen kann.
Nun ist aber nocht nicht die Herkunft der traits geklärt.
Traits erlauben es, “kostenlos”, d.h. ohne Speicher zu belegen, Informationenin Klassen zu halten, die während der Compile-Zeit genutzt werden können.
1 namespace sis {2
3 template <class StringType>4 struct string_traits {5 public:6 typedef typename ElementSize<StringType>::type string_type;7 static constexpr unsigned symbol_size = ElementSize<string_type>::value;8 };9
10 /// @brief Defines an Automaton in general11 /// @todo rename: AutomatonAbstract -> AdaptedAutomaton (?)12 template<class StringType>13 struct AutomatonAbstract : boost::noncopyable, string_traits<StringType> {14
15 using string_type = typename string_traits<StringType>::string_type;16 static constexpr unsigned symbol_size = string_traits<StringType>::symbol_size;17
18 //——————————————————————————————————————————————————————————————————————————//19 // C T O R / D T O R //20 //——————————————————————————————————————————————————————————————————————————//21 public:22 AutomatonAbstract() { mSetEndianness() } // this is important.
25.8. ÜBUNG 8: TYPE TRAITS 213
25.8 Übung 8: Type Traits
Schreiben Sie ein type-trait, das für eine Klasse template<class T> Foo zurCompile-Zeit (!)
• feststellt, ob die Klasse mit einem std::string, std::wstring oder eineraus diesen abgeleiteten Klassen besteht
• feststellt, ob es sich um einfache oder wide-strings handelt und• eine bool-variable anbietet, die wiederum von anderen Klassen abgefragt
werden kann: bool is_wide_string
Also:
namespace trait {template<class T> mytrait {static constexpr bool is_wide_string = /*...*/;
}}
temlpate<class StringType>class MyClass {using is_wide_string = mytrait<StringType>::is_wide_string;
};
auto main() -> int { // C++11 only!MyClass<std:: string> stringclass;MyClass<std::wstring> wstringclass;
std::cout << std::boolalpha<< stringclass::is_wide_string // false<< std::endl<< wstringclass::is_wide_string // true<< std::endl;
return 0;}
3.6.EBENEN49
23virtual~AutomatonAbstract(){}24
25
26//——————————————————————————————————————————————————————————————————————————//27//MAPPINGINTERFACE//28//——————————————————————————————————————————————————————————————————————————//29public:30virtualvoidshrink()=0;31virtualvoidwrite(FILE*fp)const=0;32
33//...
1namespacesis{2
3///@briefmeta-classtohandleStringTypetypetraits(usingstaticassertions)4template<classT>5structElementSize{6staticconstexprboolT_is_string_type=7std::is_base_of<std::string,T>::value8||std::is_base_of<std::wstring,T>::value;9
10static_assert(T_is_string_type,11"\n\n\tYoumustinstantiatethisclassinquestionwithstd::string,"12"\n\tstd::wstring,oranyclassderivedthereof.\n"13);14
15
16typedefTtype;17typedefTstring_type;18typedeftypenameT::value_typevalue_type;19
20typedeftypenamestd::conditional<21std::is_same<std::string,T>::value,//ifStringTypeisstd::string22std::fstream,//thenstream_typeisstd::fstream23std::wfstream//elseitisstd::wfstream24>::typestream_type;25
26staticconstexprunsignedintvalue=27sizeof(typenamestring_type::value_type);28};29
30}/*sis*/
BesprechungdesCodesDieZiele,diedieser(C++11-)Codeerreicht,sindmehrere:
1)Eswirdgeprüft,obderTemplate-Paramtertemplate<classT>
a)einstd::string,b)einstd::wstringc)odereinevoneinerderbeidenKlassenabgeleiteteKlasseist
(std::is_base_of)
212CHAPTER25.ÜBUNGEN
50 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
2) Diese Überprüfung findet zur Compile-Zeit (!) statt (constexpr) und dasErgebnis wird in einem bool ::value abgespeichert
3) Es werden sog. traits definiert, die wiederum an anderer Stelle abfragbarsind:
a) ElementSize<mystring>::type würde den Typ mystring zurück-geben
b) ElementSize<mystring>::string_type würde das selbe Ergebnisliefern
c) ElementSize<mystring>::value_type würde den value_type derKlasse zurückgeben mit der ElementSize instantiiert ist; im Fallevon std::string also char
4) Der wichtigste traits jedoch ist static constexpr unsigned int value:an dieser Stelle wird, je nach Instantiierung ein numerischer Wert von 1oder 4 zurückgegeben, nämlich die exakte Größe des value_types derKlasse template<class T>:
Bespiel:
a) für ElementSize<std::string>::value der Wert 1, da der value_typevon std::string ein char ist, und char (zwar plattform-abhängig) aberin den meisten Fällen die “Breite” 1 hat (also ein 1 Byte “breit” ist)
b) für ElementSize<std::wstring>::value der Wert 4, da der value_typevon std::wstring ein wchar_t ist, und wchar_t (zwar plattform-abhängig) aber in den meisten Fällen die “Breite” von 4 hat (also 4 Byte“breit” ist)
Passenderweise sind dies genau die Werte, die unser adaptierter AutomatotCompressedAutomaton in seinem Konstruktor erwartet! Allerdings kann dieAdapter-Klasse CompressedAutomatonAdapter nun nicht mehr “falsch” verwen-det werden!
Nicht zuletzt ist noch das trait stream_type interessant:
Je nachdem, ob die Automaten mit std::string oder std::wstring instanti-iert wurden, werden Ausgaben auf std::cout oder std::wcout gelenkt werdenmüssen. Um auch dieses “wegzuabstarhieren” wird – wiederum zur Compile-Zeit–, entschieden, was der passende Typ von Streams sein wird.
Hierfür bietet sich std::conditional aus dem Header <type_traits>an, das stream_type für eine Instantiierung mit std::string auf denstream_type-Typ auf std::fstream festlegt und mutatis mutandis das selbefür std::wstring erledigt.
Wenn nun eine Automaten-Klasse also Ausgaben vornehmen wird, so kann siedies abstrakt erledigen, indem Sie – in etwa – folgendes tut:
25.7. ÜBUNG 7: TEMPLATE META PROGRAMMIERUNG 211
25.7 Übung 7: Template Meta Programmierung
In dieser Übung werden Sie in die Template Meta Programmierung eingeführt.Dabei erlernen Sie, wie man Entscheidungen und – möglicherweise – sogarBerechnungen in die Compile-Zeit überführen kann.
In letzterem Falle bedeutet dies tatsächlich, dass zur Laufzeit bereits alle Berech-nungen erfolgreich erledigt wurden und keine Zeit mehr benötigen!
Schreiben Sie eine templatisierte C++-Klasse template<class T> class MyClass,die:
• einen default CTOR + DTOR hat
– (Verwenden Sie hierzu bestfalls den C++11-Weg)
• eine Methode zum hinzufügen von Elementen hat• eine Method zum Ausgeben der Anzahl von Elementen hat• eine Kollektion als Member-Variable speichern kann, und zwar wie folgt:
– Wenn die Klasse mit einem std::string oder einem std::wstringinstanziiert wurde, dann sollen diese in einem std::vector<> abge-speichert werden
– wenn die Klasse mit einem numerischenWert, also int, unsigned int,unsigned long long int, short, float, double, … instanziiertwurde, sollen diese in einem std::set<> gespeichert werden
– wenn die Klasse mit irgendeiner anderen Art instanziiert wird,soll dieses zur Compile-Zeit mit einem static_assert und einerentsprechenden Fehlermeldung abgelehnt werden.
• Wie immer haben Sie für alles selbstverständlich so gut es geht Tests zurVerfügung (die sich über einen (1!) Shell-Befehl bequem starten lassen,z.B. make && make test) – zugegeben, manche Dinge lassen sich hier nurschlecht (bis kaum testen)
3.6.EBENEN51
#include"ElementSize.hpp"
template<classT>classFoo{
usingstream_type=ElementSize<T>::stream_type;
stream_type&operator<<(constT&);}
SindhiermitalleAnforderungenerfüllt?
•Esistschwerergeworden,dieKlasse“falsch”zubenutzen,undleichtergeworden,sie“richtig”zubenutzen
•“StrongTyping”verhindertfalschgesetzteParameter,dabeieinemein-fachenUINToderunsignedintnichtklarist,welchekonkretenWerteandieserStelleerwartetwerden.
•DarüberhinaussinddieKlassen,dieaufdieseclassElementSizeauf-bauen,wesentlichflexibler,dasiegleichzeitigunabhänigighinsichtlichdesstream_typesoperierenkönnen.
LetztendlichalsobietetsichfolgendesSzenario:DerNutzerverwendeteineKlasseCompressedAutomatonAdapter<std::string>undbekommt–zurCompile-Zeit–diefürihn“passende”(d.h.kleinstmögliche,platzsparendste,sicherste)Klasse“zusammengebaut”undhatdabeiauchnochSicherheitfürdieVerwendunggewonnen.SollteerdieKlasse“falsch”(d.h.miteinem“nicht-string”)instantiierenwollen,würdeihmdiesbeimkompilierendurchdasstatic_assertinklusiveeinerFehlermeldungmitgeteiltwerden.ZumErlernenvonTechnikenzurTemplateMetaProgrammierung,verwendenSiebittedieÜbungen,dieimKapitel??TMPaufSeite??angegebenwerden.
TemplateMetaProgrammierung:MemberDispatchEineweitereTechnik,dieinnerhalbderSIScodebasezufindenist,isteinMemberDispatch-ingPattern.ObwohlmandasselbeZielauchüberTemplate-Spezialisierungerreichenkönnte,istesdennochratsam,diesesPatternzukennenumesimFalledesFallesauchtatsächlichzuerkennen.WiemitallenPatterns,sehendieseamAnfangkomplettunverständlichaus,kenntmansieaber,sosiehtmansofort,wasgeschieht,ohnelangenachdenkenzumüssen.Das“MemberDispatch”-Patternfunktioniertso:Angenommen,ichhabeeineTemplate-KlasseFoomiteinerMethodebar().NunmöchteichkomplettunterschiedlicheMethodenbar()ausführen,jenach-demwomitdieKlasseFooinstanziiertist–alsoz.B.alsFoo<std::string>undFoo<int>.Dermember-dispatchfunktioniertdannso:
210CHAPTER25.ÜBUNGEN
52 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
1 #include <type_traits>2 #include <cassert>3
4 // C++11 Proof of concept of different implementations of5 // member methods for different types of class instances.6
7 template<class T> struct tag {};8
9 template<class T>10 struct Foo {11
12 // obviously, you can play with where you actually put these attributes13 // (at least with gcc)14 [[ dispatched_to ]]15 std::string bar(tag<std::string>) {16 return std::string{"foo"};17 }18
19 int bar(tag<int>) [[ dispatched_to ]] {20 return 5;21 }22
23 auto bar() [[ dispatcher ]]24 ->decltype(this->bar(tag<T>{})) // 'this' seems to be needed here.25 {26 return bar(tag<T>{});27 }28 };
Zur Funktionsweise des member-dispatch Es gibt eine zentrale Meth-ode auto bar() [[ dispatcher ]], welche dann einfach weiterreicht andie eigentlichen Methoden, int bar(tag<int>) [[ dispatched_to ]] oder[[ dispatched_to ]] std::string bar(tag<std::string>).
Das struct tag dient dabei lediglich einer “Markierung” und wird vom Opti-mizer im Laufe der Kompilierung entfernt.
Test Driven Development: TDD Fast die gesamte Funktionalität der SIS-Komponente wurde mit dem Verfahren des TDD, Test Driven Developmentsentwickelt.
Mehr zum Thema TDD findet sich im Kapitel TDD – Test Driven Developmentab Seite ??.Kurz zur Struktur der Tests innerhalb von SIS:
• Die tests verwenden die Bibliothek lest(Martin Moene 2013) für die tests.• Alle tests finden sich im Verzeichnis src/features• Jeder Klasse innerhalb von src/ sollte ein Test entsprechen:
– Eine Klasse Document, z.B. in Document.hpp, sollte eine Fixture undein Feature besitzen:
25.6. ÜBUNG 6: NODE-WRAPPING 209
25.6 Übung 6: Node-Wrapping
[Spezifikation]
Verwenden Sie Ihre C++-Klasse mit den Tests aus der vorangegangenen Woche
Nun schreiben Sie ein Node-Addon, das folgendes kann:
• ich kann var addon = require('myWrappedCppClass') (oder ähnlich)aufrufen
• ich kann auf Javascript-Seite addon.add(element); aufrufen und das El-ement wird in der Member-Variable der C++-Klasse abgespeichert
• ich kann mit console.log(addon.size()); die Anzahl von Elementenin der Member-Variable der C++-Klasse abfragen
• ich kann auf Javascript-Seite mit addon.elements() alle Elemente ausder C++-Klasse in ein Javascript-Array holen.
• schreiben Sie eine for-loop in Javascript, das alle Elemente auf der Shellausgibt
Hinweise:
• Verwenden Sie zur Lösung dieser Aufgabe
– die Rezepte von hier6
– schauen Sie dieses Sympathische Youtube-Video7
• Es steht Ihnen frei, “statt” Javascript Coffeescript zu verwenden.• Bonuspunkt, wenn Sie erfolgreich utf8-Strings adden und ordentlich auf
der Shell ausgeben
6Node API (2014)7Marco Rogers (2013)
3.6.EBENEN53
–src/features/DocumentFixture.hppundsrc/features/DocumentFeature.hpp
ZurtieferenBeschreibungvonFixturesundFeatures,siehenochmaldasKapitelTDD–TestDrivenDevelopmentabSeite??;andieserStellenursoviel:
•FixturesbeschreibensowohldieInput-DatenalsauchdieerwartetenOutput-Daten
•FeaturessindspezielleTest-Klassen/Dateien,welchedieSpezifikationderKlassebeschreiben,aufdiesiesichbeziehenunddieFixturesverwendenumdieFunktionalitätdergetestetenKlassemitdenerwartetenErgebnis-senabzugleichen
BeispielInSISfindetsicheineKlasseDocument,mitdenfolgendenFix-tures/FeaturesumdieSpezifikationzuprüfen:
#ifndefDOCUMENTFIXTURE_HPP_8JMP5XLF#defineDOCUMENTFIXTURE_HPP_8JMP5XLF
#include"sis_config.hpp"
#include<vector>#include<string>
typedefstd::stringfile_t;///@todochangethistofs::path
structDocumentFixture{
std::vector<file_t>filenames={sis_TEST_DATA_DIR"ascii/1.txt",sis_TEST_DATA_DIR"ascii/2.txt",sis_TEST_DATA_DIR"ascii/3.txt",
};
std::vector<file_t>wfilenames={sis_TEST_DATA_DIR"utf8/1.txt",sis_TEST_DATA_DIR"utf8/2.txt",sis_TEST_DATA_DIR"utf8/3.txt",
};
std::vector<std::string>contents={"DasVerstehen,dieMeinung,faelltausunsrerBetrachtungheraus.","Also:KannmanEtwasanders,alsalsSatzverstehen?","Oderaber:IstesnichtersteinSatz,wennmanesversteht."
};
std::vector<std::wstring>wcontents={L"DasVerstehen,dieMeinung,fälltausunsrerBetrachtungheraus.",L"Also:KannmanEtwasanders,alsalsSatzverstehen?Ääääh...",L"Oderaber:IstesnichterßteinSatz,wennmanesversteht."
};};
#endif/*endofincludeguard:DOCUMENTFIXTURE_HPP_8JMP5XLF*/
208CHAPTER25.ÜBUNGEN
54 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
#include "sis_config.hpp"
#include "testing/lest.hpp"#include "DocumentFixture.hpp"
#include "indexer/Document.hpp"
#include <fstream>#include <locale>#include <cereal/types/vector.hpp>#include <cereal/types/string.hpp>#include <cereal/access.hpp> // For LoadAndAllocate#include <cereal/types/memory.hpp>#include <cereal/archives/binary.hpp>#include <cereal/archives/json.hpp>#include <cereal/archives/xml.hpp>
#include <cwchar>
DocumentFixture f;
const lest::test specification[] ={
"standard CTOR callable",[]{
sis::Document<std::string> d;EXPECT( d.filename() == "" );
},
"CTOR with filename", []{
sis::Document<std::string> d{ f.filenames.front() };EXPECT( d.filename() == f.filenames.front() );
},
"can serialize (automaton with added document)", []{
sis::Document<std::string> d{ f.filenames.front() };std::ofstream ofs{ "document.bin" };cereal::BinaryOutputArchive oarchive{ ofs };
oarchive( d ); // Write the data to the archive},
"can deserialize (automaton with added document)", []{
sis::Document<std::string> d{ f.filenames.front() };std::ifstream ifs{ "document.bin" };cereal::BinaryInputArchive iarchive{ ifs };
iarchive( d ); // Read the dataEXPECT( d.filename() == f.filenames.front() );EXPECT( d.contents() == f.contents. front() );
},
"can serialize (automaton without added document)", []{
25.5. ÜBUNG 5: SERIALISIERUNG 207
25.5 Übung 5: Serialisierung
Verwenden Sie ihre C++-Klasse aus der vorangegangenen Woche und schreibenSie eine Binär-Serialisierung für diese.
Zum Serialisieren können sie folgendes verwenden:
• generic_serialize3
• cereal4• boost serialization5
Erweitern Sie Ihre C++-Klasse aus der letzten Woche um folgende Methoden:
• save(const std::string & filename)• load(const std::string & filename)
…wobei die beiden Methoden (möglicherweise als static-Methoden!) die Klassejeweils auf Festplatte speichern und wieder laden.
Wie immer: schreiben Sie Tests, die Ihre Ergebnisse verifizieren und mit einemBefehl ausführbar sind. Dokumentieren Sie Ihre Vorgehensweise.
• Bonuspunkte, wenn Sie const boost::filesystem::path & path stattconst std::string & filename verwenden
• Bonuspunkte, wenn Sie neben dem Binärformat noch andere Formate un-terstützen (XML, JSON, …)
3Daniel Bruder, Florian Fink (2014)4uscilab (2014)5boost.org (2014b)
3.6.EBENEN55
sis::Document<std::string>d;std::ofstreamofs{"document.bin"};cereal::BinaryOutputArchiveoarchive{ofs};
oarchive(d);//Writethedatatothearchive},
"candeserialize(automatonwithoutaddeddocument)",[]{
sis::Document<std::string>d;std::ifstreamifs{"document.bin"};cereal::BinaryInputArchiveiarchive{ifs};
iarchive(d);//ReadthedataEXPECT(d.filename()=="");EXPECT(d.contents()=="");
},
"canaccesscontent",[]{
sis::Document<std::string>d{f.filenames.front()};EXPECT(d.contents()==f.contents.front());
},
"canaccesswidecontent",[]{
sis::Document<std::wstring>d{f.wfilenames.front()};
///Makesuretoproperlyimbue!EXPECT(d.contents()==f.wcontents.front());
},
"canaccesscontent(fordefaultCTOR)",[]{
sis::Document<std::string>d;EXPECT(d.contents()=="");
},
"canaccessfilename(fordefaultCTOR)",[]{
sis::Document<std::string>d;EXPECT(d.filename()=="");
},
"canaccessfilename(withgivenfilename)",[]{
sis::Document<std::string>d{f.filenames.front()};EXPECT(d.filename()==f.filenames.front());
},
"canserialize(automatonwithaddeddocument)[asstd::wstring]",[]{
sis::Document<std::wstring>d{f.wfilenames.front()};std::ofstreamofs{"document.json.w"};cereal::JSONOutputArchiveoarchive{ofs};
oarchive(d);//Writethedatatothearchive
206CHAPTER25.ÜBUNGEN
56 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
},
"can deserialize (automaton with added document) [as std::wstring]", []{
sis::Document<std::wstring> d{ f.wfilenames.front() };std::ifstream ifs{ "document.json.w" };cereal::JSONInputArchive iarchive{ ifs };
iarchive( d ); // Read the data
std::wstring expected = L"Das Verstehen, die Meinung, fällt aus unsrer Betrachtung heraus.";
/// Make sure to properly imbue!std::wcout << L"[" << d.contents() << L"]" << std::endl;std::wcout << L"[" << expected << L"]" << std::endl;
EXPECT( d.filename() == f.wfilenames.front() );EXPECT( d.contents() == expected );
},
"can serialize (automaton with added document) [as std::wstring]", []{
sis::Document<std::wstring> d{ f.wfilenames.front() };std::ofstream ofs{ "document.bin" };cereal::BinaryOutputArchive oarchive{ ofs };
oarchive( d ); // Write the data to the archive},
"can deserialize (automaton with added document) [as std::wstring]", []{
sis::Document<std::wstring> d{ f.wfilenames.front() };std::ifstream ifs{ "document.bin" };cereal::BinaryInputArchive iarchive{ ifs };
iarchive( d ); // Read the data
std::wstring expected = {L"Das Verstehen, die Meinung, fällt aus unsrer Betrachtung heraus."};
/// Make sure to properly imbue!// std::wcout << L"[" << d.contents() << L"]" << std::endl;// std::wcout << L"[" << expected << L"]" << std::endl;
EXPECT( d.filename() == f.wfilenames.front() );EXPECT( d.contents() == expected );
},
};
int main() {std::setlocale(LC_ALL, "");return lest::run( specification );
}
Zweistufige Serialisierung Das Thema Serialisierung wird allgemeinbeschrieben im Kapitel Serialisierung.
25.4. ÜBUNG 4: TDD – TEST DRIVEN DEVELOPMENT 205
25.4 Übung 4: TDD – Test Driven Development
Verwenden Sie Ihre C++-Klasse und den cmake build-Prozess aus der letztenWoche und schreiben Sie Unit-Tests. Auch wenn TDD eigentlich anders herumfunktioniert (Failing Test first – implementation to make the test pass later),sollten Sie dennoch ein gutes Gefühl für Unit-Testing und TDD bekommen.Nicht zuletzt ist es zum Einstieg dann doch leichter für eine bereits existierenden(hoffentlich auch funktionierende!) Klasse, Tests zu schreiben.
Die Tests sollen folgendes erfüllen:
1) die gesamte API wird abgedeckt
2) alle erdenklichen Edge-Cases, die Ihnen einfallen werden geprüft
3) alle Tests bestehen
4) alle Tests können durch einen einfachen Shell-Befehl gestartet werden
5) (dokumentieren Sie bitte, wie die Tests zu starten sind)
6) Sie dürfen als Test-Library verwenden was Sie wollen, zwei bestimmtejedoch kann ich Ihnen besonders empfehlen:
• lest1 – diese dürfen Sie auch gerne als git submodule hinzufügen,wenn Sie das möchten, ich möchte diese nicht gesondert herunter-laden müssen, damit Schritt 5 funktioniert
• Boost-Test2 – diese dürfen Sie als installiert ansehen
• Machen Sie sich schon einmal mit der zu lesenden Literatur für nächsteWoche und, wenn möglich, bereits mit der Theorie für nächste Wochegrundlegend vertraut
• Bonus:
– Schreiben Sie ein Makefile oder ein Rakefile, das per default-Task die tests frisch kompiliert und laufen lässt [finden sie den linkzu guten Beschreibungen von Rakefiles im entsprechenden Kapiteldes Skripts]
1Martin Moene (2013)2boost.org (2014a)
3.6.EBENEN57
IndiesemKapitelwirddiezweistufigeSerialisierunginnerhalbvonSISbeschrieben.
WarumdieSerialisierunginnerhalbvonSISzweistufigläuftistdurchdasWrapping-Patternzuerklären:
DadieC-SchichtihreeigeneSerialisierunghat,kanndieseselbstangesprochenwerden.UmdiezusätzlichenDatenstrukturenausderC++-Schichtzuserial-isieren,istjedochnochweitereSerialisierungnotwendig.
HierbeispielenfolgendeÜberlegungeneineRolle:
•DieSerialisierungderC-SchichtspeichertundliesteinkompaktesBinär-format(mehrInformationenzuBinär-SerialiseirungundByte-LayoutinKapitelMethodenzurSerialisierung)
•DieBeibehaltungderSerialisierungderC-Schichtbietetsichaus2Grün-denbesondersan:
–dieseistbereitsimplementiertundstelltihreFunktionalitätbereitszurVerfügung
–DieentstehendeDateikannvonderexecutablederC-Schicht–un-abhängigvonallemwasinnerhalbderC++-Schichtpassiert–,gele-senundgeschriebenwerden.EineBeibehaltungdieserSerialisierunggarantiertalsoeinegewisseÜbertragbarkeitderserialisiertenDatenzwischendenSchichten
•TrotzBeibehaltungderbestehendenFunktionalitätzurSerialisierungderC-SchichtistdieEntwicklungeinereigenenSerialisierungderC++-Schichtnotwendig.
AbgesehenvondengenerellenÜberlegungenzurSerialisierungwieimKapitelMethodenzurSerialisierungbeschrieben,bietensichzurSerialisierungineinBinärformatvorallemfolgendeOptionenan:
•boostserialization:eineStandardbibliothekfürC++,kann(virtuelleundpolymorphe)Klassenhierarchienspeichernundladen,hatextras,dieeserlaubenrawpointerzu(de)serialisieren,dieDokumentationunddieVer-wendungsindallerdingsnichtdieeinfachsten
•cereal(uscilab2014).Einemoderne,schlankeBibliothek,dievorallemaufC++11featuresderTemplateMetaProgrammierungsetzt.DieDoku-mentationistleichterzuverdauenalsdievonBoostSerializationunddieAPIleichterzubedienenundinvorhandeneStruktureneinzubauen
•cpp-generic-serialize(DanielBruder,FlorianFink2014):einekleineBibliothek,diedasBinär-Speichernund-ladenfürSTL-Containererleichtert,ebenfallsumgesetztdurchdieNutzungvonTemplateMetaProgrammierung.Erlaubtvorallemdasdetaillierteheraus-schreibenundeinlesenvoneinzelnenElementeneinesContainers,wennnicht
204CHAPTER25.ÜBUNGEN
58 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
ganze Klassen-hierarchien serialisiert sondern nur einzelne Elemente oderContainer einer Klasse serialiseirt werden sollen.
Im Falle von SIS fiel die Wahl auf cereal, da die Funktionalität den Bedürfnissenentspricht und die Verwendung als einfach bezeichnet werden kann.
Im besonderen Falle von SIS hinsichtlich des Wrappings und der Beibehaltungder Serialisierungs-Funktionalität der C-Schicht ist jedoch im besonderenzu beachten, dass die C++-Sicht beim Speichern die Serialisierung der C-Schicht anstoßen muss und beim Laden die Ergebnisse der C-Deserialisierungentsprechend berücksichtigen (und möglicherweise in die Klassenhierarchieentsprechend integrieren muss).
Hierzu stehen für einen generischen(!) template<AutomatonType> structDocumentIndexingAutomaton<AutomatonType<StringType>> folgendeSchnittstellen zur Verfügung:
template <class F = std::ofstream, class A = cereal::BinaryOutputArchive>void save(std::string & fn /* fs::path & p */);
template <class F = std::ifstream, class A = cereal::BinaryInputArchive>staticDocumentIndexingAutomaton<AutomatonType>load(std::string & fn);
Mit diesen Methoden lassen sich alle Kombinationen der folgenden Dimensionenvon DocumentIndexingAutomaton speichern und lesen:
Automaten StringType Formate Ziele
SCDAWGAdapter std::string JSON std::fstream,CDAWGAdapter std::wstring XML d.h. std::cout,CompressedAutomatonAdapter Binär std::ofstream (Datei), …
Table 3.1: Serialisierungsmöglichkeiten für DocumentIndexingAutomaton
Um zu verdeutlichen, wie die (De-)Serialisierung und dabei das Anstoßen derSerialisierungsfunktionen der C-Schicht funktioniert, hier die Implementierung:
1 namespace sis {2
3 /*****************************************************************************/4 template <class AutomatonType>
25.3. ÜBUNG 3: CMAKE 203
25.3 Übung 3: cmake
Verwenden Sie ihre Klasse aus der vorhergehenden Woche und schreiben SieMakefiles im cmake-Format diese.
Das cmake-file CMakeLists.txt soll dabei folgendes unterstützen:
• es werden zwei libraries gebaut cstructlib und cppstructlib, wobeidiese jeweils die beiden Klassen der letzten Woche enthalten
• main.cpp kann gebaut werden• die beiden o.g. libraries werden ordentlich zu main.cpp hinzugelinkt• die beiden o.g. libraries können einzeln gebaut werden: cmake .. &&
make cppstructlib• es werden out-of-source-builds unterstützt
3.6.EBENEN59
5template<classFileType,classArchiveType>6inline7void8DocumentIndexingAutomaton<AutomatonType>::9save(std::string&fn/*fs::path&p*/)
10{11FileTypeofs{fn};12ArchiveTypeoarchive{ofs};13
14index();15automaton_->save(fn+".c");//Writeautomatoninformationtoarchive16oarchive(*this);//Writethedocumentdatatothearchive17}18
19
20/*****************************************************************************/21template<classAutomatonType>22template<classFileType,classArchiveType>23inline24DocumentIndexingAutomaton<AutomatonType>25DocumentIndexingAutomaton<AutomatonType>::26load(std::string&fn)27{28FileTypeifs{fn};29ArchiveTypeiarchive{ifs};30
31autoaut=Factory::create<AutomatonType>();32aut->load(fn+".c");33
34DocumentIndexingAutomaton<AutomatonType>a;35iarchive(a);36//a.automaton_=std::shared_ptr<AutomatonAbstract<typenameAutomatonType::string_type>>(aut);37a.automaton_=aut;38for(auto&index:*(a.index_)){39index.second.set_voidsequence(a.automaton()->data());40}41returnstd::move(a);42}43
44/*....*/
ZurVerdeutlichungderKombinations-MöglichkeitenhiereinAuszugausdendazugehörigenTests:
1"CanwritetodiskinJSONformattostd::ofstream",[]2{
202CHAPTER25.ÜBUNGEN
60 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
3 std::cout << "saving to json" << std::endl;4 refresh_indexer();5 idx->save<std::ofstream,cereal::JSONOutputArchive>(f.filename.json);6 },7
8 "Can read back from disk in JSON format from std::ofstream", []9 {
10 std::cout << "loading from json" << std::endl;11 auto index_load = sis::DocumentIndexingAutomaton<sis::SCDAWGAdapter<std::string>>::load<std::ifstream,cereal::JSONInputArchive>(f.filename.json);12 },13
14 "Can write to disk in binary format to std::ofstream", []15 {16 std::cout << "saving to binary" << std::endl;17 refresh_indexer();18 idx->save<std::ofstream,cereal::BinaryOutputArchive>(f.filename.binary);19 },20
21 "Can read back from disk in binary format from std::ofstream", []22 {23 std::cout << "loading from binary" << std::endl;24 auto index_load = sis::DocumentIndexingAutomaton<sis::SCDAWGAdapter<std::string>>::load<std::ifstream,cereal::BinaryInputArchive>(f.filename.binary);25 // assert(aut.automaton_ != nullptr);26 },27
28 "Can write to disk in binary format to std::ofstream (with default template arguments)", []29 {30 refresh_indexer();31 idx->save<>(f.filename.binary);32 },33
34 "Can read back from disk in binary format from std::ofstream (with default template arguments)", []35 {36 auto aut = sis::DocumentIndexingAutomaton<sis::SCDAWGAdapter<std::string>>::load<>(f.filename.binary);37 // assert(aut.automaton_ != nullptr);38 },39
40 "Can write to disk in binary format to std::ofstream (with default template arguments -- and without using `<>')", []41 {42 refresh_indexer();43 idx->save(f.filename.binary);44 },45
46 /* ... */
25.2. ÜBUNG 2: C-WRAPPING 201
25.2 Übung 2: C-Wrapping
Schreiben Sie eine C++-Klasse, die die volle Funkionalität des folgenden C-struct wrapped und abbildet (inklusive der Unterscheidung private/public Meth-ode), mit vollen Konstruktoren und Destruktoren, die das C-Struct automatischallokieren und de-allokieren
Das C-struct halt folgende Spezifikation:
typedef struct tWordList {std::vector<std::string> words_;
} WordList;
// CTOR / DTORextern WordList * WordListInit();extern void WordListFree(WordList*);
// "public methods"extern void WordListAdd(WordList*, const char*);extern int WordListSize(WordList*);
// "private methods"static std::string WordListUpgradeWord(WordList*, const char*);
Schreiben Sie zunächst eine C++-Klasse, die:
• Einen Konstruktor und einen Destruktor enthält• einen (smart-)pointer auf das zu wrappende C-Struct hält• das C-struct im Konstruktor allokiert und im Desktruktor de-allokiert• alle public und private Methoden des C-Structs unterstützt und dabei• jeweils diese anspricht, anstatt selbst etwas zu machen
3.6.EBENEN61
DieAPIvoncerealUmeinBeispielvonderAPIvoncerealzugeben,hiereinAusschnittausDocumentIndexingAutomaton.Dabeigehtesimwesentlichendarum,einemember-Methodetemplate<classArchive>voidserialize(Archive&archive)fürdieKlassezudefinierenunddiesermitzuteilen,welchemember-Variablenserialisiertwerdensollen:
1
2template<classAutomatonType>3structDocumentIndexingAutomaton4{5
6/*....typedefsfürdiemember-TypenAutomatonAbstract_t,etc...*/7
8AutomatonAbstract_tautomaton_=nullptr;9std::unique_ptr<DocumentCollection_t>documents_=nullptr;
10std::unique_ptr<DocumentIndex_t>index_=nullptr;11std::map<UINT,std::vector<Document_t>>states_=nullptr;12FindResult_tresults_=nullptr;13size_ttotal_length_={0};14boolindexed_=false;15string_typequery_;16
17template<classArchive>voidserialize(Archive&archive){18archive(19CEREAL_NVP(documents_),20CEREAL_NVP(index_),21CEREAL_NVP(states_),22CEREAL_NVP(indexed_)23);24}
HinzuweisenistnochaufCEREAL_NVP:hiermitwirdfestgelegt,dass,wennnachjsonoderXMLserialisiertwird,dieDateninderSerialisierungbenanntwerden(NVP=namedvaluepair).
3.6.2Web-Ebene
IndiesemKapitelwerdendiewesentlichenBausteinederWeb-EbenevonSISbesprochen.DerWeb-TeilistimwesentlicheneineSPA(SingePageApp)undbauthierbeiweitestgehendaufdensogenanntenMEAN-Stack7auf,lässtaberu.a.dieDatenbankweg,dadieDatenvondenAutomateninSISgeliefertwerden.
7dasKürzelfürMongoDB+Express+Angular+Node,verlgeichehierzuauchdasnächsteKapitelunddasKapitel[Teilbesprechungen][]undseineUnterkapitel[DerMEAN-Stack][]und[Web-Applikationen,Basics][]
200CHAPTER25.ÜBUNGEN
•push-enSieIhrenneuentagsnachorigin
•BietenSieeinenpull-requestzumupstream-Repositoryan(dasRepository,dassSieamAnfangge-clone-dhatten)undbittenSieumÜbernahmeihres“Patches”
•Bonus:
–wennSiesichohnePasswortmitsshaufdencip-Rechnerneinloggenwollen,dannfügenSieihrenPublic-Keydortzu~/.sshhinzu,en-twederperHand,odermitssh-copy-id(IhreDistributionliefertdiesesmöglicherweiseschonmit,oderSiekönnenessichbequemin-stallierenwennSiemöchten)
•Bonus:
–clonenSiedasrepositoryaufdenCIP-Rechner,arbeitenSievonRe-motezuHause,ändernSieeineDateiab,undpushendieseinsgitlab.
•SSH-Bonus:
–legenSieeineDatei~/.ssh/configanundermöglichenSieessichdadurchsshcipstattsshnutzer@cip.ifi.lmu.desagenzukön-nen,umsicherfolgreichandencip-Rechnerneinzuloggen
•Remote-Working-Bonus:
–machenSiesichmitscreen,tmuxoderbyobu(alsFrontendfüreinesdervorgestelltenvertraut)undermöglichenSieessichdadurch,Terminal-Sessionsaufdencip-rechnernlaufenlassenzukönnenundzudiesenspäterzurückkehrenzukönnen.
•Bonus:
–arbeitenSiemitautosshoderdemPerl-ModulApp::asshundver-suchenSie,einepermanenteVerbindungzudencip-Rechnernhaltenzukönnen(schaltenSiedafürIhrInternetab-undwieder-an,undguckenSie,obdieVerbindungautomatischwiederhergestelltwird)
62 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
3.6.2.1 Wesentliche Technologien und ihr Zweck
• Node: stellt den (eigenen) Webserver dar• Express: Ein Web-Framework für Node• Angular: Client-seitige Logik• Jade: HTML-Templating Engine• Bootstrap: Client-seitiges CSS und mehr• Bootstrap UI: Client-seitige UI-Module (Dropdowns, etc.)• v8: Javascript-Engine in C++
Für Detail-Besprechungen dieser Technologien siehe auch das eigene Buch“Teilbesprechungen”.
3.6.2.2 Überblick
Wie im Kapitel Wesentliche Technologien und ihr Zweck angedeutet handelt essich bei der Web-Schicht um eine SPA in Form des MEAN-Stack.
Dabei spielt der Node-Webserver eine wesentliche Rolle. Mit Express, dem Web-Framework für node lassen sich routen definieren und Antworten an den Clientzurücksenden (vergleiche hierzu Abbildung 11.1 auf Seite 100).
Das Zusammenspiel von Node und den C++-Automaten von SIS funktioniertnun auf folgende Art und Weise:
Im Ordner web/ befindet sich eine weitere Schicht, welche die nun in C++ vor-liegenden Automaten derart wrapped, dass diese direkt in Javascript verwendetwerden können:
1 ## --[ app.coffee ]-- ##2
3 # import4 indexer = require './build/Release/sis'5 log.info('index imported', {})6
7 # deserialize8 indexerObj = indexer.load '../etc/allfiles'9 log.info('index loaded', {})
10
11 # size12 size = indexerObj.size()13 log.info('index size', {size: size})14
15
16 ## --[ query.coffee ]-- ##
25.1. ÜBUNG 1: GIT UND KOLLABORATION 199
25.1 Übung 1: git und Kollaboration
• aktivieren Sie den für Sie von der IFI bereitgestellten gitlab-Account beirz.ifi.lmu.de
– Stellen Sie dabei sicher, dass ihre (???) weitergeleitet werden,oder klicken Sie den Aktivierungslink, der an ihre cip.ifi-Adressegeschickt wurde, durch Verwendung von webmail2.cip.ifi.lmu.de oderwebmail.cip.ifi.lmu.de, wenn Sie der festen Meinung waren, dassSie ihre Mails zwar weiterleiten würden, aber unverständlicherweisekeine bekommen haben
• generieren sie ssh-Keys (mit oder ohne Passphrase), und legen Sie ihrenPublic(!)-Key an der dafür vorgesehenen Stelle in gitlab ab (im Notfalllesen Sie Dokumentation! Einmal: ‘generate ssh keys’ und die gitlab-Dokumentation: ssh keys adden.)
• nun loggen Sie sich in gitlab ein
– und forken sie das bisher dort eingestellte Kursmaterial in ein eigenesrepository
– clonen Sie dieses Repository auf ihren Rechner (von dem aus Sieihren Public-Key erstellt und hochgeladen haben)
• Installieren Sie die git-extras auf Ihrem und/oder den cip-Rechnern (dannwie [hier] beschrieben). Dieser Schritt ist empfohlen aber nicht zwingend:alles was die git-extras machen, lässt sich mit git alleine auch machen.
• Kreieren Sie einen branch in dem ge-clone-ten repository
• Kreieren Sie ein Verzeichnis mit ihrem cip-ifi-Namen
• Schreiben Sie eine Datei im Markdown-Format in ihrem Ordner, in doku-mentieren Sie in dieser ihre bisher geleisteten Schritte – so dass andere vonIhnen lernen könnten und klar ist, was Sie getan haben – es steht Ihnendabei selbstverständlich frei, hierfür pandoc zu verwenden und damit zuspielen
• push-en Sie ihren Branch nach origin
• Wechseln Sie zu ihrem master-branch zurück und mergen Sie ihren erstell-ten Branch dort hinein (mit einem Kommentar der in etwa sagt, ‘mergebranch Foo’)
• tag-gen Sie Ihr ge-merge-tes Changeset mit einer semantischen Version-snummber ihrer Wahl (c.f. das Kapitel über semantisches Verionieren;also in etwa 0.1.0 oder v0.1.0)
• push-en Sie Ihren neuen Master-Branch nach origin
3.6.EBENEN63
17#query18found=app.get('indexer').find(query,width)
Konkretbedeutetdies,dassdasC++-ObjektandieserStelleinJavascriptnutzbargemachtwordenist,undzwarals“node-addon”überv8!
DieErklärung,wiediesbewerkstelligtwerdenkann,folgtindiesemKapitel.
3.6.2.3ZweckdesWrapping
SelbstverständlichstelltsichdieFrage,warumüberhauptmanC++-Objektesowrappensollte,dassmanmitdieseninjavascriptarbeitenkann.DieAntwortlautet
a)weilmaneskann!b)weilesVorteilebeiderGeschwindigkeitliefert:
DieÜberlegungist,nur1xzudeserialisieren.
3.6.2.4Installation,KompilierungundBenutzungderWeb-Schicht
ZunächsteinmalaberzumLauffähig-machenderWeb-Componente(auchhiergilt:bittevergleichenSieauchdieeinschlägigenKapitelin[Teilbesprechun-gen][]).
ImNormalfallsolltederKompilierungs-undInstallationsprozessfürdieWeb-Komponentedurchdencmake-Workflowautomatischübernommenwerden,den-nochandieserStelleeinpaarHinweiseimSpeziellenundzumVorgangallge-mein.
Dercmake-WorkflowbildetdieWeb-Komponente(ausZeitgründen)nicht(!)perdefaultundmussgesondertaktiviertwerden:
17if($ENV{sis_BUILD_WEB_COMPONENT})18set(sis_BUILD_WEB_COMPONENTON)19else()20set(sis_BUILD_WEB_COMPONENTOFF)21endif()
Dasheisst,esgibtzweiMöglichkeiten,denBuildderWeb-Komponenteanzus-tossen:
a)dendefaultinderoberstenCMakeLists.txt-Dateiauszutauschen,oder
198CHAPTER25.ÜBUNGEN
–VergleichenSiehierzuauchdielinks[link]und[link]
•Facebookundemailsindzwargutundnett,aberdamitSielernen,wiemansichoptimalHilfeholenkann,probierenSieIRCaus.DiesesProtokollistzwarschonälteralsdasWWW,abernochimmer“hängen”hierdieEn-twicklerderSoftwaredieSiebenutzen“ab”.MachenSiesichmitIRCunddendortherrschendenUmgangsformenvertraut.(Hinweis:effektivFra-genzustellenkannhierbedeuten,alleAnredenwie“Hallo”…“ichhabeeinProblem”…“kannmirjemandhelfen”wegzulassenundseinekonkrete(!)Fragedirektzustellen,ohnejemandenbesondershervorzuheben).Ver-wendenSiehierzueinenbeliebigenIRC-Client.DesweiterenhabenwireineneigenenIRC-ChatroomfürdiesenKurs:[irc.ifi.lmu.de?]
64 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
b) eine environment-Variable auf ON zu setzen, womit der “volle” cmake-Befehl folgendermaßen aussieht:sis/build> SIS_BUILD_WEB_COMPONENT=ON cmake ..
(Der cmake-Befehl wird entsprechend eine Ausgabe liefern, die bestätigt oderverneint, ob die Web-Komponente gebaut wird):
[...]-- [WEB COMPONENT]-- Will NOT build web component[...]
bzw.
[...]-- [WEB COMPONENT]-- Will build web component[...]
Die Teile der Build-Kette für die Web-Komponente, die cmake automatischanstößt, umfassen:
• das Installieren der server-seitigen Dependencies• das Installieren der client-seitigen Dependencies• das Builden des node addon
server-seitige Dependencies installieren die server-seitigen Dependencieswerden in node immer mit dem node package manager npm installiert. Dieserliest die Datei package.json im obersten Verzeichnis aus und installiert diedort aufgeführten Dependencies (und rekursiv deren Sub-Dependencies).
sis/web> npm install
Hinweis: npm installiert seine projekt-spezifischen Pakete nach node_modules/.
client-seitige Dependencies installieren Die client-seitigen Dependencieswerden mit bower installiert. bower kümmert sich ebenfalls um das Auflösen vonAbhängigkeiten von Javascript-Paketen – nur eben, im Gegensatz zu npmˆ–, fürdie Client-Seite, also den Browser.
sis/web> bower install
Chapter 25
Übungen
Inhalt25.1Übung 1: git und Kollaboration . . . . . . . . . . . . 19925.2Übung 2: C-Wrapping . . . . . . . . . . . . . . . . . . 20125.3Übung 3: cmake . . . . . . . . . . . . . . . . . . . . . . 20325.4Übung 4: TDD – Test Driven Development . . . . . 20525.5Übung 5: Serialisierung . . . . . . . . . . . . . . . . . 20725.6Übung 6: Node-Wrapping . . . . . . . . . . . . . . . . 20925.7Übung 7: Template Meta Programmierung . . . . . 21125.8Übung 8: Type Traits . . . . . . . . . . . . . . . . . . 21325.9Übung 9: Web-Programmierung mit dem MEAN-
Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Grundlegendes zu den Übungen:
• helfen Sie sich gegenseitig aber lernen Sie für sich selbst!
Warum:
• ohnehin kann ich nicht kontrollieren, ob Sie sich gegenseitig bei den Auf-gaben helfen (oder nicht)
• ohnehin sind die Abgaben der Übungen für den Dozenten lediglich einHinweis auf Ihren Lernerfolg
• ohnehin ist Ihr Lernerfolg langfristig gesehen nur für Sie selbst interessant• ohnehin ist jeder bei der Komplexität der Programmier-Materie perma-
nent auf die Hilfe von anderen angewiesen – zu lernen wie man sich gegen-seitig effektiv helfen kann, ist ein ganz ganz wichtiger, nicht zu unter-schätzender Teil! Nicht zuletzt gehört dazu auch, sich effektiv helfen zulassen, d.h. Fragen zu konkretisieren, Beispiele auf ein Minimum zu re-duzieren, etc.
197
3.6.EBENEN65
Hinweis:bowerinstalliertseineprojekt-spezifischenPaketenachbower_components/oderapp/bower_components/
VergleicheauchnocheinmaldieBeschreibungderProjektstrukturimKapitelProjektstruktur!
nodeaddonbuildenNichtzuletztmussnochdasnodeaddonkompiliertwerden,dassdieC++-ObjekteinJavascriptzurVerfügungstellt.Dafürwirdklassischerweisenode-gyp8alsBuild-Toolverwendet.
node-gypliestdieDateibinding.gypausundorientiertdaranseinenbuild-Prozess.
node-gypumfasstwiederummehreresub-befehle,imwesentlichenaberreichtein…
web/sis>node-gyprebuild
…um(implizit)einnode-gypbuildanzustossen.
binding.gypEineminimalebinding.gyp-Dateisiehtfolgendermaßenaus:
{"targets":[{"target_name":"hello","sources":["hello.cc"]
}]
}
AndieserStellesollendiewichtigstenAusschnittederbinding.gypvonSISinallerKürzebesprochenwerden:
{'targets':[{
'target_name':'sis','sources':[
'cpp/sis.cpp','cpp/DocumentIndexingAutomaton.cpp'
8gypstehtfür“GenerateYourProject”undwurdevonGooglefürdenBuild-ProzessvonChromeentwickelt:umdieKomplexitätdessenzuermessen,vergleiche:“LifeOfAChromiumDeveloper”aufhttp://dev.chromium.org/Home
66 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
],'include_dirs': [
'/usr/include','<!@(echo `pwd`/../src/)','<!@(echo `pwd`/../vendor)','<!@(echo `pwd`/../vendor/serialization/include)','<!@(echo `pwd`/../vendor/make_unique)','<!@(echo `pwd`/../vendor/pugixml/src)'
],# global flags go here# `cflags_cc!` is supposed to mean: remove these flags'cflags_cc!': [ '-fno-rtti' ], # '-fno-exceptions'# `cflags_cc` is supposed to mean: add these flags
'cflags_cc': [ '-fPIC', '-std=c++11', '-fexceptions', '-Wall', '-Wextra', '-Wno-attributes', '-Wno-pointer-arith' ],'conditions': [
/* [......] */
Zu beachten sind folgende Punkte:
• include_dirs verlangt vollständige Pfade, daher der “Hack” über diecommandline
• cflags_cc! nimmt vorhandene Compiler-Flags weg• cflags_cc fügt Compiler-Flags an die bereits vorhandenen hinzu
Hinweise
• Hinweis für Server omega bzw. 64-bit-Systeme: Omega hat 2 verschiedeneVerzeichnisse, in denen libs liegen können: /usr/lib und /usr/lib64! ImFalle von fehlenden shared-objects auch dort suchen. Beim Build-Prozess
• Hinweis für spezielle Compiler: um SIS kompilieren zu können ist einGNU gcc Compiler >= 4.7.0 nötig. Ein solcher ist zwar möglicherweiseinstalliert, aber mit einem Namenssuffix versehen, d.h. liegt als g++-4.8oder ähnlich vor. Daher unbedingt den Standard-Compiler des akutellenSystems genauer unter die Lupe nehmen:
i) which gcc; gcc --version;ii) einen anderen compiler suchen – dabei die “einschlägigen” Pfade
durchsuchen, z.B.: ls /usr/bin/g++*iii) Diesen speziellen compiler nötigenfalls noch node-gyp “un-
terzuschmuggeln”: um den Compiler zu ermitteln, liest node-gyp dieENV-Variable CXX aus. Diese lässt sich am besten gleich auf denvollen Pfad von gcc setzen, der Befehl lautet also ungefähr:
Part IX
Übungen
195
3.6.EBENEN67
CXX=whichg++-4.8node-gyprebuild
•Manchmalkannesvorkommen,dassbeimStartdesnodeServersdiesharedobjectsausdemnodewrappingnichtgefundenwerden;dahilftesdieVariableLD_LIBRARY_PATHentsprechendanzupassen:LD_LIBRARY_PATH=/srv/www/sis/sis3/build/lib:$LD_LIBRARY_PATHcoffeeapp.coffee
WebServerstartenumdenWeb-Serverzustarten,reichtesmitnodedieentsprechendejavascript-Dateizustarten.
DafürSIScoffeescriptstattjavascriptverwendetwird,stattdessendenserveralsomitdemBefehlcoffeestattnodestarten:coffeeapp.coffee.
DeployMitdeno.g.HinweisenimGepäcklässtsichdieApplikationnunauchaufdenServerdeployen(beachtehierzubitteauchdasKapitel[Derausführendeuserwastd][]).
UmimFalleeinesCrashsdenWeb-Serversofortwiederneuzustarten(spezielldiesesAddonmitseinerzugrundliegendenC-SchichitistsehrgefährdetfürSEG-FAULTs…),lässtsichdasnode-moduleforever9verwenden.SiehedieDateiweb/wast.startfürnähereDetails.
3.6.3NodeAddon
3.6.4NächsteSchritte
•AlternativzueinemNode-AddongibtesdieMöglichkeit,durchdieVerwendungvonemscripten(EmscriptenAuthors2013),C++nachJavascriptzukompilieren.AllerdingsmüsstendabeidiekomplettenIndex-DateienindenBrowserdesClientübertragenwerden,weshalbhiernurderHinweisaufemscriptengegebenwerdensoll.
9http://node-modules.com/search?q=forever
194CHAPTER24.MAILINGLISTE
•antwort-oben-zitat-unten?
•linkvonstefan
•linkzumailing-list-best-practicesbzwimportvondort
68 CHAPTER 3. SIS: SYMMETRIC INDEX STRUCTURES
Chapter 24
Mailingliste
• Die Mailinglisten sind:
– wast-list – die allgemeine Mailingliste für WAST* https://lists.ifi.lmu.de/mailman/admin/wast-list
– wast-kurs – Mailingliste für den WAST-Kurs von Max und Daniel(SoSe 2014)* https://lists.ifi.lmu.de/mailman/admin/wast-kurs
• Die Mailinglisten laufen über die IFI: https://lists.ifi.lmu.de/
• wann kommt sie zum einsatz?
• wofür?
• wer ist drauf?
• Überlegungen:
• externe mailingliste für norweger, etc.
• interne für developer
• dort:
– announces für neue releases– diskussion intern
• Verweis auf best-practices / netiquette:
• thread-sortiertes antworten (warum: wieso soll es meine aufgabe sein, einealte mail rauszusuchen?, wie soll jemand im archiv die antwort finden?)
• warum? archivierbar, nachvollziehbar, multiplexing fähig
193
PartIV
Feedback
69
192CHAPTER23.LIZENZEN
23.1GNUGPL
23.1.1GNUGPLv2
23.1.2GNUGPLv3
23.1.3GNULGPL
23.1.4GPL-Compaitibility
23.1.5AfferoGPL
23.1.6GPLv2Loophole
23.2MIT
23.3CreativeCommons
23.3.1CC-Bausteine
23.3.2NC-BY-SA
23.3.3NC-BY…
23.4WTFPL
Chapter 23
Lizenzen
Inhalt23.1GNU GPL . . . . . . . . . . . . . . . . . . . . . . . . . 192
23.1.1 GNU GPLv2 . . . . . . . . . . . . . . . . . . . . . . 19223.1.2 GNU GPLv3 . . . . . . . . . . . . . . . . . . . . . . 19223.1.3 GNU LGPL . . . . . . . . . . . . . . . . . . . . . . . 19223.1.4 GPL-Compaitibility . . . . . . . . . . . . . . . . . . 19223.1.5 Affero GPL . . . . . . . . . . . . . . . . . . . . . . . 19223.1.6 GPLv2 Loophole . . . . . . . . . . . . . . . . . . . . 192
23.2MIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19223.3Creative Commons . . . . . . . . . . . . . . . . . . . . 192
23.3.1 CC-Bausteine . . . . . . . . . . . . . . . . . . . . . . 19223.3.2 NC-BY-SA . . . . . . . . . . . . . . . . . . . . . . . 19223.3.3 NC-BY … . . . . . . . . . . . . . . . . . . . . . . . . 192
23.4WTFPL . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Bei allen Entwicklungen – sowohl im kommerziellen wie auch in der “PublicDomain” –, ist die Frage nach Lizenzen als sehr wichtig einzustufen.Die Geschichte der “Open Source”- und “Free/Libre Software”-Lizenzen istsehr interessant und in erster Linie hier nachzulesen [Lessig, Lessig, Stallman,Moody].Kurz gesagt mussten sich die “Hacker” auch in Lizenzmodelle einarbeiten unddiese “hacken” um ihre Software zu schützen, daher die vielen verschiedenen,z.T. sich widersprechenden und komplizierten Lizenzmodelle.Im folgenden ein Kurzüberblick über die meistverwendeten Lizenzen und derenCharaktersitika – dies aber vollständig “ohne Gewähr”, um bei Entwicklungeninnerhalb von WAST die richtige Lizenz wählen zu können.[Lizenz-Wizard auch verlinken]
191
Chapter4
feedback
Inhalt4.1Aufbau............................72
4.1.1Dateistruktur......................724.2Application-Logic.....................72
DieApplikationFeedback1dientalsWeb-Front-endfürdasreportingvonbugs,featurerequestsundalleranderenDinge,dierelevantsindfürdenBugtrackerunddiedahinterliegendenKonzepteder“BugTrackingBestPractices”.
Bugsundfeaturerequestssubmittenzukönnenkanninteressantseinfür
•Philosophen•Interessierte•dieKomponenten-Verwalterselbst•generallalle,dienichtgitlabverwendenwollen(oderkönnen)
AlsWeb-ApplikationistFeedbackkonzipiert,dagenerelljeder,dereinenBugimBugTrackereintragenmöchte,eineRegistrierungaufderWeb-Oberflächedesgitlab2benötigenwürde,diesesabereinezuhoheHürdedarstelltundBugRe-porteraufgrunddesAufwandsdavonabhaltenkönnte,wichtigeInformationenbereitzustellen.
DarüberhinausgarantiertFeedbackeinegeordeneteWeise,inderBugsabgelegtwerden,indemesbugsautomatischnachKomponentenundMaintainernsortiert(durchtags)direktindieBug-Listeeinträgt.
1https://gitlab.cis.uni-muenchen.de/wast/wast-feedback2http://gitlab.cis.lmu.de
71
190CHAPTER22.SEMANTICVERSIONING
ImobengegebenenBeispielhatsichXmitv14.02aufdieVersionvonWASTzumZeitpunktFebruar2014bezogen.DieVersionvonNovember2015wirdalso15.11sein.DabeiisteinmonatlicherRelease-Cyclegegeben.
Wiegesagt,diesistdieVersionierungnachaußen,d.h.imZusammenspielallerKomponenten.InderVersionierungnachinnensolltesichjedederKomponen-tenselbstjedochamBestenamSchemadesSemanticVersioningorientieren.
DementsprechendkanneinReleaseunddieVersiondesselbengenauerunterteiltwerden:
Beispiel:
•Release14.02könntenämlichindiesemSinneeineZusammenstellungderfolgendenKomponentengewesensein:
–WAB-Transkription2.3.1–wittfind-Komponente4.2.3–sis-Komponente3.9.1–…
22.1.2SemanticVersioning
ImwewsentlichenverstehtmanuntersemanticversioningeineVersionsangabemitfolgendemFormat:Major.Minor.Patch.
DabeistehenMajor-Versionenfür(z.T.)untereinandernicht-kompatibleAPIsodergroßeVeränderungen/VerbesserungenamCode,bzw.VerweisenaufwesentlicheEntwicklungsschritteimCode.
DieZahlunterMinorbezeichnetdenaktuellenEntwicklungsstanddesCodes.IndenmeistenFällenwerdenalsMinorungeradeZahlenverwendetumanzudeuten,dassdieseineEntwickler-Versionist,und,nachdemdieseEntwick-lungeinesbestimmtenFeatures(oderähnlichem)abgeschlossenist,diesedannumeinshochgezähltzueinergeradenZahl.
NichtzuletztwirdPatchbeibugfixeshochgezählt.
Vergleichez.B.
•Perl,Version5.19.4(Perl5,Weiterentwicklungvon5.18(alsEntwicklerver-sion),patch-level4)
•nodejs,Version0.10.20(Nochnichtals1.0.0-fähiganerkanntes,d.h.nochnichtkomplettstabilisiertes,dennochfortgeschrittenesProjektineiner0.10-er-“stableversion”mitpatch-level20)
MehrInformationenzuSematicVersioningfindensichbeihttp://semver.org/(TomPreston-Werner2013)
72 CHAPTER 4. FEEDBACK
4.1 Aufbau
Der Aufbau von Feedback gestaltet sich in Form ein MEAN-Stack Web-Applikation, welche das Frontend und Backend bildet.
Im Backend wird im wesentlichen die API des Gitlab genutzt, um Bugs eintzu-tragen.
Um mit der API von Gitlab sprechen zu können bedarf eines eines sogenan-nten “Private Token” zur Authentifizierung. Hierfür wurde ein gesonderterUser (“FeedbackBot”) angelegt, dessen Token verwendet wird, um Bugs zusubmitten (dieses geheimzuhaltende Token wird auf der Serverseite bereitge-halten und nicht in das Frontend, zum Client übertragen). Um innerhalb vonWittgenstein-Issues3 bugs submitten zu können, muss FeedbackBot selbstver-ständlich als Member im Projekt vorhanden sein.
4.1.1 Dateistruktur
.|-- Makefile # targets zum starten, stoppen, restart|-- README.md|-- bower.json # ini-file für client-seitige dependencies|-- bower_components # Ordner für client-seitige dependencies|-- database # MongoDB-Anbindung|-- node_modules # Ordner für Server-seitige dependencies|-- npm-shrinkwrap.json # ini-file für server-seitige dependencies (unwichtig)|-- package.json # ini-file für server-seitige dependencies (wichtig)|-- public # client-seitiger Applikationsteil: Application-Logic (AngularJS)|-- routes.js # Server-seitige Routes|-- views # client-seitiger Teil: Views (Jade)`-- wast-feedback-server.js # Der Web-Server selbst (node)
4.2 Application-Logic
Der operationale Ablauf der Web-Applikation gestaltet sich folgendermaßen:
1. User geht auf2. Er ist noch nicht eingeloggt (wittgenstein-issues soll nicht von Bots ges-
pammed werden)3. User logged sich ein (CIS/lmu)4. User füllt Formular aus:
a. Das Formular wird permanent auf Vollständigkeit geprüft (ansonstenwird live eine Warnung/Hilfe angezeigt)
3https://gitlab.cis.uni-muenchen.de/wast/wittgenstein-issues/issues
Chapter 22
Semantic Versioning
Inhalt22.1Versions-Schema . . . . . . . . . . . . . . . . . . . . . . 189
22.1.1 Ubuntu-Schema . . . . . . . . . . . . . . . . . . . . . 18922.1.2 Semantic Versioning . . . . . . . . . . . . . . . . . . 190
Die Versionierung (in Zusammenarbeit mit der gemeinsamen Bug Verwaltung)garantiert Referenzierbarkeit hinsichtlich der Zitierbarkeit für die Philosophie(und darüber hinaus).
Beispiel:
• Der Philosoph X schreibt einen Aufsatz und benutzt die Transkription ausNorwegen.
• Er behauptet Y in seinem Artikel und referenziert sauber seine Quelle. Inetwa: WAST, v14.02
• Der Artikel wird veröffentlicht, und später wird entdeckt, dass X’s Be-hauptung Y ungültig ist, da die Transkription einen Fehler enthielt
• Nun hat X aber Y unter Voraussetzung der Version 14.02 behauptet undkann nicht die Verantwortung für den Transkriptions-Fehler übernehmen.
22.1 Versions-Schema
22.1.1 Ubuntu-Schema
Das Versionsschema von WAST orientiert sich nach außen am Versions-Schemavon Ubuntu. Dabei wrid die Versionsnummer zusammengesetzt aus derJahreszahl und dem Monat des Releases.
189
4.2.APPLICATION-LOGIC73
b.UserbeschreibtseinenBuggenau(nachdenRegelndesWAST-Workflow:wie/wann/woerscheintdieserFehler,wiekannmanihnreproduzieren,etc.)undhinterlässtseineemail-Adresse:dadurchkanneramEndeeinesresolvetenBugsverify-enobderBuginseinemSinnegelöstwurde
5.UserschicktFormularab:
a.einPOST-RequestaufeinebestimmteServer-RoutewirdmitdenDatendesFormularsgetätigt
b.DerWeb-ServerhateinebestimmteLogikimplementiert,waspassierensoll,wennereinenPOST-RequestaufdieserRouteentgegennimmt:
c.DerWeb-ServernimmtdenprivatenTokendesFeedbackBotundschicktmiteinemcurl-RequesteineBugsubmissionandieAPIvongitlab.
d.DerServersagtderClient-Seite,obererfolgreichmitdergitlab-APIsprechenkonnte
e.DieClient-SeitegibtdemUsereineRückmeldung,obderBugerfol-greicheingetragenwerdenkonnte.
6.DemUserstehtesfrei,einenweiterenBug-Reportzusenden(alsozurückzu1.)oderfertigzusein.
Hinweis:FüreinegenauereBeschreibungvonClient-Seite/Server-SeitesiehedasKapitelWeb-Applikationen,füreineBeschreibungdereinzelnenKomponentensiehedasKapitelMEAN-StackundfüreineBeschreibungderApplikations-LogikhinsichtlichController,View,etc.,vergleichedasKapitelDesignPatterns.
188CHAPTER21.VERSIONIERUNG
#[Ingitlabisteinissueimbugtrackereröffnet]pltk@master$gitbugissue-66pltk@bug/issue-66$[hackhack...]pltk@bug/issue-66$[letztercommit]pltk@bug/issue-66$gitcheckoutmasterpltk@master$gitfeaturefinishissue-66
74 CHAPTER 4. FEEDBACK 21.1. GIT 187
21.1.3 git-extras
git-extras (visionmedia 2014) geben viele nützliche (neue) Kommandos zu denStandard git-Kommandos hinzu.
Dadurch kürzen sie einige Wege ab, oder erleichtern andere, routine-mäßigeAufgaben.
Da sie aber mit Hilfe der von git selbst zur Verfügung gestellten Kommandosimplementiert sind, könnte man selbstverständlich alles auch ohne git-extrasmachen.
Dennoch können die git-extras als eine sinnvolle Empfehlung betrachtet werden.
21.1.3.1 Installation auf CIP-Rechnern
Um die git-extras auf den CIP-Rechnern zu installieren kann man folgendesVerfahren nutzen:
git clone https://github.com/visionmedia/git-extrascd git-extrasmake DESTDIR=$HOME PREFIX="" install
Ich empfehle sehr, die git-extras9 zu verwenden und schlage folgendes Branching-Model vor:
• Der master branch wird nur für fertiggestellte Funktionalität verwendet• gearbeitet wird auf dev/feature/bug und refactor branches• dann merges oder pull requests• zuletzt ein release
Mit git-extras ist das wirklich einfach: Anstatt selbst einen Branch anzulegen,auf diesen zu wechseln, dort zu arbeiten, dann diesen Branch in den master-Branch zu mergen, bietet sich u.a. folgender Workflow an:
pltk@master$ git feature lemmatizerpltk@feature/lemmatizer$ [hack hack (möglichst kleine Commits bitte!)]pltk@feature/lemmatizer$ git commit -am 'last commit'pltk@feature/lemmatizer$ git checkout masterpltk@master$ git feature finish lemmatizer
Bei Bug-Fixes schlage ich folgendes Modell vor:9https://github.com/visionmedia/git-extras
PartV
WeitereKomponenten
75
186CHAPTER21.VERSIONIERUNG
5.dendev-branchlöschen(sonstentstehtbaldChaos!)
>gitbranch-ddevDeletedbranchdev(was46b34ab).
ZuguterletztwollenwirdieErgebnisseaufeinremote-repositorypushen.
Dafürcheckenwirerstmalobremoteseingetragensind:
>gitremote-v[keinoutput]
Dahertragenwirunsereersteremote-Adresseeinundnennensieorigin:
>gitremoteaddoriginname@machine:path/to/bare/repository.git>gitremote-voriginname@machine:path/to/bare/repository.git(fetch)originname@machine:path/to/bare/repository.git(push)
…dabeifunktionierendieAngabenfürremote-repositoriesgenauwiebeimssh-Protokoll:
•name@machinefürdenZugang•gefolgtvoneienmDoppelpunkt:•gefolgtvomPfadzumrepositorypath/to/bare/repository.git•(indiesemFalldeutetderrepository-Namerepository.gitan,dassdies
einsog.git“bare”repositoryist,dazuanandererStellemehr).
WenndasVerzeichnisexistiertunddiePfadangabestimmt,lässtsichnunaufdiesesrepositorypushen:
>gitpushoriginmaster
Hierbeipushenwirunserenbranchmasteraufdasremote-repositorymitdemNamenorigin.
Äquivalentdazuistderpull,d.h.Änderungen(diewomöglichvonanderen)indasremote-repositoryge-push-twordensind,abzuholen:
>gitpulloriginmaster
21.1. GIT 185
# (use "git add <file>..." to include in what will be committed)## var/nothing added to commit but untracked files present (use "git add" to track)
2. den dev-branch mergen
> git merge devUpdating 9112df6..46b34abFast-forward.gitignore | 1 +eos.pl | 15 +++++++++++++++eos.t | 4 ++++3 files changed, 20 insertions(+)create mode 100644 .gitignorecreate mode 100755 eos.plcreate mode 100644 eos.t
3. Die vorhandenen Dateien prüfen
> ls -1READMEeos.pleos.tvar
4. Den log prüfen
> git --no-pager log --graph* commit 46b34ab61c7f23ed6d4fbb2baf7dca468bbfb07d| Author: NAME <EMAIL>| Date: DATE|| add first version of eos + test data|* commit 1f986bd9d98e04aa5ea73a68ea9cbf83a736da7a| Author: NAME <EMAIL>| Date: DATE|| add gitignore|* commit 9112df662257116774d946cb5482116263cbc511
Author: NAME <EMAIL>Date: DATE
add documentation
Chapter5
wab2cis
Inhalt5.1Einbindungalsgit-submodule..............77
VerwendungvonTEI,[sieheauchSonderkapitelTEI]
5.1Einbindungalsgit-submodule
ZurVerwendungvongit,sieheKapitelgitsubmodules.
77
184CHAPTER21.VERSIONIERUNG
InteressantwirdnunfolgendesExperiment:WirlassenunsganzgewöhnlichvondershelldenInhaltdesVerzeichnissesanzeigen,wechselndannindenmaster-branchundschauenunsdenVerzeichnisinhalterneutanundvergleichenbeideErgebnisse.
>gitbranch*dev
master
>ls-1READMEeos.pleos.tvar
>gitcheckoutmasterSwitchedtobranch'master'>ls-1READMEvar
>gitcheckoutdevSwitchedtobranch'dev'>ls-1READMEeos.pleos.tvar
DasErgebnisistdurchausausverblüffendzubezeichnen:githattatsächlichaufFile-System-Ebene(!)dieDateien“ausgetauscht”unddasVerzeichniskomplettverändert.
AlsnächstesnunwollenwirdieEntwicklungunsereseoshierbeendenunddendev-branchnunindenmaster-branchzurück-mergen.Dafürwerdenwirfolgendestun:
1.Aufdenmasterbranchwechseln
>gitcheckoutmasterSwitchedtobranch'master'
>gitstatus#Onbranchmaster#Untrackedfiles:
78 CHAPTER 5. WAB2CIS 21.1. GIT 183
git hat schon die Datei .gitignore ausgewertet und zeigt das Verzeichnis vargar nicht mehr als potentiell-hinzuzufügende Datei an!Um schöne kleine commits zu haben (die man im Notfall später leichter “zurück-spielen” kann), werden wir die fehlenden Dateien nur Stück für Stück zum repos-itory adden:
> git add .gitignore
> git commit -am 'add gitignore'[dev 1f986bd] add gitignore1 file changed, 1 insertion(+)create mode 100644 .gitignore
> git status# On branch dev# Untracked files:# (use "git add <file>..." to include in what will be committed)## eos.pl# eos.tnothing added to commit but untracked files present (use "git add" to track)
> git add eos.*
> git commit -am 'add first version of eos + test data'[dev 46b34ab] add first version of eos + test data2 files changed, 19 insertions(+)create mode 100755 eos.plcreate mode 100644 eos.t
> git status# On branch devnothing to commit (working directory clean)
Nun können wir bereits die kurze History unseres repository anschauen, z.B. indiesem Format:
> git log --oneline --decorate --graph* 46b34ab (HEAD, dev) add first version of eos + test data* 1f986bd add gitignore* 9112df6 (master) add documentation
…und sehen hierbei die Bezeichnungen für die jeweiligen branches auf denen dieÄnderungen gemacht wurden, und den aktuellen HEAD.
Chapter6
WIndex
79
182CHAPTER21.VERSIONIERUNG
>chmodu+xeos.pl
UndlegennocheinVerzeichnisfürErgebnissevonunterschiedlichenTestläufenan–dieseErgebnisseunddasgesamtezugehörigeVerzeichniswerdenwirabernichtinunserencommitshabenwollenundignorieren:
>mkdirvar
>cateos.t|./eos.pl>var/res.1
DieAusgabevongitstatusistmittlerweilealsoschonvertraut:
>gitstatus#Onbranchdev#Untrackedfiles:#(use"gitadd<file>..."toincludeinwhatwillbecommitted)##eos.pl#eos.t#var/
gitteiltunsalsomit,dasseszweiDateienundeinVerzeichnisinunseremProjektgibt,dassesnochnichtkennt,diewiraberpergitaddzuunsererVersionskontrollehinzufügenkönnen.
DawirdasVerzeichnisfürZwischenergebnisse,abernichttrackenundlieberignorierenwollen,tunwirfolgendes:wirlegeneineDatei.gitignorean,diealleDateienundVerzeichnisselistet,diegitignorierensollundfügendieseindasrepositoryhinzu.
echovar/>>.gitignore
NunzeigtgitstatusfoldenesinteressantesErgebnis:
gitstatus#Onbranchdev#Untrackedfiles:#(use"gitadd<file>..."toincludeinwhatwillbecommitted)##.gitignore#eos.pl#eos.t
80 CHAPTER 6. WINDEX 21.1. GIT 181
…was bedeutet, dass es einen branch namens dev gibt, der aktuelle branch abernoch auf master steht. Das wollen wir ändern:
> git checkout devSwitched to branch 'dev'
Wie erwartet, haben wir in den branch dev gewechselt und können dies auchüberprüfen:
> git branch* dev
master
Hier also können wir neue Funktionalität entwickeln, ohne die Hauptentwick-lungslinie zu beeinträchtigen.
Legen wir also als nächstes unsere ersten Dateien des Satzendeerkenners an, mitfolgenden Inhalten:
> cat eos.pl#!/usr/bin/env perl -0 -ps/((((Mr|[[:upper:]]|\d+)\. # Ausnahmen: Abkürzungen etc.|.+? # alles andere (non-greedy,
# d.h. 1. nicht [.!?] gefolgt von SPACE + Großbuchstabe)# 2. keine Abkürzung
)+? # eine Folge von Abkürzungen oder "alles"[.!?](?=\s+[[:upper:]]) # EOS))
/$1<EOS>/gx;EOS
> cat eos.tEin Satz? Hier auch! Am 19. August 1972 schläftMr. G. W. Spencer. Hier beginnt ein Satz. In derOettingenstr. 67 stehen Computer.Perl arbeitet hier zeilenweise, Sätze dürfen nicht über Zeilen gehen.TXT
Als nächstes machen wir das Programm ausführbar:
Chapter7
Patrick’sTeil:AusformulierungvonAlternativen
81
180CHAPTER21.VERSIONIERUNG
AlsnächsteswollenwirinderEntwicklungunseresSatzende-Erkennersfort-fahrenunddabeieinesvongit’swichtigstenfeaturesnutzen,dasbranching,d.h.wirzweigenvonderHauptentwicklungslinieweg,umeineneueFunktional-itätzuentwickelnundwerdendiese,sobaldsiefertigist,wiederindieHaupten-twicklungsliniezurückführen(mergen).gitistimVergleichzusvnsehrsparsambeimAnlegenvonneuenbranchesundfördertdasAnlegenundmergenvonbranchessehr.
Alsersteswollenwireinmalgucken,obesdennvielleichtzufälligschonbranchesgibt:
>gitbranch*master
Offensichtlichgibtesderzeitnureinenbranch,undzwardenbranchmaster.
Vorsicht!GitzeigtindiesemFallnurunserelokalenbranchesan,nichtaberpotentiellebranchesdieaufservernliegen!Bisherhabenwirnochkeinesog.remotes(alsoentfernterepositories,wiezumBeispielein“Zentral-”Repository)eingetragen,aberumpotentiell“entfernte”branchesanzeigenzulassen,brauchenwirfolgendenSwitch:
>githelpbranch[...]-a,--all
Listbothremote-trackingbranchesandlocalbranches.[...]
DaaberkeineremotesexistierenwirddasErgebnisvongitbranch-aalsodasselbeergebenwiegitbranch(nurlokalebranchesanzeigen):
>gitbranch-a*master
NunalsosollendlicheinbranchfürdieEntwicklungmitdemNamendevan-gelegtwerden:
>gitbranchdev
Einerneutercheck,welchebranchesexistieren,zeigt:
>gitbranchdev*master
82CHAPTER 7. PATRICK’S TEIL: AUSFORMULIERUNG VON ALTERNATIVEN 21.1. GIT 179
commit 9112df662257116774d946cb5482116263cbc511Author: AUTORENNAME <EMAILADRESSE></emailadresse>Date: DATUM
add documentation
Anders als svn hat git keine “klaren” Revisions-Nummern wie r1 etc., sondernstatt dessen 40-stellige SHA-Summen für jeden commit.
Dies hat mehrere Vorteile (vergleiche Daten-Sicherheit[ˆsiehe oben, und hier[[link einfügen]]]), aber auch einen entscheidenden Nachteil: sie sind menschlichschlecht lesbar.
Es gibt mehrere Möglichkeiten, sich nicht diese 40-stelligen Nummern merken zumüssen, um, z.B. um mit jemand anderen über eine bestimmte Revision redenzu können.
Hierzu gibt es verschiedene Strategien, die git anbietet, z.B.: Abkürzen derSHA-Summe auf wenige Stellen (solange der damit gemeinte commit eindeutigbleibt). In der Regel einigt man sich auf die ersten 6 Stellen wenn man übereinen konkreten commit sprechen will, in diesem Fall also:
9112df
Nebenbemerkung für Interessierte: Es gibt einen sogenannten git plumbing com-mand (sozusagen ein Kommando um mit git selbst zu arbeiten, das aber gewöhn-lich nicht im Alltag gebraucht wird (dies wären die porcelain commands)), dasanzeigt, was git aus einer solchen abgekürzten Revisions-Nummer herausliest:
> git rev-parse 9112df9112df662257116774d946cb5482116263cbc511
Eine weitere Strategie, Revisionsnummern menschlich zugänglicher zu machen,besteht darin, Aliases zu verwenden.
Dies kann geschehen durch:
1. das Alias HEAD, HEADˆ, HEADˆˆ um jeweils auf den letzten, vorletzten, vor-vor-letzten commit zu referenzieren
2. oder durch die Aliase HEAD@{1}, HEAD@{2} um auf die selben commits zureferenzieren
3. durch tags: später werden wir sehen, wie man bestimmte Revisionen ex-plizit “benennen” kann durch git tag. So könnte man also einen ganzbestimmten 40-stelligen commit als v1.2.3 taggen und somit genau dasgleiche meinen.
PartVI
Toolchain
83
178CHAPTER21.VERSIONIERUNG
>gitaddREADME
MitdiesemBefehlwurdedieDateiabernochnichtendgültigindasrepositoryaufgenommen:vielmehrwurdedieDateiindiesog.stagingarea(InAbbil-dung21.1aufSeite176“Index”genannt)übernommenundwirdbeimnächstencommitendgültigindasrepositoryaufgenommenwerden.EinweitererVergleichdesvorherigenStatusmitdemjetzigenStatusverdeut-lichtdies:
>gitstatus
…liefertunsnunfolgendenOutput:
#Onbranchmaster##Initialcommit##Changestobecommitted:#(use"gitrm--cached<file>..."tounstage)##newfile:README#
DadiesdieeinzigeÄnderungist,diewirindiesemChangesetausführenwollen(iwrkönntenauchnochweitereDateienaddenunderstdanncommiten),machenwireinencommit:
>gitcommit-am'adddocumentation'
Nunwird…
>gitstatus
…folgendesmelden:
#Onbranchmasternothingtocommit(workingdirectoryclean)
d.h.wirbefindenunseinem“clean-state”,d.h.alleaktuellenÄnderungensindbekanntundessindkeineweiterenÄnderungenanirgendwelchenDateienunseresrepositoryvorgenommenworden.UmdieseletzterenÄnderungenzuverfolgenbetrachtenwiralsnächstesdenOutputvongitlog:
21.1. GIT 177
> git commit -am 'initial commit'
Dabei stellen die (kombinierten) Kommandozeilen Switches folgendes dar:
-a Füge alle git bereits bekannten Dateien zum commit hinzu (bisher habenwir solche noch nicht, aber gewöhnlich wird immer ein git commit -a -mverwendet werden)
-m MESSAGE die commit message, welche in den log eingetragen wird
Als nächstes werden wir gleich unsere erste Datei in das repository einfügen,wollen davor aber noch kurz den aktuellen status des repository betrachten:
> git status
Hierauf wird git etwa folgendes antworten (je nach Spracheinstellung):
# On branch master## Initial commit## Untracked files:# (use "git add <file>..." to include in what will be committed)## READMEnothing added to commit but untracked files present (use "git add" to track)
Was dies im einzelnen bedeutet:
0. Wir befinden uns auf dem branch master (mehr zum Thema branching,s.u.)
1. Das repository ist noch vollständig “initial”, d.h. es wurden noch keineDateien hinzugefügt
2. Es gibt “untracked files”, also Dateien, die im Verzeichnis liegen, git abernicht bekannt sind. Diese Dateien können git auf zweierlei Arten bekanntsein0. Sie wurden dem repository hinzugefügt durch git add1. git wurde mitgeteilt diese Dateien im repository-Pfad zu ignorieren
(mit Hilfe der Datei .gitignore)3. wie die Dateien hinzugefügt werden können, sagt git auch gleich: durch
git add und zählt die ihm unbekannten Dateien auf (in diesem Falllediglich die Datei README).
Nun also zum Hinzufügen der ersten Datei:
Chapter8
gitlab
ImRahmenderEntwicklungvonWASTspieltdasselbst-gehostetegitlabdesCISuntereineganzentscheidendeRolle.
ZudenwesentlichenAufgaben,dieübergitlablaufen,zählt:
•dasZusammenfließendereinzelnenKomponenten•dieVersionierungmitgit•damitdieCode-Verwaltung•AccessControl:nichtjederdarfallesjederzeitverändern•KommunikationinnerhalbdesTeamsüberCode-spezifischeBelange•BugTracking(repositorywittgenstein-issues)•Code-Review:
a)codereviewvoncodedereinenbugfixdarstellt(vergleiche[BugTrackingWorkflow][]unddort:status:verify)
b)vonneuemcodedercommitedwird:mitgitlablassensichanderecodebaseseinfach“passiv”verfolgenundbequemHinweiseundKom-mentareaufZeilenebenegeben.
•nichtzuletztistdasgitlabderzentraleAnkerfürdieContinuousIntegra-tion.
85
176CHAPTER21.VERSIONIERUNG
Figure21.1:Gitoverview
86 CHAPTER 8. GITLAB 21.1. GIT 175
21.1.2.1 Überblick
Im Gegensatz zu svn gibt es bei git mehr Ebenen als nur “local repository” und“upstream repository”.
Abbildung 21.1 auf Seite 176 gibt ein Überblick7 über die unterschiedlichenEbenen und die Interaktion zwischen denselben:
21.1.2.2 Beispiel: Szenario 1: ein eigenes repository erstellen
Nachdem man seinen Namen und seine email-Adresse in git konfiguriert hat,kann man bereits beginnen, produktiv zu arbeiten.8
Nehmen wir als Beispiel ein Projekt genannt eos, das Satzende-Erkennung be-handeln soll.
Als erstes legen wir ein Verzeichnis an, in dem das Programm entwickelt werdensoll.
> mkdir eos && cd $_
Nun legen wir eine Datei README an, welche die wesentlichen Punkte des repos-itories erläutert:
> cat <<HERE >READMEeos---
an end-of-sentence recognizerHERE
Nun machen wir aus dem reinen Verzeichnis ein repository…
> git init
In diesem Befehl wird git ein (verstecktes) Verzeichnis .git in unserem Projektanlegen, also in eos/.git, in welchem es das repository verwaltet.
Als nächstes machen wir sogleich den ersten commit, um unserem repositoryeine “Geschichte” zu geben – ab hier beginnt nun also die Versionierung unseresProjekts:
7diese Graphik ist inspiriert von http://www.ndpsoftware.com/git-cheatsheet.html unddort interkativ mit Erklärungen zu den jeweiligen Ebenen und Interaktionen verfügbar
8Zu diesem Punkt ist u.a. diese Hilfe sehr gut geeignet: https://help.github.com/articles/set-up-git#set-up-git
Chapter9
ContinuousIntegration
Inhalt9.1Definition..........................879.2CI@CIS...........................899.3Referenzen.........................89
9.1Definition
UnterContinuousIntegration(CI)verstehtman:
ContinuousIntegrationisasoftwaredevelopmentpracticewheremembersofateamintegratetheirworkfrequently,usuallyeachpersonintegratesatleastdaily-leadingtomultipleintegrationsperday.Eachintegrationisverifiedbyanautomatedbuild(includ-ingtest)todetectintegrationerrorsasquicklyaspossible.Manyteamsfindthatthisapproachleadstosignificantlyreducedintegra-tionproblemsandallowsateamtodevelopcohesivesoftwaremorerapidly.ThisarticleisaquickoverviewofContinuousIntegrationsummarizingthetechniqueanditscurrentusage.1
Abbildung9.1aufSeite88verdeutlichtdenWorkfloweinerCI.
1http://www.martinfowler.com/articles/continuousIntegration.html
87
174CHAPTER21.VERSIONIERUNG
whenafilewasrenamed,addedordeletedetc)Gitdoesn’texplicitlytrackthisinformationinanywayatall.Itinsteadtrackscontentwithinarepository.BywalkingtherepositoryhistoryGitcanrecon-structwhathappenedtoaparticularfile,butthisisanextrapolationfromthedataratherthansomethingexplicitlyencoded.Thisisaradicaldeparturethatmeansthatwhenyoudosomethinglikecuttingamethodfromonefileandpastingitintoanotherthenthehistoryofthemethodgoesalongwithit(thinksvnblame).ThisisexplainedbyLinusTorvaldsinthispost;seealsothisseparatepostontrackingrenames.Firstoff,let’sjustpositthat“files”donotmatter.Theonlythingthatmattersishow“content”movedinthetree.Ok?IfIcopyafunctionfromonefiletoanother,theperfectSCMwillnoticethat,andshowitasadiffthatremovesitfromonefileandaddsittoanother,andisstillabletotrackauthorshippastthemove.5
21.1.1.5Lowbarriertoparticipation
NichtzuletzterlaubtesgitaufeinfachsteWeiseeineigenesvollständig-funktionierendescode-repositoryaufzusetzen.BeisvnwirdfürdiesenSchritteinservermitlaufendemsvnbenötigt–undistdamitzumeistaneinenAdministratorgebunden,z.B.umeinneuesrepositoryzuerstellen.
Eineinfachesgitinit--barereichtaus,umeinvollständigesgitrepositoryanzulegen,aufwelchesmanseineÄnderungenpushenundmitanderenkolla-borierenkann.ImEndeffektistdiesbereitseinkleiner“gitserver”–wennmansowill:
ItisincrediblyeasytostartmanagingcodewithGit.UnlikeSub-versionthereisnoneedtosetuparepositoryona(possiblyremote)serverbeforestartingtowork.GitisevensimplerthanSVK,be-causewhatwouldnormallybeconsidereda“workingcopy”actuallybecomesa(distributed)repositoryitself,containingboththe“work-ingcopy”andallofthehistoryoftherepository6
21.1.2gitbasics
UmschnellermitgitarbeitenzukönnenwerdenimfolgendendiewesentlichenerstenSchrittedetaillierterklärtunderläutert.AufjedenFallwirdempfohlen,weitereLiteraturzudiesenThemenzukonsultieren.
5https://wincent.com/wiki/Git_advantages6https://wincent.com/wiki/Git_advantages
88 CHAPTER 9. CONTINUOUS INTEGRATION
Figure 9.1: Continuous Integration
21.1. GIT 173
try new ideas without worrying about having to plan how and whenthey are going to merge it in or share it with others.There are ways to accomplish some of this with other systems, butthe work involved is much more difficult and error-prone. Git makesthis process incredibly easy and it changes the way most developerswork when they learn it.2
21.1.1.2 effizient, klein und schnell
Small and Fast Git is fast. With Git, nearly all operations areperformed locally, giving it a huge speed advantage on centralizedsystems that constantly have to communicate with a server some-where.Git was built to work on the Linux kernel, meaning that it has hadto effectively handle large repositories from day one. Git is writtenin C, reducing the overhead of runtimes associated with higher-levellanguages. Speed and performance has been a primary design goalof the Git from the start.3
21.1.1.3 verteilt
Distributed One of the nicest features of any Distributed SCM, Gitincluded, is that it’s distributed. This means that instead of doinga “checkout” of the current tip of the source code, you do a “clone”of the entire repository.Multiple Backups This means that even if you’re using a central-ized workflow, every user essentially has a full backup of the mainserver. Each of these copies could be pushed up to replace the mainserver in the event of a crash or corruption. In effect, there is nosingle point of failure with Git unless there is only a single copy ofthe repository.Any Workflow Because of Git’s distributed nature and superbbranching system, an almost endless number of workflows can beimplemented with relative ease.4
21.1.1.4 Content-tracking rather than file-tracking
Whereas every other version control system in the world tracks filehistory (when lines were added to a file, when lines were removed,
2http://www.git-scm.com/about/branching-and-merging3http://www.git-scm.com/about/small-and-fast4http://www.git-scm.com/about/distributed
9.2.CI@CIS89
9.2CI@CIS
DieWebseitefürdieCIamCISfindetsichunterhttps://gitlabci.cis.lmu.de/2.
InnerhalbderCIlassensichdannProjekte,dieimgitlabverfügbarsind,zuautomatisiertenTestshinzufügen.
Dafürgibtmanimwesentlichenan,wiedieSoftwarezutestenistunderhältdannnachjedempushvonÄnderungeninseinRepositoryautomatischdiesesgetestet.
DamitergibtsicheineguteRückversicherung–undnichtzuletzteinegutnachaußenhinsichtbareFrom,dasssämtlicheSoftwaresichineinem“ship-baren”,alsogesundenZustandbefindet.DasschafftVertrauenundistauchinnerhalbdesTeamshöchstpraktisch.
EineausführlicheAnleitungwiedieCIzubenutzenistfindetmanhier:https://gitlab.cis.lmu.de/schweter/cis-ci/tree/master(erreichbarüberhttps://gitlab.cis.lmu.de/public).
DerMaintainerderCIistStefanSchweter(schweter@cip.ifi.lmu.de)unddieCIumfasstderzeitetwa4virtuelleMaschinen(einbunterMixausDebian,Ubuntu,Suse,etc.)welchezufälligausgewähltwerdenunddieTestsausführen.Damitwirdsogarnocheinbisschen“Smoke-Testing”verhaltenemuliertundsichergestellt,dassdieinnerhalbvonWASTentwickelteSoftwareauchaufan-derenBetriebssysteminstallierbaristunddieTestsbestehen.
9.3Referenzen
DasThemaCIhängtengzusammenmitdenThemen:
•TestDrivenDevelopment•gitlab•Versionierung•[UnitTests]•IntegrationTests•BuildSysteme
2unbedingthttpsverwenden,sonstkannessein,dassmanvonhttpnichtweitergeleitetwirdaufhttps!
172CHAPTER21.VERSIONIERUNG
DiesenentscheidendenUnterschiedzubegreifenkanndurchauseinenMomentbrauchenunddieUmstellung,bismansichingitwirklich“zuHause”fühlt,kanneinenMomentdauern.
TrotzallemaberhatgitdieEntwickler-WeltimSturmerobertunddasausgutenGründen.
DieKombinationausgitundgitlabalsonline-Kollaborations-OberflächebieteteineMengeanüberzeugendenVorteilenfürdiegemeinsameEntwicklungvonSoftware,wieimfolgendenkurzdargestelltwerdensoll.
21.1.1Vorteilevongit
21.1.1.1branchingundmerging
Dasfreie“gitBook”1schreibtdazu:
TheGitfeaturethatreallymakesitstandapartfromnearlyeveryotherSCMoutthereisitsbranchingmodel.Gitallowsandencouragesyoutohavemultiplelocalbranchesthatcanbeentirelyindependentofeachother.Thecreation,merging,anddeletionofthoselinesofdevelopmenttakesseconds.Thismeansthatyoucandothingslike:FrictionlessContextSwitching.Createabranchtotryoutanidea,commitafewtimes,switchbacktowhereyoubranchedfrom,applyapatch,switchbacktowhereyouareexperimenting,andmergeitin.Role-BasedCodelines.Haveabranchthatalwayscontainsonlywhatgoestoproduction,anotherthatyoumergeworkintofortest-ing,andseveralsmalleronesfordaytodaywork.FeatureBasedWorkflow.Createnewbranchesforeachnewfeatureyou’reworkingonsoyoucanseamlesslyswitchbackandforthbetweenthem,thendeleteeachbranchwhenthatfeaturegetsmergedintoyourmainline.DisposableExperimentation.Createabranchtoexperimentin,realizeit’snotgoingtowork,andjustdeleteit-abandoningthework—withnobodyelseeverseeingit(evenifyou’vepushedotherbranchesinthemeantime).Notably,whenyoupushtoaremoterepository,youdonothavetopushallofyourbranches.Youcanchoosetosharejustoneofyourbranches,afewofthem,orallofthem.Thistendstofreepeopleto
1http://www.git-scm.com/book
90 CHAPTER 9. CONTINUOUS INTEGRATION
Chapter 21
Versionierung
Inhalt21.1 git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
21.1.1 Vorteile von git . . . . . . . . . . . . . . . . . . . . . 17221.1.2 git basics . . . . . . . . . . . . . . . . . . . . . . . . . 17421.1.3 git-extras . . . . . . . . . . . . . . . . . . . . . . . . 187
In praktisch jedem Software-Projekt ist Versionskontrolle unerlässlich um Sicher-heit zu garantieren und Übersichtlichkeit zu wahren.
Hinsichtlich der Auswahl von Versionskontrollsystemen gibt es eine Vielzahl vonProdukten, die sich verwenden lassen:
• cvs• svn• mercurial• bitkeeper• git
21.1 git
Die meisten Teile der WAST-Landschaft sind mit git versioniert da dieses Sys-tem die meisten Vorteile bietet.
Als beliebteste Versionskontrollsysteme sind natürlich svn und git zu erwäh-nen. git ist ein “version control system (vcs)” wie svn, bzw. ein source controlmanagement System (scm), mit dem entscheidenden Unterschied, dass es imGegensatz zu svn ein verteiltes (distributed) vcs ist.
171
Chapter10
BuildSysteme
Inhalt10.1make.............................9210.2cmake............................92
10.2.1Motivation........................9210.2.2vs.autotools(autotool-hell)..............9310.2.3out-of-source-builds...................9310.2.4Wichtigeoptionenfürcmake..............9310.2.5Beispiel.........................95
10.3rake.............................9610.4gyp..............................97
MakefilesunddasdazugehörigeProgrammmakewerdeninderSoftware-EntwicklungseitjeheralsBuild-Systemeverwendet.Build-SystemebeschreibenjedeneinzlnenSchritteinesBuild-ProzessesundführendieseaufintelligenteArtundWeisesoaus,dassmöglichstwenigeSchritteausreichen,umeinenfunktionierendenbuildzugarantieren.DaBuild-ProzessebeigrößerenProjekteneinigeZeitbeanspruchenkönnen(mehrereStundensindhiernichtausgeschlossen)undesbeimdebuggensehrunpraktischwäre,nachjederÄnderungeinenkomplettenBuild-Prozessabzuwarten,machtmansichandieserStellesowohlEigenschaftenvonCundC++(Object-Files,TrennungvonHeaderundImplementationinunter-schiedlicheDateien,sharedundstaticlibs,…)alsauchdasintelligenteVorgehenvonMakefileszuNutze,umdieentsprechendenWarte-Zeitenabzukürzen.MakefilesbildenstetseinenPfadvonAbhängigkeiten,welcheschrittweiseaufzulösen/abzuarbeitensind,umzumnächstenZielkommenzukönnen.Dabeidienendiesog.targetsalsdieZieleunddieDefinitiondiesertargetsalsdiezuabsolvierendenSchritte(häufig“recipes”genannt).
91
170CHAPTER20.BUGTRACKER
92 CHAPTER 10. BUILD SYSTEME
Hinzu kommt, dass sich die Bearbeitungszeiten der Dateien nutzen lassen, umfestszustellen, ob – zum Beispiel – ein Object-File neu gebildet werden musss,oder nicht.
10.1 make
make ist, wie bereits erwähnt, der Platzhirsch und der Standard unter den Build-Systemen. Allerdings können Makefiles schnell komplex und unübersichtlichwerden, weshalb man sog. “Makefile-Generatoren”, wie z.B. cmake oder gypverwendet, um sich die entsprechenden Makefiles generieren zu lassen und diesenicht selbst schreiben und verwalten zu müssen.
Bis zu einer gewissen Größe und für eine breite Palette von Aufgaben lassen sichMakefiles ganz hervorragend und gewinnbringend einsetzen – nicht zuletzt, dasie auf so gut wie jedem System vorhanden sind.1
Eine Einführung zu GNU make findet sich unter https://www.gnu.org/software/make/manual/make.pdf; vergleiche u.a. auch das Makefile zumErstellen dieser Dokumentation.
10.2 cmake
cmake2 ist ein Betriebssystem-unabhängiger Makefile-Generator für C- undC++-Projekte. Das heisst, man benutzt cmake, um ein Makefile zu generieren.cmake kann als “Industriestandard” für C- und C++-Projekte betrachtetwerden.
Der Workflow mit cmake funktioniert also folgendermaßen:
cmake DIRmake
Dazu verteilt man (mindestens eine) CMakeLists.txt-Datei (potentiell rekur-siv) im Projekt, welche die Deklarationen zu Targets, Libraries, etc. enthält undteilt cmake durch die Angabe DIR mit, wo sich diese Datei befindet. Danachwird ein Makefile zur Verfügung stehen, welches man mit make aufrufen kann.
10.2.1 Motivation
cmake zu verwenden bringt mehrere Vorteile:1Dieses Skript zum Beispiel wird ebenfalls durch ein Makefile gesteuert: dazu gehören
neben dem Typesetten auch das Hochladen auf den webspace und andere Aufgaben.2http://www.cmake.org/
20.2. WAST-WORKFLOW 169
den referenzierten Bugs dieses automatisch von gitlab eingetragen: ‘this bugwas mentioned in bug XY’. Dies ist ziemlich praktisch.
10.2.CMAKE93
a)dieSyntaxvoncmakeisteinfacheralsdievon“klassischen”Makefilesb)dadurch,dassdieCMakeLists.txt-Dateienrekursivaufeinanderaufbauen
undjeweilsangeeignetenStellenimProjektuntergebrachtwerden,bleibendiesestetsübersichtlich
10.2.2vs.autotools(autotool-hell)
cmakewirdvorallemdeshalbgerneverwendet,weilder“klassische”autotools-Wegsehrumständlich,fehleranfälligundschlicht“altbacken”seinkann–siehehierzudenAblaufgraph“Autotools”,welcherdenautotools-Wegnachzeichnet.
autotoolsfasstwiederumdenbisdahinverwendetenWegunddiedazubenötigtentoolszusammen,diebenutztwurdenumMakefilesgenerierenzulassen.Denautotools-Wegerkenntmanimmerdaran,dasseineSoftwareden“klasssischenDreischritt”./configure&&make&&makeinstallverwendet.
10.2.3out-of-source-builds
Klassischerweiseverwendetmanbeicmakeinsog.“out-of-sourcebuilds”.Ein-fachgesagt,heisstdiesnur,dassmanseinenBuildnichtdirektindersourcemacht,sonderndafüreineigenesVerzeichnis(meistbuild/)anlegt,undfortanvondortarbeitet.
Damitvermeidetmandas“Vermüllen”dessource-directoriesmitObject-FilesunddergleichenundhältsodieQuellenstetssauber.
DerWorkflowistalso:
~/project/foo>mkdir-pbuild&&cd$_#Hierliegtu.a.src/mitdenQuellenund(mindestens)einerCMakeLists.txt~/project/foo/build>cmake..#`..`istübergeordnetesVerzeichnis!~/project/foo/build>make#build-fileswerdenout-of-sourceangelegt!
10.2.4Wichtigeoptionenfürcmake
DiebeidenwitchtigstenOptionenfürcmakesind:
•-DCMAKE_CXX_COMPILER=/opt/local/bin/g++#VerwendespeziellenCompiler•-DCMAKE_BUILD_TYPE=Debug#Buildtypefestlegen(andereSwitchesfürden
Compiler)
Diesegibtmancmakemit,dasdannentsprechenddieMakefilesgeneriert:
cmake-DCMAKE_CXX_COMPILER=/Users/dbruder/bin/g++-DCMAKE_BUILD_TYPE=Debug..
168CHAPTER20.BUGTRACKER
Figure20.1:BugTrackingWorkflowStatus
94 CHAPTER 10. BUILD SYSTEME
Figure 10.1: Autotools
20.2. WAST-WORKFLOW 167
Priorität Label Charakterisierung Beschreibung
1 P1 Showstopper. Muss sofort behoben werden.Kritischer Bug.
2 P2 Wichtiger Bug. Sollte ebenfalls schnellstmöglichbehoben werden. Wichtiger Bug.
3 P3 Durchauswichtiger Bug.
Durchaus wichtiger Bug, aber nichtunbedingt wesentlich solange nochP1 und P2 Bugs vorliegen. Könnenauch Feature Requests sein, die dannzumeist zu P4-Bugs werden.
4 P4 Nicht so wichtigerBug.
Meist “Nice To Have” FeatureRequests oder wird häufig vergebenfür “Next Release/Milestone”, d.h.dieses Feature wird wohl erst imnächsten Milestone umgesetztwerden.
Table 20.1: Prioritäten bei Bugs
20.2.3 Workflow
Der Workflow orientiert sich an folgendem Modell: Der Bug geht durch ver-schiedene Phasen, die unterschiedliche Bedeutung haben. Diese werden immerper tag signalisiert. So können andere ablesen, dass jemand an einem bug ar-beitet. Abbildung 20.1 fasst dies zusammen.
20.2.4 Spezialität: Umbrella-Bug
Wenn es mehrere “related” Bugs zu einem größeren Thema gibt, so bietet essich an einen umbrella-Bug zu definieren, der alle diese verstreuten, kleinerenBugs zusammenfasst und miteinander referenziert. Die wird am Einfachsten sogehandhabt, dass:
• der umbrella-Bug bekommt einen tag ‘umbrella’• der umbrella bug bekommt eine Bezeichnung/Beschreibung ‘umbrella bug’• der umbrella bug referenziert die die related-bugs, indem er tags bekommt
mit den bug-id’s der related bugs, also, z.B. ‘#19, #22, #53’. Damit wäreklar, dass der umbrella-bug die bugs mit den Nummern 19, 22 und 53zusammenfasst
Wenn man in der Beschreibung des Umbrella Bugs eine kleine Beschreibunganlegt, die sagt ‘this is an umbrella bug for bugs #19, #22, #53’, so wird in
10.2.CMAKE95
10.2.5Beispiel
HiereinAuszugausdenCMakeLists.txt-DateiendesProjektssis:
project(sis)cmake_minimum_required(VERSION2.8.3)set(sis_AUTHORS"\"DanielBruder<bruder@cip.ifi.lmu.de>\"")
set(sis_NAME"\"SIS\"")set(sis_SUBNAME"\"SymmetricIndexStructures\"")set(sis_FULLNAME"\"SIS--SymmetricIndexStructures\"")
#versionnumbers:lassensichgutindoxygenetcverwendenset(sis_VERSION_MAJOR3)set(sis_VERSION_MINOR8)set(sis_VERSION_PATCH0)
set(CMAKE_INSTALL_PREFIX/usr/local)set(FIND_LIBRARY_USE_LIB64_PATHS)
#dieseVariablenkönnenaufderCommandlinemit-Dgesetztwerdenset(sis_BUILD_TESTSON)set(sis_TEST_STATIC_ASSERTIONS0)#0=='OFF'/0=='ON'set(GIT_SUBMODULES_CHECKOUT_QUIETON)
set(CONF_DIR${PROJECT_SOURCE_DIR}/cmake)
include(${CONF_DIR}/config.cmake)include(${CONF_DIR}/compilerdetect.cmake)include(${CONF_DIR}/processorcount.cmake)include(${CONF_DIR}/buildflags.cmake)include(${CONF_DIR}/doxygen.cmake)include(${CONF_DIR}/boost.cmake)include(${CONF_DIR}/ctest.cmake)include(${CONF_DIR}/cpack.cmake)include(${CONF_DIR}/host.cmake)include(${CONF_DIR}/checklocale.cmake)include(${CONF_DIR}/submodules.cmake)include(${CONF_DIR}/githooks.cmake)include(${CONF_DIR}/nodewrap.cmake)
add_subdirectory(src/)add_subdirectory(src/features)add_subdirectory(vendor/)add_subdirectory(web/)
ImVerzeichnissrc/findetsichfolgendescmake-file:
#DieseVerzeichnissemit-IandenCompileralsSuchpfademitgebeninclude_directories(${CMAKE_SOURCE_DIR}/src/)
166CHAPTER20.BUGTRACKER
•Vererbbarkeit:WennsichdieZusammensetzungderTeamsändert,kön-nennachfolgendeEntwicklersichschnellundklareinenÜberblicküberdieausstehendenProblemeundbisherigenLösungenverschaffen.
20.2WAST-Workflow
ImfolgendeneineBeschreibungderKonventionenundVorgänge,wiebugsin-nerhalbvonWASTgehandhabtwerdensollen.
20.2.1Konventionen
Bugssollenordentlichdokumentiertwerdenundgetaggedwerden.Taggenerlaubtes,dieoffenenbugszusortieren,filternunddamitbesserimÜberblickbehaltenzukönnen.Ordentlichdokumentierenbedeutet,dasseinnachfolgendergenaunachvol-lziehenkann,wie/wann/wermiteinemBugumgegangenwurde.Dazugehören:
•taggen:priorisieren(sieheunten,Prioritäten)•taggen:Status(sieheunten,Workflow)•dokumentieren:WennsichderStatuseinesBugsändert,ambesteneinen
KommentarimBug-Verlaufhinterlassen,ambestenso:–Beispiel:[Issued->Analyze].Dieswürdebedeuten,dasssich
PersonFoomitdemBugauseinandersetztunddentagIssuedent-ferntunddurchdentagAnalyzeersetzthat.Diesbedeutetfüralleanderen,dass:*sichbereitsjemandumdenBugkümmert*anderekönnendienochoffenenbugsbequemfilternundsehen,wasalsnächsteszutunist
–Beispiel:[p1->p2].*Bedeutet:PersonFoohatdenBugherunterpriorisiertvonP1nachP2
*Beispiel:[+p1]·Bedeutet:PersonhatP1-tagandenBughinzugefügt
20.2.2Prioritäten
BugssindambestenPriorisiertvon“P1”bis“P4”.DiePrioritätenentsprechenungefährfolgendenIdeen:
96 CHAPTER 10. BUILD SYSTEME
# Diese Verzeichnisse mit -isystem (oder nach OS abhängig) an den Compiler als Suchpfade mitgeben. -isystem bindet "externe" Header so ein, dass diese keine Warnings werfen.include_directories(SYSTEM
${CMAKE_SOURCE_DIR}/vendor/${CMAKE_SOURCE_DIR}/vendor/cautomata${CMAKE_SOURCE_DIR}/vendor/make_unique${CMAKE_SOURCE_DIR}/vendor/serialization/include
)
# Shared lib bauenadd_library(cppautomataadapter SHARED
adapter/CompressedAutomatonAdapter.cppadapter/SCDAWGAdapter.cppadapter/VoidSequenceAdapter.cpp
)target_link_libraries(cppautomataadapter cautomata)
add_library(cppindexer SHAREDindexer/DocumentIndexingAutomaton.cpp
)target_link_libraries(cppindexer cppautomataadapter cautomata)
add_executable (sis main.cpp)target_link_libraries(sis cppautomataadapter cppindexer cautomata ${Boost_LIBRARIES})
10.3 rake
rake3 ist ein kleines aber feines Build-Tool, das hier als eine Alternative zu makekurz vorgestellt werden soll. rake ist und wird in Ruby geschrieben und ist aufden meisten Systemen, die ruby mitliefern, enthalten.
rake ist aber nur eine von sehr vielen Alternativen zu make! Es gibt vieleweitere, ähnliche Tools, doch nur eines, nämlich make kann als echter “Standard”angesehen werden. Nicht zuletzt aber lohnt sich ein Blick auf make: unterUmständen lässt sich make durch diesen kleinen Umweg schneller und einfacherverstehen…
Rake ist – im Gegensatz zu cmake – aber kein Makefile-Generator und kannfolglich (leider) keine makefiles generieren!
3http://rake.rubyforge.org/
Chapter 20
Bug tracker
Inhalt20.1Motivation . . . . . . . . . . . . . . . . . . . . . . . . . 16520.2WAST-Workflow . . . . . . . . . . . . . . . . . . . . . . 166
20.2.1 Konventionen . . . . . . . . . . . . . . . . . . . . . . 16620.2.2 Prioritäten . . . . . . . . . . . . . . . . . . . . . . . . 16620.2.3 Workflow . . . . . . . . . . . . . . . . . . . . . . . . 16720.2.4 Spezialität: Umbrella-Bug . . . . . . . . . . . . . . . 167
20.1 Motivation
Der Bug-Tracker dient der gemeinsamen Verwaltung von Bugs und der Version-ierungObwohl eigentlich einleuchtend und selbstverständlich haben “ordentliche” Bug-Tracking best practices eine Reihe entscheidender Vorteile:
• Transparenz: Alle Mitarbeiter haben einen genauen Überblick über denStand des Projekts / der einzelnen Komponenten
• Milestones und wesentliche Entwicklungsschritte über Komponenten hin-weg können besser erreicht werden, das gesamte Projekt sich schneller en-twickeln
• Genauigkeit: Durch die Transparenz und das Wegfallen von“Flüsterpost-Ketten” ist es wesentlich einfacher sich gemeinsam zukoordinieren
• Genaue Rückgabe: Es ist zu jedem Zeitpunkt klar, was man denPhilsophen gegenüber geliefert hat / was noch aussteht / wer geradeworan arbeitet.
165
10.4.GYP97
10.4gyp
gyp(GenerateYourProjects)4isteinMakefile-Generator,dervonGooglefürdenBuild-ProzessvonChromeentwickeltwurde.ErwirddesweiterenauchfürdenbuildvonNode.jsverwendet(wasanandererStellewichtigwird–hierwerdenwirgypwiederbegegnen).gypistalsoeinbuild-automationtoolähnlichzucmake,gegenübercmakeaberwerdendieTargetsingyp-filesalsJSON-Strukturbeschrieben–hiereinBeispielfüreingyp-file:
1{2'targets':[3{4'target_name':'foo',5'type':'executable',6'msvs_guid':'5ECEC9E5-8F23-47B6-93E0-C3B328B3BE65',7'dependencies':[8'xyzzy',9'../bar/bar.gyp:bar',
10],11'defines':[12'DEFINE_FOO',13'DEFINE_A_VALUE=value',14],15'include_dirs':[16'..',17],18'sources':[19'file1.cc',20'file2.cc',21],22'conditions':[23['OS=="linux"',{24'defines':[25'LINUX_DEFINE',26],27'include_dirs':[28'include/linux',29],30}],31['OS=="win"',{32'defines':[33'WINDOWS_SPECIFIC_DEFINE',34],35},{#OS!="win",36'defines':[37'NON_WINDOWS_DEFINE',38],
4https://code.google.com/p/gyp/wiki/GypUserDocumentation
164CHAPTER19.TESTDRIVENDEVELOPMENT
98 CHAPTER 10. BUILD SYSTEME
39 }]40 ],41 },42 ],43 }
19.2. ARTEN VON TESTS 163
wurde, sind diese einzelnen Klassen bereits durch die Unit-Tests in sich getestet.Der Integration Test nun testet diese einzelnen Kompomeneten in ihrem Zusam-menhang, ihrer Kooperation etc. Diese Art von Tests wird aber zumeist eherab einer umfangreicheren Größe des Projekts benötigt.
19.2.3 Sanity Tests
Neben Unit- und Integration-Tests gibt es auch noch die sog. Sanity-Tests.Diese Art von Tests validiert und prüft User-Eingaben, Datentypen und ähn-liches auf korrekte Werte.
19.2.4 E2E Tests
E2E-Tests, bzw. End-to-end-tests sind sehr ähnlich zu Integration Tests, indemsie das Zusammenspiel der einzelnen Komponenten prüfen, haben aber eher einkonkretes Interaktions-Szenario des Benutzers im Blick: oft werden e2e Testsin Web-Frameworks und in der Entwicklung von Webseiten verwendet, um einkomplettes “Szenario” der Benutzer-Interaktion durchzuspielen und zu prüfen,ob dieses von Anfang bis Ende fehlerlos ablaufen kann.
Beispiel:
• User geht auf Seite• User sucht etwas• User klickt ein Ergebnis an• User wird auf Seite des Ergebnisses geleitet• User will dort eine Eingabe machen• User muss angemeldet sein• User meldet sich an• User is angemeldet• User kann Eingabe machen• User kann Eingabe speichern• …
Chapter11
Web
Inhalt11.1Web-Applikationen....................99
11.1.1SchematischeDarstellung...............10011.1.2UnterschiedlicheKombinationsmöglichkeiten.....101
11.2MEAN-Stack........................10211.2.1Vorteile.........................10311.2.2Node...........................10411.2.3Angular.........................10411.2.4Express.........................10411.2.5MongoDB........................104
11.3Jade.............................10511.3.1Bootstrap........................10511.3.2BootstrapUI......................10511.3.3jQuery..........................105
IndiesemKapitelwerdendiewesentlichenZügevonWeb-Applikationenvorgestellt(dazuzählenClient-Server-KonfigurationenundKommunikation),undamBeispieldes[MEAN-Stack][DerMEAN-Stack]einkonkretes,sehrmodernesFrameworkzumErstellenvonSPAs(SinglePageApplications),bzw.RichClientWebApplicationsvorgestellt.WesentlichbeidiesenistdasdynamischeLadenvonSeiten-Bestandteilen,stattdemkomplettenReloaddergesamtenSeite.
11.1Web-Applikationen
ModerneWeb-ApplikationenfunktionierenimAllgemeinennachwenigen,wesentlichenPrinzipien.InwelcherArtundWeisediesekonkretausgestaltetwerden,isteineandereFrage–dieBasicsjedochbleibendieselben.
99
162CHAPTER19.TESTDRIVENDEVELOPMENT
classstringAppendFeature{EXPECT(
stringAppendFixture::teststring1_append_in.append('c')==stringAppendFixture::teststring1_append_out
);
//hiergibtesschondenzweitenTestfall!EXPECT(
stringAppendFixture::teststring2_append_in.append('c')==stringAppendFixture::teststring2_append_out
);//weiteretestsderSpezifikation...
};
ErfülltderTestdieSpezifikation?WaswäredennnunmitdemFall,dassderStringauf\nendet?Solldercharchinterdem\nangefügtwerden,dasnewlinemöglicherweisekomplettersetzen,odersichwomöglichvordasnewlineeinsetzen?EinTestwirdKlärungbringen,und,enpassantdieSpezifikationderKlassestringfestigen!SeidieSpezifikationnunerweitertumfolgendeRegel(n):
1.esgibteineKlassestring2.string::append(charc)solleinenBuchstabenandenbestehenden
Stringanfügen3.wennderstringleerist,sollderneuestringausdemangefügtenBuch-
stabenbestehen(imPrinzipnureinSpezialfallvon2.)4.wennderStringaufeinnewlineendet,solldercharactervordemnewline
einfügtwerdenunddasnewlineanletzterStellebehaltenwerden
DieTestskönntennunerneutrefactoredwerdenundfolgendesergeben:
classstringAppendFixture{std::map<string/*input*/,string/*output*/>fixture{{"foobar","foobarc"},{"","c"},{"foobar\n","foobarc\n"},
};};
classstringAppendFeature{conststringAppendFixtureF;
for(constauto&f:F.fixture){EXPECT(f.first==f.second);
}};
19.2.2IntegrationTests
IntegrationTeststestenindenmeistenFällendasZusammenspielvoneinzel-nenKlassenoderSoftware-Komponenten.WieimvorherigenAbschnittgezeigt
100 CHAPTER 11. WEB
11.1.1 Schematische Darstellung
Figure 11.1: Web Apps Basics
11.1.1.1 Ablauf der Aktionen
• Anfrage (1) vom Client (B) an den Server (A)• Anfrage (2) des Servers (A) an die Datenbank (C)• …
11.1.1.2 Aktionsarten
Die genannten Aktionen können unterschiedlicher Art sein:
Anfrage (1) kann – nach dem HTTP-Protokoll unterschiedliche Methoden haben:
• GET• POST• PUT• UPDATE• DELETE
19.2. ARTEN VON TESTS 161
19.2.1.1 Features/Fixtures
Angenommen, es gibt eine Klasse string, und diese Klasse soll eine Methodeappend(char c) besitzen, welche einen Buchstaben an den String anhängt.
Die Spezifikation sagt also:
• es gibt eine Klasse string• string::append(char c) soll einen Buchstaben an den bestehenden
String anfügen
Die Fixture enthält vorgegebene Eingaben und die erwarteten Aus-gaben/Rückgabewerte. Die stringAppendFixture wird genau dieses verhaltenabbilden:
In einer schematischen Darstellung:
class stringAppendFixture {string teststring1_append_in = "foobar";string teststring1_append_out = "foobarc";
};
Jede Fixture ist einem Feature zugeordnet. Das Feature ist ein kleiner Testfall,der die Funktionen der getesteten Klasse verwendet, die Eingaben der Fixturean diese füttert und die Rückgaben anhand der Fixture überprüft.
Die Klasse stringFeature wird also die Spezifikation von string::appendprüfen (erneut in schematischer Darstellung):
class stringAppendFeature {EXPECT(
stringAppendFixture::teststring1_append_in.append('c')== stringAppendFixture::teststring1_append_out
);// weitere tests der Spezifikation...
};
Diese Sorte von kleinen Tests zu schreiben ist sehr einfach und dabei aberhochgradig effektiv!
Bald nämlich wird einem auffallen, dass es sinnvoll wäre, zu testen, was passiert,wenn der string vorher leer ist:
class stringAppendFixture {string teststring1_append_in = "foobar";string teststring1_append_out = "foobarc";string teststring2_append_in = "";string teststring2_append_out = "c";
};
11.1.WEB-APPLIKATIONEN101
DieAnfragenvomTyp(1)vomClient(B)andenServer(A)richtensichimmernacheinerbestimmtenRouten.
DerServerbestimmt,wieseineAPIgestaltetist,undreagiertentsprechendaufAnfragenanbestimmteRouten.
Anfragenkönnensein:
DerServer(A)kannaufAnfrage(1)imSchritt(4)mitunterschiedlichenTypenvonRessourcenantworten(selbstverständlichwird(B)diesen“richtig”anfragen,bzw.genaudieseErgebnisseerwarten):
•GET-AnfragenacheinerstatischenHTML-SeiteaufeinembestimmtenPfad,serverkanndiesedirektausliefern
•GET-AnfragenacheinerRessource(möglicherweisevoneinerDatenbank,oderausanderenQuellen),serverkannJSONliefern
•POSTaufeinebestimmteRoute:ServersolldieimPOSTgesendetenDatenirgendwohinpacken
DERHTTP-StandardunterstützttheoretischnochmehrAnfrage-Methoden,allerdingssinddiesedefactoaberkaumbisgarnichtumgesetzt(dienichtumgesetztenMethodenlassensichgutGETundPOSTemulieren)
DieSchritte(3)und(4)sindoptional.DerTypderDatenbankistauchnichtfestgelegtundesgibtimwesentlichen2TypenvonDatenbanken:
•Relationale(SQL-Datenbanken)•Nicht-Relationale(NOSQL-Datenbanken),Dokumentorientert,meist
eigentlichsehrJSON-artig
InSchritt(5)sendetderServerseineAntwortaufAnfrage(1),diesekann,wiegesehen,eineHTML-Seitesein,JSON,oderetwasanderes.AndiesemPunktistesAufgabedesClient,dieseAntwortentsprechendzuverarbeiten.
11.1.2UnterschiedlicheKombinationsmöglichkeiten
HiereinekleineListe,wasanwelchenStellenmöglicherweisevorkommenkönnte–dieseListeistbeiweitemnichtexhaustiv!
11.1.2.1Server
AlsServerkönnenunterschiedlicheSoftware-KomponenteninBetrachtkommen.EinServerliefertimwesentlichenDatenaus(er“serve-d”):
•Apache
160CHAPTER19.TESTDRIVENDEVELOPMENT
TestDrivenDevelopmentgehtdabeieinenzunächstungewöhnlicherscheinendenWeg:eswerdenzuerstdie(failenden)Testsgeschrieben,unddanacherstdiedazupassendeImplementation(alsodieImplementation,diedenTest“pass”-enlässt).
DerWorkflowimTDDistalsokurzgesagtfolgender:
1.Testschreibendernichtklappenwird2.PassendeImplementationschreiben,diedenTestklappenlässt3.Abhier:wiederbei1)beginnen
InteressanterweiseerlaubtTDDzumeisteineschnellereEntwicklungimProjekt,einelangfristiggesehenstabilere,ausgereiftereundnachhaltigereCode-BaseundmachtdabeiauchnochSpaß.
Obwohleszunächstparadoxerscheinenmag,sogibteszwareinenklarenMehraufwand,zuerstdieTestsunddanachdieImplementationzuschreiben,durchdasvorherigeschreibenderTestsaber
•wirddieSpezifikationnocheinmalgenauerüberdacht,•liegtdieSpezifikationauchinkonkreterFormvor:spätereEntwickler
sehenTeiledesCodes“live”inderVerwendung•liegendieTest-Fällebereitsvor•machtmansichbereitsimplizitGedankenüberdiespätereAPIundVer-
wendungder(nochzuschreibendenKlasse)•Könnenedge-caseswesentlichbessererkanntunddaherauchgetestetwer-
den
19.2ArtenvonTests
Zumeistsinddiesog.Unit-Testsdiewichtigsten,beieinemgrößerenProjektwiediesemjedochistesdenkbar,volleIntegrationTests,Sanity-Tests,etc.paratzuhaben.
19.2.1Unit-Tests
EinUnit-TestbildetklassischerweisedieFunktionalitäteinerKlasseineinerIsoliertenArtundWeiseab.
IdealerweisebildetderUnit-TestzueinerKlassezugleichauchihreSpezifikationabundprüftdieseanhandderFixturesdurch.
102 CHAPTER 11. WEB
• IIS• nginx• lighttpd• unicorn• Node• …
11.1.2.2 Client
• Browser: Firefox, Chrome, Chromium, Safari, IE, …• curl, wget, …
11.1.2.3 Datenbank
Wie bereits erwähnt gibt es unterschiedliche Typen von Datenbanken und imwesentlichen SQL-orientierte und NO-SQL-orientierte:
• SQL-orientierte Datenbanken
– MySQL– PostgreSQL
• NoSQL-orientierte DB:
– MongoDB– CouchDB– Redis
• Graph-orientierte Datenbanken:
– Neo4j– viele andere…
11.2 MEAN-Stack
Der MEAN-Stack ist ein Framework für die Entwicklung von modernen Web-seiten – ähnlich wie das bekanntere “Ruby on Rails”. Diese neue Generation vonWebseiten ist auch als “SPA” (Single Page Web-Applications) oder “Rich ClientWeb Applications” bekannt und unterscheidet sich von “herkömmlichen” Web-seiten dadurch, dass stets nur einzelne Teilbereiche einer Webseite neu geladenwerden anstatt durch eine Reihe von Seiten “vorwärts und rückwärts” zu gehenund diese jeweils komplett zu laden. Rich Client Web Applications fühlen sichwesentlich “applikationshafter” an als “herkömmliche” Webseiten und zeichnensich nicht zuletzt dadurch aus, dass mehr Arbeit, die klassicherweise auf dem
Chapter 19
Test Driven Development
Inhalt19.1Motivation und Vorteile . . . . . . . . . . . . . . . . . 15919.2Arten von Tests . . . . . . . . . . . . . . . . . . . . . . 160
19.2.1 Unit-Tests . . . . . . . . . . . . . . . . . . . . . . . . 16019.2.2 Integration Tests . . . . . . . . . . . . . . . . . . . . 16219.2.3 Sanity Tests . . . . . . . . . . . . . . . . . . . . . . . 16319.2.4 E2E Tests . . . . . . . . . . . . . . . . . . . . . . . . 163
19.1 Motivation und Vorteile
Die Vorteile von Test-geleiteter Entwicklung sind mannigfaltig. Unter anderemerlaubt eine Test-Suite folgendes:
• Es ist einfach nach der Kompilierung einen sogenannten “Sanity-Test” zumachen, um zu überprüfen, ob alle Teile auf dem target-host genau sofunktionieren wie sie es auf der Entwicklungsmaschine getan haben undalle Teile richtig kompiliert wurden und verfügbar sind
• Es ist einfach, später neue Funktionalitäten einzubauen, da stets dasSicherheitsnetz besteht, zu sehen, ob die Veränderung am Code möglicher-weise an anderer Stelle einen Fehler auslöst
• Es ist wesentlich einfacher, sein eigenes Programm zu debuggen, und manbenötigt wesentlich weniger sog. “printf-debugging”, da die (vielen kleinen)tests mögliche Fehler sehr gut lokalisieren und eingrenzen. In den meistenFällen wird durch gute (d.h. viele kleine) Tests die Ursache des Problemssehr schnell ersichtlich und es wird einem mühsames “dem Code hinter-hersteigen” erspart.
159
11.2.MEAN-STACK103
ServergemachtwurdeaufdenClient–alsodenBrowserdesBeutzersausge-lagertwird.GenaugenommenistderMEAN-StacknichteinFramework,sonderndieKom-binationmehrerer,kleinererFrameworks,SchichtenundModulezueinemsoge-nanntenstack.
11.2.1Vorteile
EntscheidenderVorteildesMEAN-StacksgegenüberRubyonRailssindu.a.folgende
•mankanndurchalleTeilehinwegstetsnurinJavascriptbleiben•dieWebseitensindwesentlichperformanterunddieLoadaufdemServer
bleibtwesentlichgeringer•dieSub-Komponenten(diegleichbesprochenwerden)sindjeweilsgegen
andereaustauschbar:indiesemSinnehandeltessichumeinenStack:mankannfürdiejeweiligenAufgabendurchausauchandereModulezumEinsatzbringen
•esgibtwenigerKonventionenundeinenfreierenAufbau(dieskannsowohleinVor-alsaucheinNachteilsein)
HierbeistehendieInitialenfürfolgendeTeile,welche–ganzgrobumrissen–,folgendeAufgabenübernehmen:
•MongoDB1–Datenbank•Express2–FrameworkaufbauendaufNode,fürdieServer-Seite•Angular3–fürdieClient-Seite•Node4–derWebserver(ähnlichwie,aberstattApache,nginx,unicorn,
…)
WieobenangedeutetließensichdieeinzelnenKomponentendesStackauchdurchandereKomponentenaustauschen–dazuimfolgendeneinekleineAufzäh-lung,welcheAlternativen(untervielenvielenmehr)potentiellbestehenkönnten–hierbeiwerdenvielleichtauchdieAufgabendereinzelnenKomponentendeut-licher:
•MongoDB:mysql,postgresql,redis,couchDB,…•Express:koa,puresNode,…•Angular:jQuery+php,ember.js,sails.js,…•Node:Apache,nginx,unicorn,foreman,…
1MongoDB(2014)2expressjs(2014)3Google(2014)4node(2014)
104 CHAPTER 11. WEB
11.2.2 Node
Node5 wird verwendet um einen eigenen Webserver selbst zu schreiben. Node istein unglaublich schneller Webserver und ein funktionsfähiger eigener Webserverlässt sich in Node bereits mit wenigen Zeilen schreiben.
Da am Ende Webseiten über eine normale WWW-Adresse ausgeliefert werdensollen und meistens ein Apache auf dem Server bereits läuft und auf dem HTTP-Port 80 “listened”, kann dieser Port nicht erneut belegt werden. Node machtdaher seinen eigenen Port auf, z.B. 6688, was aber wiederum bedeuten würde,dass der user die seite auf diesem Port ansteuern müsste, z.B. webseite.com:6688.
Für diesen Fall wird zumeist ein sog. “Reverse Proxy” im Apache eingerichtet,der alle unterschiedlichen Services und Webserver die möglicherweise sonst nochauf dem Server laufen zusammenfasst und eine einheitliche Oberfläche nachaußen bietet (d.h. keine expliziten Port-Angaben vom User verlangt, die ihnohnehin nur verwirren würden). Bei einem Reverse-Proxy wird Apache mit-geteilt bestimmte Pfade auf bestimmte Ports einfach weiterzuleiten und nichtselbst zu bearbeiten.
11.2.3 Angular
Angular erlaubt es, vieles an Logik bereits in der View zu lösen, d.h. an derStelle, an der es in einem MVC-Pattern6 häufig gebraucht wird. (Der andere,gegenteilige Ansatz nennt sich “Fat Controller”).
Angular erlaubt das ganz hervorragende “double data-binding”, welches mansich lieber live in einem Beispiel anschaut um es zu verstehen. Damit erlaubtes Angular unglaublich schnell schöne Web-Applikationen zu entwickeln.
11.2.4 Express
Express ist ein Mini-Framework, das auf Node aufbaut, und es deutlich einfachermacht, einen Server mit Routes, Middleware, etc auf die Beine zu stellen. Dabeiarbeitet es sehr eng mit dem Node-Webserver zusammen.
11.2.5 MongoDB
MongoDB (von “humounguous”, riesig) ist eine sogenannte “NoSQL”-, bzw.Dokumentenorientierte Datenbank.
Dabei speichert es im Gegensatz zu SQL-artigen Datenbanken JSON-Objekte(“Dokumente”) anstatt von Tabellen und ist wesentlich einfacher zu bedienen.
5node (2014)6vergleiche hierzu auch das Kapitel MVC im Abschnitt Design Patterns
Part VIII
Best Practices
157
11.3.JADE105
AuchpasstessichbesseransichschnellundhäufigwechselndeDatenbank-SchemataanundistdadurchwesentlichflexibleralseineSQL-BasierteDaten-bank.
11.3Jade
11.3.1Bootstrap
11.3.2BootstrapUI
11.3.3jQuery
156CHAPTER18.DESIGNPATTERNS
106 CHAPTER 11. WEB
Chapter 18
Design Patterns
Inhalt18.1MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15518.2MVVM . . . . . . . . . . . . . . . . . . . . . . . . . . . 15518.3MV* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15518.4 (Teile aus SIS) . . . . . . . . . . . . . . . . . . . . . . . 155
18.1 MVC
18.2 MVVM
18.3 MV*
18.4 (Teile aus SIS)
155
Chapter12
XML
Inhalt12.1TEI..............................10712.2XPath............................107
12.1TEI
12.2XPath
107
154CHAPTER17.NODEWRAPPING
108 CHAPTER 12. XML 17.4. DEMONSTRATION 153
37 '-Wall',38 '-Wextra',39 '-Wno-attributes',40 '-Wno-pointer-arith'41 ]42 }43 ]44 ]45 }
Hiermit ist es also möglich, wie oben gezeigt, die C++-Klasse WL von Javascriptaus anzusprechen:
1 var addon = require('./build/Release/WLNodeWrap');2
3 var wl = new addon.WLNodeWrap();4
5 wl.add('foo');6 wl.add('bar');7 wl.add('baz');8
9 var size = wl.size();10 console.log( size ); // 3
Chapter13
Dokumentation
Inhalt13.1pipelinemitgpp,ppp&pandoc............109
13.1.1HinweisezurInstallationderdependencies......11113.1.2HinweisezurBenutzungdesMakefiles........111
13.1pipelinemitgpp,ppp&pandoc
DiesesDokumentwurdeerstelltmiteinerelaboriertenpipeline,diemehrereToolsumfasst.Dabeiwirdvonpandoc1derwesentlicheTeilübernommen,unddiesesvongpp2,dem“generalpreprocessor”undppp3,dem“pandocpreprocessor”begleitet.MitpandoclassensicheinebreiteVielfaltvonDokumenteninMarkdowner-stellenundinverschiedeneFormateexportieren,wiez.B.:
•LATEX
•HTML•ebooks•Präsentationen•u.v.w.m.
UmdiesesDokumentvollsetzenzukönnensindmindestensnotwendig:1http://johnmacfarlane.net/pandoc/2http://en.nothingisreal.com/wiki/GPP3https://github.com/typesetters/p5-App-pandoc-preprocessbzw.https://metacpan.org/
release/App-pandoc-preprocess
109
152CHAPTER17.NODEWRAPPING
17.4.3Schritt3:binding.gyp,diebuild-Dateifürnode-gypschreiben
NichtzuletztmussnocheineDateibinding.gypangelegtwerden,welche–ganzwieeinMakefile–,diebuild-Dateifürnode-gypdarstellt.node-gypisteinspeziellesbuild-Tool(vergleicheBuildSysteme)für“node-addons”undkümmertsichumdasnotwendigelinkingzudenbenötigtennode-undv8-libraries.ZumvorhandenenProjektsiehtdiebinding.gypfolgendermaßenaus(esgehtindieserbinding.gypv.a.auchdarum,C++11transparent,überverschiedeneBetriebssystemehinwegverwendenzukönnen):
1{2"targets":[3{4"target_name":"WLNodeWrap",5"sources":["addon.cpp","WLNodeWrap.cpp"]6}7],8#globalflagsgohere9#`cflags_cc!`issupposedtomean:removetheseflags
10#`cflags_cc`issupposedtomean:addtheseflags11'conditions':[12[13'OS=="mac"',{14'xcode_settings':{15'GCC_ENABLE_CPP_RTTI':'YES',16'GCC_ENABLE_CPP_EXCEPTIONS':'YES',17'CLANG_CXX_LANGUAGE_STANDARD':'c++11',18'MACOSX_DEPLOYMENT_TARGET':'10.7',19'OTHER_CFLAGS':[20'-fPIC',21'-Wall',22'-Wextra',23'-Wno-attributes',24'-Wno-pointer-arith'25]26}27}28],29[30'OS=="linux"',{31'cflags_cc!':['-fno-rtti'],32'cflags_cc':[33'-frtti',34'-fPIC',35'-fexceptions',36'-std=c++11',
110 CHAPTER 13. DOKUMENTATION
• pandoc4
• gpp5
• ppp6
– dot7
– neato8
– rdfdot9
– ditaa10
– Image::Magick11
– rsvg-convert12
– yuml13. (als python-modul installieren mit pip installhttps://github.com/wandernauta/yuml/zipball/master odereasy_install https://github.com/wandernauta/yuml/zipball/master)
– plantuml14
• TeXLive / MikTex / MacTex15
Empfohlen werden dazu noch für das Bibliographieren:
• zotero• chrome zotero plugin• zotero plugin auto export bibtex
Desweiteren sei hingewiesen auf das von David Kaumanns mit Stefan Schweterentwickelte Template zur Gestaltung von Bachelor- und Hausarbeiten, welchesauf dieser pipeline aufbaut:
• BA Thesis Template16
Der Workflow eines vollen Typeset gestaltet sich folgendermaßen:
• Vorverarbeitung mit gpp: Datei-includes, Teile Ein- und Ausblenden jenach #defines
4http://johnmacfarlane.net/pandoc/5http://en.nothingisreal.com/wiki/GPP6https://github.com/typesetters/p5-App-pandoc-preprocess bzw. https://metacpan.org/
release/App-pandoc-preprocess7http://www.graphviz.org/Documentation.php8http://www.graphviz.org/pdf/neatoguide.pdf9https://metacpan.org/release/RDF-Trine-Exporter-GraphViz
10http://ditaa.sourceforge.net/11http://www.imagemagick.org/12http://live.gnome.org/LibRsvg13https://github.com/wandernauta/yuml14http://plantuml.sourceforge.net/15http://www.dante.de/tex/TeXDistro.html16https://gitlab.cis.uni-muenchen.de/David/stub-template-bathesis
17.4. DEMONSTRATION 151
53 std::string str{ *ustring };54
55 // Unwrap WL to `This'56 WLNodeWrap* This = node::ObjectWrap::Unwrap<WLNodeWrap>(args.This());57
58 // Talk to WL's member `wl_'59 This->wl_.add(str);60
61 return scope.Close(Undefined());62 }63
64 Handle<Value> WLNodeWrap::Size(const v8::Arguments& args) {65 HandleScope scope;66
67 // Unwrap WL to `This'68 WLNodeWrap* This = node::ObjectWrap::Unwrap<WLNodeWrap>(args.This());69
70 // Return WL::wl_'s return value to Javascript (as a number)71 return scope.Close( Number::New( This->wl_.size() ) );72 }
17.4.2.1 Besprechung des Codes
• Zeilen 1–17: Diese Zeilen sind direkt aus der node-Dokumentation
• Zeilen 18–23: An dieser Stelle wird das Mapping vorgenommen, welchesbesagt, dass auf Javascript-Seite eine Methode add vorhanden sein wird,welche auf WLNodeWrap::Add zeigt. Dort wiederum wird dann auf daseigentliche add(), nämlich WL.add() weitergeleitet werden. (Das selbegilt für size() [JS-Seite] -> WLNodeWrap::Add [JS-V8-C++-BridgeEbene] -> WL::size() [echte C++-Ebene])
• Die Zeilen 54–57 zeigen die Verbindung aus der node::ObjectWrap/JS-V8-C++-Bridge-Ebene zur “echten” C++-Ebene und methode:
– zunächst wird das “eigentliche” Objekt auf node-Seite “aus-gepackt” (Zeile 54) und dessen member wl_, die “eigentliche”C++-Klasse angesprochen, und auf dieser nun die Methodeadd(const std::string&) aufgerufen.
• Jede Methode auf der V8-Ebene muss seinen Scope schließen und diesesals Rückgabewert zurückliefern. Zeile 59 zeigt, wie man ein “void” zurück-geben kann.
• Die Zeilen 66–69 zeigen erneut, wie sich size()/Size()/size() vonJavascript bis in die C++-Ebene verknüpfen lassen.
• Die Zeilen 48–51 führen den “klassischen Dreisatz” vor, wie Strings vonJavascript bis in C++-Strings umgewandelt werden.
13.1.PIPELINEMITGPP,PPP&PANDOC111
•Vorverarbeitungmitppp:alle“code”-TeiledieGraphikenbeschreibenzuGraphikenrendern
•Zentrale:pandoc:ExportinverschiedeneFormate:pdf,html,tex,ebook,etc.
Figure13.1:DerTypesettingProcess
EinegenauereBeschreibungundAnleitungfindetsichinppp-Documentation.pdfimRepositoryvonppp17.
13.1.1HinweisezurInstallationderdependencies
FürHinweisezurInstallationderdependenciesbezüglichderRechneramCIP-Pool,vergleichedieREADME.mdinBAThesisTemplate18.
13.1.2HinweisezurBenutzungdesMakefiles
FürHinweisezurBenutzungdesMakefiles,vergleicheebenfallsdieREADME.mdinBAThesisTemplate19.
17https://github.com/typesetters/p5-App-pandoc-preprocess18https://gitlab.cis.uni-muenchen.de/David/stub-template-bathesis19https://gitlab.cis.uni-muenchen.de/David/stub-template-bathesis
150CHAPTER17.NODEWRAPPING
3#endif4
5#include<node.h>6#include"WLNodeWrap.hpp"7
8usingnamespacev8;9
10Persistent<Function>WLNodeWrap::constructor;11
12voidWLNodeWrap::Init(Handle<Object>exports){13
14//Prepareconstructortemplate15Local<FunctionTemplate>tpl=FunctionTemplate::New(New);16tpl->SetClassName(String::NewSymbol("WLNodeWrap"));17tpl->InstanceTemplate()->SetInternalFieldCount(1);18
19//Prototype20tpl->PrototypeTemplate()->Set(String::NewSymbol("add"),21FunctionTemplate::New(Add)->GetFunction()22);23tpl->PrototypeTemplate()->Set(String::NewSymbol("size"),24FunctionTemplate::New(Size)->GetFunction()25);26
27constructor=Persistent<Function>::New(tpl->GetFunction());28exports->Set(String::NewSymbol("WLNodeWrap"),constructor);29}30
31Handle<Value>WLNodeWrap::New(constArguments&args){32HandleScopescope;33
34if(args.IsConstructCall()){35//Invokedasconstructor:`newWLNodeWrap(...)`36WLNodeWrap*obj=newWLNodeWrap();37obj->Wrap(args.This());38returnargs.This();39}else{40//Invokedasplainfunction`WLNodeWrap(...)`,turnintoconstructcall.41constintargc=1;42Local<Value>argv[argc]={args[0]};43returnscope.Close(constructor->NewInstance(argc,argv));44}45}46
47Handle<Value>WLNodeWrap::Add(constv8::Arguments&args){48HandleScopescope;49
50//Standardunpackingofstrings51Local<String>String=args[0]->ToString();52String::Utf8Valueustring{String};
112 CHAPTER 13. DOKUMENTATION 17.4. DEMONSTRATION 149
17.4.2 Schritt 2: Wrapper-Klasse WLNodeWrap, die vonnode::ObjectWrap erbt, schreiben
Die Wrapper-Klasse WLNodeWrap wiederum orientiert sich sehr stark an der o.g.node-Dokumentation.
Im wesentlichen erbt sie von node::ObjectWrap und exportiert eine static-Methode Init. (Diese static Methode ruft der vorherige Schritt auf:NODE_MODULE -> WLNodeWrap -> InitAll -> WLNodeWrap::Init!)
Desweiteren wird die eigentliche, zu wrappende Klasse WL<std::string> derKlasse WLNodeWrap als Member hinzugefügt.
1 #ifndef NODEWRAP_HPP_SBNDJF7E2 #define NODEWRAP_HPP_SBNDJF7E3
4 #include <node.h>5 #include <string>6 #include "WL.hpp"7
8 class WLNodeWrap : public node::ObjectWrap {9 typedef WL<std::string> wrapped_wl;
10
11 public:12 static void Init(v8::Handle<v8::Object> exports);13
14 private:15 explicit WLNodeWrap() = default;16 virtual ~WLNodeWrap() = default;17
18 static v8::Handle<v8::Value> New(const v8::Arguments& args);19
20 // Add wird nach WL.add(const std::string&) gemapped werden21 static v8::Handle<v8::Value> Add(const v8::Arguments& args);22 // Size wird nach WL.size() gemapped werden23 static v8::Handle<v8::Value> Size(const v8::Arguments& args);24 static v8::Persistent<v8::Function> constructor;25
26 wrapped_wl wl_;27 };28
29 #endif /* end of include guard: NODEWRAP_HPP_SBNDJF7E */
Selbstverständlich gibt es eine passende Datei WLNodeWrap.cpp, welche dieseDeklarationen des Header definiert, auch hier kann man sich wieder sehr eng andie node-Dokumentation halten:
1 #ifndef BUILDING_NODE_EXTENSION2 #define BUILDING_NODE_EXTENSION
Chapter14
UnifiedDeployment
Inhalt14.1wast-infrastructure....................113
14.1.1BündelungderKomponentenuntereinemDach...11414.1.2Abstraktiondesdeployment-Prozesses........115
14.2userwastd..........................116
14.1wast-infrastructure
DurchdenunifieddeploymentprocessinWASTwerdenalleKomponenten(un-abhängigvonihremAufbau,ihrenverwendetenModulen,backends,frontends,…)abstrahiertuntereinemDachzusammengefassst,undmitnureinemBefehlverwaltet,administriert,unddeployed.
DiesesVorgehenhatdenentscheidendenVorteil,dassspätereGenerationenalleKomponenteningewohnterWeisebilden,kompilierenunddeployenkönnen–ohnesichspeziellmitdemeinzelnenModulimDetailauskennenzumüssen–und,letztendlich,dabeieinzelneBefehleinderrichigenReihenfolgemitdenrichtigenArgumentenaufdiesenaufrufenzumüssen.
DerunifieddeploymentprocesswirdnachundnachimmerstärkereingesetztwerdenumdiegesamteTool-undKomponenten-LandschaftvonWASTzuver-walten,d.h.–unteranderem–,Gesamt-Releasesanzulegen(nachdemSeman-ticVersioning-Schema),denDevelopmentunddenMaster-Branchzuverwal-ten(siehe[gitbranchingmodel][]),einzelneKomponentenupzudaten,neuean-notierteDatenausBergenmiteinemBefehlinalleSuchmaschinenzuverteilenunddergleichen.
113
148CHAPTER17.NODEWRAPPING
maßeninnerhalbvonJavascriptverwendetwerdenkann:
1varaddon=require('./build/Release/WLNodeWrap');2
3varwl=newaddon.WLNodeWrap();4
5wl.add('foo');6wl.add('bar');7wl.add('baz');8
9varsize=wl.size();10console.log(size);//3
UmdieseszuerreichensindfolgendeSchrittenötig:
1.Einsteigsdateiaddon.cppschreiben2.Wrapper-KlasseWLNodeWrap,dievonnode::ObjectWraperbtundWLals
Memberenthältschreiben3.binding.gyp,diebuild-Dateifürnode-gyp,schreiben4.entstehende*.nodeDateientsprechendinJavascripteinbindenundbe-
nutzen
17.4.1Schritt1:Einsteigsdateiaddon.cppschreiben
EinekleineDateiaddon.cppwirddiegesamteStrukturvonC++nachJavascriptverbinden,undsieht–demBeispielderDokumentationfolgend–,soaus:
#ifndefBUILDING_NODE_EXTENSION#defineBUILDING_NODE_EXTENSION#endif#include<node.h>#include"WLNodeWrap.hpp"
usingnamespacev8;
voidInitAll(Handle<Object>exports){WLNodeWrap::Init(exports);
}
NODE_MODULE(WLNodeWrap,InitAll)
Hierwirdfestgelegt,dasseinModulmitdemNamenWLNodeWrapdefiniertwird,und,sobalddiesesperrequire(varaddon=require('./build/Release/WLNodeWrap');aufJavascript-Seiteaufgerufenwird,zurFunktionInitAllgesprungenwerdensoll.DieFunktionInitAllwiederumwirdWLNodeWrap::Initaufrufen,welcheswirsogleichdefinierenwerden.
114 CHAPTER 14. UNIFIED DEPLOYMENT
14.1.1 Bündelung der Komponenten unter einem Dach
Die zentrale Stelle an der alle Komponenten der WAST-Landschaft zusammen-laufen ist das repository wittfind-web.
wittfind-web stellt nach außen hin die zentrale Webseite als Einstieg für dieNutzer dar; nach innen hin ist dies der Schnittpunkt an dem alle Module zusam-menlaufen1.
Das zentrale Makefile, welches alle diese administrativen Aufgaben übernimmt(und dabei u.a. an komponentenspezifische Makefiles weiterleitet ist hier).
+++ BEGIN DEPRECATED +++Ab hier ist dieses Kapitel ein bisschen out-dated, vermittelt aber trotzallem den richtigen Eindruck von unserem neueren Makefile-Ansatz,bitte die folgenden Teile Updaten!Um die Komponenten und Tools unter einem Dach zu bündeln bietet wast-infrastructure den Befehl wast.
Unter wast werden die verschiedenen Komponenten registriert und sind damitfür den “unified deployment”-Prozess verfügbar:
> ./wastWAST, version 0.9.5
This is the help section
Usage:
./wast <command>
Available COMMANDS:init : initialize (all) componentsbuild <component> : build component <component>start <component> : start component <component>stop <component> : stop component <component>restart <component> : restart component <component>
Available COMPONENTS:wast-feedback-appwast-websitewf
1siehe hierzu auch das Kapitel Integration Tests und E2E Tests. Inegration Tests prüfendas korrekte Zusammenspiel von Komponenten welche, einzeln für sich bereits alle ihre eigenen[Unit Tests][] bestehen. Mit E2E Tests beschreibt man komplette User-Szenarien, wie diesesich auf der Webseite bewegen und mit dieser interagieren. Hierbei wird auch gleichzeitig dieVerfügbarkeit der Webserver und der auf diesen vorhandenen routes, etc. geprüft)
17.4. DEMONSTRATION 147
Figure 17.1: Node Wrapping Pattern
8 class WL {9 typedef StringType string_type;
10 typedef std::vector<string_type> value_type;11
12 public:13 explicit WL() = default;14 virtual ~WL() = default;15
16 void add(const string_type & s);17 size_t size() const;18
19 auto begin() -> typename value_type::iterator;20 auto end() -> typename value_type::iterator;21 bool operator== (const WL& other) const;22
23 private:24 value_type wl_;25 };26
27 #include "WL.cpp"28
29 #endif /* end of include guard: WL_HPP_A8E3G2X4 */
Diese Klasse soll nun also nach node gewrapped werden, damit sie folgender-
14.1.WAST-INFRASTRUCTURE115
sis
DieKomponentenwerdenunterAvailableCOMPONENTSgelistetundsindsomitfürdieBefehle,dieunterCOMMANDSgelistetsind,verfügbar.
BeispielsweiselässtsichsomitalsodieKomponentewfmitfolgendemBefehlbildenundstarten:
>./wastinitwf&&\./wastbuildwf&&\./waststartwf
Selbstverständlichlässtessichdarübernachdenken,welcheweiterenSub-Befehlefürwastnochdenkbarsind(z.B.istwastrelease<version>nochnichtimplementiert,unddenkbarsindauchBefehlewiewasttest<component>,wastdeploym<component>umdievorhergehendendreiBefehlezusammenzufassen).DieserTeilbefindetsichbishernochinderbeta-undEvaluations-Phase,dahersollenzunächstdiewichtigstenBefehlerobustimplementiertsein,bevorneueFunktionalitäthinzugefügtwird.
UmwastneueFunktionalitäthinzuzufügenodereineKomponenteTeildesuni-fieddeployment-Prozesseszumachenistgarnichtvielnötig,wieimnächstenTeilgezeigtwird.
14.1.2Abstraktiondesdeployment-Prozesses
wasterwartetvoneinerKomponenteimwesentlichen2Dinge:
•dieKomponentewollinwastregistriertsein•dieKomponentesollfürallewast-Sub-Befehle,dieunterstütztwerden
sollen,einentsprechendesSkriptliefern.Konkretmusswf,wennesdieBefehlewastbuildundwaststartanbietenwill,inseinemVerzeichnisdieDateienwast.buildundwast.startanbieten.
14.1.2.1Beispiele
IndiesemBeispielsolldieKomponentesisundihreImplementationimRahmenderwast-infrastructurebetrachtetwerden.
ZunächstalsodieRegistrierungderKomponenteinderwastinfrastructureinderDateiwast:
14COMPONENTS=(wast-feedback-appwast-websitewfsis)
146CHAPTER17.NODEWRAPPING
MöglichwirddiesdurchdiederzeitschnellsteJavascript-Implementation,V8.V8isteineJavascript-ImplementationinC++undwirdvonGoogleopensourcebereitgestellt.(V8istübrigensauchimBrowserChromefürdieJavascript-Ausführungzuständig.)ÜberdieseBridgenunkönnenalleobengenanntenAufgabenzwischendenbeidenSprach-Weltenwahrgenommenwerden.
17.1Beispiel
DasKapitelWeb-EbeneimTeilSISzeigtingenauererWeiseeinBeispielfürdieVerwendungderC++-AutomatenaufJavascript-Ebene.
17.2NodeAddon
DadasSchreibenvonNode-AddonskeineganzsimpleSacheist,empfiehltessichdieDokumentationhierzusehrgenauzustudierenundsichunbedingtsonahewiemöglichandievorgeschlagenenPatternsundBeispieleinderDokumeneta-tionzuhalten:http://nodejs.org/api/addons.html
17.3SchematischeDarstellung
Abbildung17.1aufSeite147zeigtdieschematischeDarstellungeinesnode-wrap.
17.4Demonstration
DieseDemonstrationhältsichsehrengandasPattern“WrappingC++Objects”ausdernode-addon-Dokumentation(http://nodejs.org/api/addons.html#addons_wrapping_c_objects)undbeschreibtnocheinmaldieeinzelnenSchritteetwasdeutlicheralsesdieDokumenationselbsttut.
Angenommen,esgibteineeinfacheKlasseWordList(bzw.WL)mitfolgen-demHeader(unddenentsprechendenDefinitionenzudenMethodenineinempassenden.cpp-File):
1#ifndefWL_HPP_A8E3G2X42#defineWL_HPP_A8E3G2X43
4#include<string>5#include<vector>6
7template<classStringType>
116 CHAPTER 14. UNIFIED DEPLOYMENT
Als nächstes die entsprechenden Skripte in der Komponente selbst:Hier also die Datei wast.build innerhalb der Komponente “sis”:
#!/bin/sh
set -x # Show the commands that are executed
# try "Creating build directory" bymkdir -p build
# try "Switching to build directory" bycd build
# try "Running cmake" bycmake ..
# try "Running make" bymake VERBOSE=1
# try "Switching to web component" bycd ../web
# try "Installing web dependendices" byCXX=/usr/bin/g++-4.8 npm install
# try "Installing web dependendices" bybower install
Und hier die Datei wast.start innerhalb der Komponente “sis”, um den Befehl./wast start sis zu unterstützen:
#!/bin/shset -x# try "Starting feedback app" bycd webLD_LIBRARY_PATH=/srv/www/vhosts/wast/components/sis/build/lib \sudo -u wastd forever start -a app.coffee
+++ END DEPRECATED +++
14.2 user wastd
Alle Skripte und Komponenten, die einen Webserver starten und lange laufen,sollen unter dem “Pseudo-Superuser” genannt wastd gestartet werden.
Chapter 17
Node Wrapping
Inhalt17.1Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . 14617.2Node Addon . . . . . . . . . . . . . . . . . . . . . . . . 14617.3 Schematische Darstellung . . . . . . . . . . . . . . . . 14617.4Demonstration . . . . . . . . . . . . . . . . . . . . . . . 146
17.4.1 Schritt 1: Einsteigsdatei addon.cpp schreiben . . . . 14817.4.2 Schritt 2: Wrapper-Klasse WLNodeWrap, die von
node::ObjectWrap erbt, schreiben . . . . . . . . . . . 14917.4.3 Schritt 3: binding.gyp, die build-Datei für node-gyp
schreiben . . . . . . . . . . . . . . . . . . . . . . . . . 152
Node-Wrapping bezeichnet das wrappen von C++-Klassen derart, dass dieseinnerhalb von Javascript verwendbar gemacht werden.
Im Rahmen von SIS wird dies konkret vorgeführt: die dokument-indexierendenAutomaten auf der C++-Ebene werden von der Javascript-Ebene (und damitdem node-Webserver) nur ein einziges Mal deserialisiert und ab dort als vollw-ertige Automaten im Speicher gehalten.
Vom node-Webserver aus nun lassen sich die C++-Automaten ansprechen undbenutzen.
Um dieses language-binding zu bewerkstelligen bietet node den sog. “addon”-Mechanismus, welcher es eben erlaubt, C++-Klassen mit Javascript zuverbinden.
Die Verbindung dieser beiden Sprach-Welten läuft dabei in beide Richtungen:sowohl lassen sich aus der C++-Welt Javascript-Objekte bilden und diese nachJavascript “pushen”, als auch C++-Objekte auf der Javascript-Seite konstru-ieren, laden und dergleichen.
145
14.2.USERWASTD117
Dieser“Pseudo-Superuser”hatdenVorteil,dassWebserver,dievonjemandanderemgestartetwurden,voneinerweiterenPerson–imFalledesFalles–auchwiederge-kill-tundgestopptwerdenkönnen.NormaleProzesse,dievoneinembestimmtenUsergestartetwurden,erlaubenesnicht,voneinemanderenUserge-kill-tzuwerden.
DerUserwastdistabernichtimechtenSinneeinSuper-Usermitroot-Rechten,sondernlediglicheinentsprechendausgestatterUser,derebendiesegemeinsameNutzungvonlangelaufendenProzessenüberverschiedeneUserhinwegerlaubt.
144CHAPTER16.SERIALISIERUNG
•std::is_class<C>isteingültigerType•DerbetreffendeContainerChateineMethodebegin()undeineMethode
end()welcheeinenconst_iteratorzurückliefern.
FürmehrDetailsvergleichehttps://github.com/xdbr/cpp-generic-serialize.
118 CHAPTER 14. UNIFIED DEPLOYMENT 16.4. APIS 143
• Wenn ein Container vorliegt (gesteuert von den Prinzipien von SFINAEund EnableIfContainer<T>), dann betrachte rekursiv alle Elemente([Type Traits][]: value_type) dieses Containers, so lange bis du auf einenfundamentalen Datentyp stößt: int, char, o.ä.
• Sobald ein Container bis auf seine fundamentalen Datentypen zurückge-führt, ist, so kann dieser Type binär gespeichert werden:
template <typename T, EnableIfFundamental<T>...>Tsave(std::ofstream & os, T t) {
os.write(reinterpret_cast<const char*>(&t), sizeof(t));return t;
}
• Hierbei wird zuerst die Größe des Containers und danach die einzelnenfundamentalen Datentypen gespeichert, z.B.:
template <typename T, EnableIfContainer<T>...>Tsave(std::ofstream & os, T t) {
unsigned size = t.size();save(os, size);
for (auto it = begin(t); it != end(t); ++it) {save(os, *it);
}return t;
}
Das Einlesen funktioniert mutatis mutandis.
Ein Container liegt vor – und aktiviert nach den Prinzipien von SFINAE –die entsprechende save/load Funktionalität wenn folgendes Konstrukt einengültigen Typ zurückliefert:
template<typename C>struct is_container<C,
typename is_of_type<typename C::const_iterator(C::*)() const,&C::begin,&C::end
>::type> : std::is_class<C> { };
D.h. es wird, um einen Container zur Compile-Zeit zu erkennen vom type Cfolgendes erwartet:
PartVII
Techniken
119
142CHAPTER16.SERIALISIERUNG
namespaceusb=util::serialize::binary;
/*Example:Writenestedcontainertoabinaryfile*/std::list<std::map<std::string,unsigned>>list={{{"foo",1},{"bar",2}},{{"baz",1},{"quux",2}}
};
/*save*/std::ofstreamos{"file.bin",std::ios::out|std::ios::binary};usb::save(os,list);os.close();
DasEinlesenvonBinärdatenmitgenericserializeistebenfallssehreinfach:
namespaceusb=util::serialize::binary;
/*Example:Readnestedcontainerfrombinaryfile,way#1*/std::ifstreamis{"file.bin",std::ios::in|std::ios::binary};std::list<std::map<std::string,unsigned>>list;usb::load(is,list);
EinandererWegwärees,denContainer-Typalstemplate-ArgumentanzugebenundC++11’sautozunutzen:
namespaceusb=util::serialize::binary;
/*Example:Readnestedcontainerfrombinaryfile,way#2*/std::ifstreamis{"file.bin",std::ios::in|std::ios::binary};
autolist=usb::load<std::list<std::map<std::string,unsigned>>
>(is);
AufdieseArtundWeisewerdenbeliebigeContainerineinemFormatwieinderGrafikAbbildung16.1abSeite138angedeutet,angelegt.
16.4.3.1BeobachtungenDiesesKapitelbeschreibtsehrtiefeundz.T.sehrkomplexeDetailsundistnuralstechnischeReferenzfürInteressiertegedacht.
ImwesentlichenbedientsichgenericserializederTechnikenderTemplateMetaProgrammierungunddenHilfestellungenvonhttp://flamingdangerzone.com/cxx11/2012/05/29/type-traits-galore.html.
DabeifunktioniertderSpeicher-Algorithmusfolgendermaßen:
16.4. APIS 141
int main() {/* Container füllen ... */
// JSON nach std::cout serialisieren:cereal::JSONOutputArchive json_archive_cout{std::cout};json_archive_cout( wl );
/* ... */}
Das Einlesen ist wiederum genauso einfach:
#include <iostream>#include <fstream>#include <string>
#include <cereal/archives/binary.hpp>
#include "WordList.hpp"
int main() {
/* Es gibt eine Binär-Serialisierte WordList ... */std::ifstream is{"out.bin", std::ios::binary};
// cereal Input-Archiv auf diese Datei festlegencereal::BinaryInputArchive binary_archive{ is };
// leeren Container anlegenWordList wl;
// Container aus Binär-Datei ladenbinary_archive(wl);
return 0;}
16.4.3 generic serialize
generic serialize erlaubt es, beliebige Standard-Container (mit beliebigerSchachtelung) individuell mit save zu speichern und mit load zu laden.Es kümmert sich automatisch darum, die richtige Speichermethode für denContainer und die “Tiefe” des Containers zu finden.Die API von generic serialize ist ebenfalls sehr einfach und überschaubar. Siefunktioniert so:
Chapter15
C++
Inhalt15.1WrappingvonCnachC++...............121
15.1.1Vorteile.........................12215.1.2Patterns.........................122
15.2PolicybasedDesign....................12515.2.1Beispiel.........................125
15.3Typetraits.........................12715.3.1Beispiel.........................128
15.4TemplateMetaProgrammierung............12915.5SFINAE...........................12915.6SilentDegredation.....................130
15.6.1Beispiel.........................13115.6.2Bemerkung.......................131
15.7StaticDispatching/Tagdispatch...........13215.8Detail-Beschreibung....................13315.9Bemerkungen........................13415.10WrappingvonC++nachJavacript(Node).....134
IndiesemKapitelwerdenentscheidendeTechnikenvorgestellt,diebesondersinfortgeschrittenenC++-ProgrammeneinegroßeRollespielenkönnen.DiefolgendenTechnikenkommensehrvielzumEinsatzinwittfindundSIS.
15.1WrappingvonCnachC++
InmanchenSituationenbietetessichan,CstructsnachC++zuwrappen.
121
140CHAPTER16.SERIALISIERUNG
private:list_tlist_;
public:template<classArchive>voidserialize(Archive&archive){
archive(list_);}
};
NunkanndieKlassevonaussenserialisiertunddeserialisiertwerden:
#include<iostream>#include<fstream>#include<string>
#include<cereal/archives/binary.hpp>
#include"WordList.hpp"
intmain(){WordListwl;
//ElementezumContainerhinzufügenstd::stringbaz{"baz"};wl.add("foo");wl.add(std::string{"bar"});wl.add(baz);
std::cout<<wl.size()<<std::endl;
//Binär-Dateianlegen,inwelcheserialisertwerdensollstd::ofstreamos{"out.bin",std::ios::binary};
//cereal-ArchivaufdieBinär-Dateianlegencereal::BinaryOutputArchivebinary_archive_file{os};
//SerialisierbarenContainerindascereal-Archivgebenbinary_archive_file(wl);
return0;}
NachXMLoderJSONzuserialiserenfunktioniertgenaunachdemselbenSchema:
122 CHAPTER 15. C++
15.1.1 Vorteile
Die entscheidenden Vorteile des Wrappens von C nach C++ sind:
• automatische und saubere Allokation / Deallokation von Klassen bzw.structs (dieses ist auch bekannt unter dem Namen “RAII” – zu diesemsiehe auch das nächste Kapitel sowie Definitionen)
• einfacheres “Handling” der Instantiierung von Klassen, also Konstruktionund, v.a. sauberere, sicherere Destruktion
Selbstverständlich lassen sich nach dem Wrapping auch alle Vorteile von C++bzw. C++11 (und, später C++14) nutzen. Darunter fallen u.a.:
• Die Smart Pointers shared_ptr und unique_ptr: Diese legen u.a. festeOwnership zu Grunde. Damit wird verhindert, dass man vergisst einstruct wieder zu deallokieren und die Zuständigkeit wird festgelegt: wersoll den pointer am Ende wieder deallokieren?
• Templatisierung
• Vererbung und Interfaces und damit klare Strukturen: Mit C++ lässt sichviel stärker auf der Problem-Ebene arbeiten denn auf der reinen Sprach-Ebene
15.1.2 Patterns
Grundlegend funktioniert das Adapter/Wrapper-Pattern immer auf die gleicheArt und Weise: Es gibt eine Klasse die gewrapped werden soll, den Adaptee undeinen Wrapper, den Adaptor bzw. Wrapper.
Figure 15.1: Adapter Pattern
16.4. APIS 139
16.4.2 cereal
Die API von cereal ist relativ einfach – für einen tiefergehenden Einblick vergle-iche das Kapitel Zweistufige Serialisierung in SIS: Symmetric Index Structures.
Im Grunde ist es lediglich notwendig eine Methode der folgenden Art in seinerKlasse zu schreiben:
Angenommen, die Klasse hat folgendes Member list_:
#include <vector>#include <string>
class WordList {public:
typedef std::vector<std::string> list_t;
/* Constructors, Methods, etc... */
private: // Memberslist_t list_;
};
So reicht es bereits aus, die notwendigen header von cereal und eine Methodeserialize() folgendermaßen zu schreiben:
// This method lets cereal know which data members to serializetemplate<class Archive>void serialize(Archive & archive) {
archive( list_ ); // serialize things by passing them to the archive}
Die Klasse sieht nun also so aus:
#include <vector>#include <string>
#include <cereal/types/string.hpp>#include <cereal/types/vector.hpp>
class WordList {public:
typedef std::vector<std::string> list_t;
/* Constructors, Methods, etc... */
15.1.WRAPPINGVONCNACHC++123
DerWrapperhälteineVerbindungzumAdapteeundbildetdieAPInach.DerClientwirdnurnocheinenAdaptorbzw.WrapperinstantiierenundderAdap-torkümmertsichdarum,denentsprechenden,eigentlichenAdapeezukonstru-ieren.
WennderClientMethodendesAdaptorsverwendet,sowirddieserlediglichdieParameterandenAdapteeweiterleitenunddieErgebnisse,dievomAdapteekommenwiederandenClientzurückleiten.
ImFallvonC++bietetessichnatürlichan,denAdapteealsPointerimAdaptorzuhalten.
Einmögliches,elegantes,sicheresundeigentlichsimplesPatternumCstructsnachC++zuwrappenbeschreibt(R.MartinhoFernandes2013)mitseiner“RuleofZero”.EinekonkreteAnwendungwirdimKapitelAbschnitt3.6.1.1abSeite43sowiehierimDetailbeschrieben.
UmdiesesPatternbesserverstehenzukönnensollandieserStellenocheinmaleingenuererBlickdaraufgeworfenwerden.AlsBeispieldientindiesesmFalldieKlasseVoidSequenceAdapter,welchedasC-StructVoidSequencewrapped.
VoidSequencestelltinderC-SchichteineArtstd::vectordar,indemeseineListevonElementenführt,und,fallsderallokierteSpeichernichtausreicht,neuenbesorgt,umweitereElementeinseinenMemberseinfügenzukönnen.DabeispeichertesbeliebigeObjekte,indemessichalsvoid*verwaltet–let-zteressetztnatürlichvoraus,dassdiesepointerspäterwiederentsprechend“zurückgecastet”werden.
WieauchimmerdasstructimDetailaussieht,dasWrapping-Patternbleibtstetsidentisch.ZunächstsolleinnaiverAnsatzvorgestelltwerden,welcherdannkontrastiertwirdvondem“RuleofZero”-Ansatz.
1#include"Adaptee.h"23classAdaptor{4Adaptee*adaptee_;5Adaptor():adaptee_{newAdaptee()}{};6~Adaptee(){deleteadaptee_;}7};
DiesernaiveAnsatzzeigtdasWrapping-PatterninklassischerWeiseinC++:eswirdeinPointerzumAdapteegehalten.DerPointerwirdimKonstruktorhergestelltundimDestruktordeallokiert.Problematischwirdes,wennder“Konstruktor”desAdapteeeineexceptionwirft:KonstruktorensollenkeineExceptionswerfen,daessonstschwierigwird,bereitsgelaufeneAllokationenrückgängigzumachen.
EinfortgeschrittenererAnsatzistder“RuleofZero”-Ansatzvon(R.MartinhoFernandes2013):IndiesemFallistauchdieOwnershipzurAdaptee-Ressourcegeregelt,daessichhierumeinenunique_ptrhandelt.
138CHAPTER16.SERIALISIERUNG
Figure16.1:BeispielfüreinByte-Layout
–hierbeihatdererstestd::stringeinesize()==4–hierbeihatderzweitestd::stringeinesize()==6
DieingesamteGrößedesBinärformatsbeträgtdann19Byte.
16.3.1Beobachtungen
•DerersteCharacterbelegt1Byte•unsignedintbeträgt4Byte(aufeinem64-Bit-System)•boolbelegt1Byte:Obwohleinbooltheoretischnur1Bitstatteinem
ganzenByte(8bit)bräuchte,tritthierdasPhänomendesPaddingaufunddasbitwirdaligned(siehedazuhttp://en.wikipedia.org/wiki/Data_padding)
•Derstd::vector<std::string>istfolgendermaßenaufgebaut:–daserstebytewirdbelegtmitderAngabe,wievieleElementedervectorenthält,alsomitvector.size()
–dasnächstebytekündigtdieGrößedeserstenstd::stringsan:4–nunfolgendie4charactersdeserstenstrings–dadervector2stringsenthältmussnundieLängeninformationüber
denzweitenStringfolgen:string2.size()==6–nunfolgennoch6charsdeszweitenstringsdesvectorunddie
Informationensindvollständig.
16.4APIs
16.4.1Boost.Serialization
Vergleichehttp://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html
124 CHAPTER 15. C++
1 #include "voidSequence.h"23 class VoidSequenceAdapter {4 using adaptee_handle = std::unique_ptr<VoidSequence, decltype(&::VoidSequenceFree)>;56 private:7 adaptee_handle adaptee_;89 public:
10 VoidSequenceAdapter()11 : adaptee_{ ::VoidSequenceInit(1), &::VoidSequenceFree } {}12 ~VoidSequenceAdapter() {}13 };
15.1.2.1 Besprechung des Codes
• Zeile 1 bindet die Definitionen des C structs ein• Zeile 3 definiert eine Adapter-Klasse VoidSequenceAdapter, die das C
struct VoidSequence wrappen wird• Zeile 4 definiert einen geeigneten Daten-Typ für den Adaptee:
– Der Typ des unique_ptr ist unique_ptr<VoidSequence> miteinem custom-Desktruktor. Letzterer wird aufgerufen, sobald derunique_ptr destruiert wird.
• die gewöhnungsbedürftige Schreibweise &::VoidSequenceFree bedeutetfolgendes:
– unique_ptr verlangt, wenn man einen custom-DTOR angeben will,als zweites Template-Argument den Typ einer Funktion. Dieses wirddurch decltype generiert.
– decltype wiederum wird den Typ der Funktion VoidSequenceFreezurückliefern
– & nimmt die Adresse der Funktion (liefert also einen Pointer zurück)– ::VoidSequenceFree gibt an, dass es sich hier um eine namespace-
lose Funktion handelt. (Also das Gegenstück von, z.B. std::)
• adaptee_handle adaptee_ legt das member adaptee_ vom Typadaptee_handle an. Damit ist sichergestellt, dass zu dem Zeitpunkt,an dem die Destruktion des Objekts VoidSequenceAdapter stattfindet,alle seine member destruiert werden. Damit wiederum wird dercustom-DTOR des adaptee_handle angestoßen und dieser ist einVoidSequenceFree, also ist die Rückbindung an die C-Schicht gegeben.
• Zeile 10-11: Der CTOR von VoidSequenceAdapter nun wird das memberkonkret initialisieren: Als erstes Argument wird die Konstruktionsfunk-tion des C-structs mitgegeben, als zweites Argument die Adresse derDestruktionsfunktion des C-structs.
• Zeile 12: Der DTOR des VoidSequenceAdapters braucht nichts weiter –das member adaptee_handle wird nach den Standard-Regeln von C++destruiert werden.
16.2. FORMATE 137
16.1.1.4 generic serialize
ist eine Idee und ein Proof of Concept von Florian Fink und Daniel Bruder, umeinzelne Container gezielt durch ein- und die selbe API im Binärformat auf dieFestplatte schreiben und von dort wieder laden zu können. Dies wird ermöglichtdurch C++11 und Template Meta Programmierung und SFINAE. Teile hiervonwerden im folgenden gleich beschrieben werden.
16.2 Formate
Die wesentlichen Formate, um Klassen, deren Members und Vererbungskettenauf Festplatte zu speichern und später wieder zu laden sind v.a. die drei folgen-den:
• JSON / Text• XML• Binärformat
cereal und boost serialization unterstützen jeweils alle 3 der hier genanntenFormate.
Selbstverständlich ist das Byte-Format das platzsparendste unter den Formaten,dabei auch das am kompliziertesten “zu debuggende”, sollten Fehler auftreten.JSON ist sowohl platzsparend als auch bequem zu lesen. XML ist am meisten“verbose”.
16.3 Klassische Verfahren: Binärformat undbyte-layout
Beim Serialisieren in das Byte-Format gibt es eine gängige Praxis die hierbeschrieben werden soll.
Im Binärformat muss der Anwender das byte-layout genau kennen, um etwassinnvolles damit anfangen zu können – die Grafik in ?? ab Seite ?? soll diesverdeutlichen.
In diesem Fall werden 4 Variablen gespeichert:
• ein char• ein unsigned int• ein bool• ein std::vector<std::string> mit der Größe 2:
15.2.POLICYBASEDDESIGN125
15.2PolicybasedDesign
Policy-baseddesignerlaubtes,eineKlasse,dieverschiedenePolicieskennt,aufvieleArtenundWeisenzukonfigurierenundsomiteindeutlichunterschiedlichesVerhaltenderKlasseerzeugenzukönnen.
Policiesdeckendabeiunterschiedliche,orthogonaleKonzepteabundlassensichmiteinanderkombinierenumeineVielzahlvonFunktionalitätenundVerhal-tensweisenzubewirken.
VergleichevorallemdieImplementationdererstenGenerationvonSmartPoint-ern(auto_ptr)welchezudenheutigenStandard-Smart-Pointern(shared_ptrundunique_ptr)geführthabenin(Alexandrescu2000).
15.2.1Beispiel
UmdasBeispielausdemvorherigenKapitelerneutaufzugreifen,sollandieserStelleaufdietatsächlicheImplementationdesadaptee_handleeingegangenwerden:
1classManaged:std::true_type{};2classUnmanaged:std::false_type{};34template<classStringType=std::string,classManagedAdaptee=Managed>classVoidSequenceAdapter;56template<classStringType,classManagedAdaptee>7classVoidSequenceAdapter{89usingadaptee_handle=typename
10std::conditional<11ManagedAdaptee::value==true//ifadapteeistobemanagedbythisadapter12,std::unique_ptr<VoidSequence,decltype(&::VoidSequenceFree)>//thenhandleisaunique_ptrw/customDTOR13,VoidSequence*//otherwise:bareptr,noautomaticdeletion.14>::type;//finally:don'tforgettochoosethistype15adaptee_handleadaptee_;1617/*...*/18};
AbegesehenvondenTemplateMetaProgrammierungs-Anteilen(std::conditional)unddenTypeTraits-Anteilen(ManagedAdaptee::value)indiesemBeispielsollandieserStellederPolicy-BasedAnsatz(ManagedAdaptee)genaubetrachtetwerden.
KurzzurWiederholung:NachderDefintioninZeile4,kanneinVoidSequenceAdapterauffolgendeArtenundWeiseninstantiiertwerdenunddabeieinsehrunter-schiedlichesVerhaltenaufweisen:
1VoidSequenceAdapter<>v1;/*std::string,managed*/2VoidSequenceAdapter<std::wstring>v2;/*std::wstring,managed*/3VoidSequenceAdapter<std::wstring,Managed>v3;/*same*/4VoidSequenceAdapter<std::wstring,Unmanaged>v4;/*std::wstring,unmanaged!*/
136CHAPTER16.SERIALISIERUNG
16.1.1Hinweise
16.1.1.1SelbstgeschriebeneSerialisierungsmethoden
zuverwenden,kannmehrereNachteilehaben:
•esgibtschonguteundweithin-getesteFrameworkswirdboost-serializationundcereal.
•SerialisierunginC++richtigzumachen,kannsehrkompliziertseinundvielAufwanderfordern(v.a.dieSerialisierungvonPointernundtrackenderselben,vonVererbungsketten(virtualvs.non-virtual)undvieleweiteredetailreicheProbleme)
•ÜbertragbarkeitundWartung:solltenandereEntwicklerdiemitdervorhandenenCode-Baseweiterarbeitenmüssen,sokennendiesehöchst-wahrscheinlichschonboostserializationundhabenvorherschonmitdiesergearbeitet
16.1.1.2BoostSerialization
isteineweitverbreitete,d.h.gutbekannteundinvielenProjektengetesteteSerialisierungsbibliothek.BoostSerializationkannu.a.auchrawpointerserial-isiern,wennsolchealsKlassenmemberverwendetwerdenundVererbungskettenbeiderDeserialisierungrichtigauflösen.Leideristesz.T.etwaskomplexunddieDokumentationnichtgeradeleichtzuverstehen;dafüraberistesmiteinedermächtigstenSerialisierungsbibliotheken.
16.1.1.3cereal
cerealisteinejungeSerialisierungsbibliothekundverwendetv.a.FeaturesausC++11,wiez.B.TemplateMetaProgrammierung,umweitreichendeAnnah-menüberDatentypenmachenzukönnen.(Diesistvorallemdarumwichtig,weilC++keineIntrospectionhatbzw.habenkann).
cereal’sAPIistrelativeinfachzuverstehenundeinzusetzen,weshalbcerealinSISeingesetztwird,umdenC++-TeilderAutomatenaufderFestplattezuspeichernundwiederzuladen.
Hinweis:inSISwerdennurdieC++-SchichtderAutomatenvoncerealserialisiert;fürdieC-SchichtwerdendieC-eigenenSerialisierungsmetho-denverwendet.DabeideSchichtenunddiedarinbefindlichenKlassenaufeinanderaufbauen,isthierbeiabertunlichstdaraufzuachten,dassbeide(De-)Serialisierungenordentlichaufeinanderabgestimmtsind!SiehedieentsprechendenKapitelbeiSISfüreinetiefereDokumentationzudiesemThema.
126 CHAPTER 15. C++
Wie im vorherigen Kapitel besprochen, wird die Klasse VoidSequenceAdapter– im Standardfall – den Speicher des Structs adaptee_ automatisch am Endeseiner eigenen Lifetime deleten, indem es die Funktion VoidSequenceFree ausder C-Schicht aufrufen wird.
Nun kann es aber ganz bestimmte Situationen geben, in welchen dieses Verhal-ten nicht nur unerwünscht sondern fehlerhaft wäre. In diesen Fällen lässt sichein weiteres Template-Argument, Unmanaged mitgeben, um die Klasse derartanders zu gestalten, dass sie kein (!) automatisches delete von VoidSequenceausführen wird.
Dabei spielen folgende Teile zusammen:
• class Managed : std::true_type {}; ist eine bereits fertige Klasseohne weitere Implementation. Sie stellt einen “sprechenden” strong typedar, der sich als Template-Argument nutzen lässt. std::true_typestellt einen Typ aus C++11 dar, der folgendem Typ entspricht:std::integral_constant<bool, true>. Das heisst, es handelt sichhier um einen “strong type” vom Typ bool mit der Belegung true,dessen einfachste Implementierung folgende sein könnte (der Standardübernimmt dieses aber):
template<class T, T v>struct integral_constant {
static constexpr T value = v;};
• Hiermit wiederum lassen sich entscheidende Weichen (zur Compile-Zeit!)stellen, um VoidSequenceAdapter entweder Managed oder Unmanaged zumachen. Um zur Compile-Zeit die Klasse VoidSequenceAdapter anderszu konfigurieren lässt sich Managed::value abfragen, um zu sehen, wiedie Klasse konfiguriert werden soll (vergleiche hierzu das “Type Traits”-sowie das “Template Meta Programmierungs”-Kapitel).
• In diesem elaborierteren Fall wird also der Typ des adaptee_handle zurCompile-Zeit entschieden und kann – je nach Typ von ManagedAdaptee –eines der beiden folgenden werden:
std::unique_ptr<VoidSequence, decltype(&::VoidSequenceFree)>
oder schlicht:
VoidSequence*
Mit diesem Policy-Based Ansatz ist es also möglich, eine Klasse zu schreiben,die mehreren Ansprüchen – je nach Bedarf – gerecht werden kann: ImStandardfall ist VoidSequenceAdapter eine Adapter-Klasse, welche den
Chapter 16
Serialisierung
Inhalt16.1Methoden zur Serialisierung . . . . . . . . . . . . . . . 135
16.1.1 Hinweise . . . . . . . . . . . . . . . . . . . . . . . . . 13616.2 Formate . . . . . . . . . . . . . . . . . . . . . . . . . . . 13716.3Klassische Verfahren: Binärformat und byte-layout . 137
16.3.1 Beobachtungen . . . . . . . . . . . . . . . . . . . . . 13816.4APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
16.4.1 Boost.Serialization . . . . . . . . . . . . . . . . . . . 13816.4.2 cereal . . . . . . . . . . . . . . . . . . . . . . . . . . . 13916.4.3 generic serialize . . . . . . . . . . . . . . . . . . . . . 141
Unter Serialisierung versteht man das Abspeichern einer konkreten, instanzi-ierten Klasse – henau genommen der Klassentyp, seine Member und dieVererbungskette – auf der Festplatte, um diese Klasse in genau diesem Zustandzu einem späteren Zeitpunkt wiederherstellen zu können.
16.1 Methoden zur Serialisierung
Für das Serialisieren und Deserialisieren in C++ gibt es mehrere Möglichkeiten:
a) selbst geschriebene Serialisierungsmethoden verwendenb) Boost Serializationc) cereald) generic-serialize
135
15.3.TYPETRAITS127
RAII-Prinzipenfolgt;solltejedocheinanderes,möglicherweiseorthogonales,Verhaltenbenötigtwerden,solässtsichdiesesebensoumsetzenundderrestlicheCode,derVoidSequenceAdapternutzt,kanndiesenauchweiterhinwiegewohntnutzen.
ZudiesemKapitelwirdempfohlenauchdieanderenKapitelTemplateMetaPro-grammierung,SFINAE,Typetraits,undSilentDegredationgenauzubeachten;vorallemaber(Alexandrescu2000),(DiGennaro2012)und(AbrahamsandGurtovoy2005)genauzustudieren.
15.3Typetraits
TypetraitssindimwesentlichenschlichttypedefsineinerKlasse,diemanvonaußenabfragenkann.
EinkleinesBeispielsolldieskurzdarstellen:
Anstattfolgendeszuschreiben:
1#include<vector>2#include<string>3#include<cctype>4#include<algorithm>5#include<iostream>6
7#include<boost/algorithm/string.hpp>8
9intmain(){10typedefstd::vector<std::string>string_vector_t;11
12string_vector_tvec={"foo","bar","baz"};13
14for(std::vector<std::string>::iteratorit=vec.begin();15it!=vec.end();16++it)17{18std::cout<<*it<<std::endl;19}20
21for(autoit=vec.begin();it!=vec.end();++it){22boost::to_upper(*it);23}24
25for(constauto&elem:vec){26std::cout<<elem<<std::endl;27}28
29return0;30}
läßtsichaufeinfachdertypedefvalue_typevonstd::vectornutzen:
134CHAPTER15.C++
–beiderWeiterleitung–demdispatching–,verwendetautobar()[[dispatcher]]diesenTagderart,dasses:*einMini-ObjektvomTyptag<T>anlegt–durchuniforminitial-
ization:tag<T>{}–diesesMini-Objektkannauchwiederumalslediglichdeskriptivbe-
trachtetwerden,denneswirdletztendlichvomOptimizierentferntwerden
•nunaberistderWegfrei,jenachInstanziierungentwederintbar(tag<int>)oderstd::stringbar(tag<std::string>)aufzurufen.
•SchlussendlichwirdauchnochinnerhalbderdispatchendenMeth-odederRückgabewertoffengehaltenundrichtetsichnachdemRückgabewertderlogik-tragenden,[[dispatched_to]]-Methode:->decltype(this->bar(tag<T>{}))
15.9Bemerkungen
Offensichtlichlässtsichmitden[[Attributen]]spielenunddiesesindvariabelhinsichtlichdessen,wodiesegenauplatziertwerden.
AttributewurdeninC++11eingeführt,umdenWegaufSprachebenedahinge-hendzuöffnenundstandardisieren,dassderCompiler(zueinemspäterenZeit-punkt)dieseAttributeinderKompilierungnutzenkann–bisherjedochwer-dendiesevondengängigenCompilerngroßflächigignoriert,sindaberbereitsnutzbar,wieindiesemBeispiel;machenaberlediglichfürdenAnwenderSinn.
DieImplementationvondiesemCode-Stückfindetsichhier.
15.10WrappingvonC++nachJavacript(Node)
SiehehierzudaseigeneKapitelNodeWrapping.
128 CHAPTER 15. C++
1 #include <vector>2 #include <string>3 #include <cctype>4 #include <algorithm>5 #include <iostream>6
7 #include <boost/algorithm/string.hpp>8
9 int main() {10 typedef std::vector<std::string> string_vector_t;11
12 string_vector_t vec = { "foo", "bar", "baz" };13
14 std::for_each(begin(vec), end(vec), [&](string_vector_t::value_type & elem) {15 std::cout << elem << std::endl;16 });17
18 std::for_each(begin(vec), end(vec), [&](decltype(vec)::value_type & elem) {19 boost::to_upper(elem);20 });21
22 std::for_each(begin(vec), end(vec), [&](std::vector<std::string>::value_type & elem) {23 std::cout << elem << std::endl;24 });25
26
27 auto output_function = [&](string_vector_t::value_type & elem) {28 std::cout << elem << std::endl;29 };30 std::for_each(begin(vec), end(vec), output_function);31
32 return 0;33 }
Type traits lassen sich insbesondere im Zusammenspiel von verschiedenenKlassen nutzen und ermöglichen es, unterschiedliche Klassen unabhängigervoneinander zu halten, dabei aber für mehr Typsicherheit zu sorgen.
15.3.1 Beispiel/// @brief meta-class to handle StringType type traits (using static assertions)template<class T>struct ElementSize {
static constexpr bool T_is_string_type =std::is_base_of< std::string, T>::value
|| std::is_base_of<std::wstring, T>::value ;
static_assert(T_is_string_type,"\n\n\tYou must instantiate this class in question with std::string,""\n\tstd::wstring, or any class derived thereof.\n"
);
typedef T type;typedef T string_type;typedef typename T::value_type value_type;
typedef typename std::conditional<
15.8. DETAIL-BESCHREIBUNG 133
10
11 [[ dispatched_to ]]12 std::string bar(tag<std::string>) {13 return std::string{"foo"};14 }15
16 int bar(tag<int>) [[ dispatched_to ]] {17 return 5;18 }19
20 auto bar() [[ dispatcher ]]21 ->decltype(this->bar(tag<T>{})) // 'this' seems to be needed here.22 {23 return bar(tag<T>{});24 }25 };
15.8 Detail-Beschreibung
• es gibt einen zentralen Einstiegspunkt, die Methode bar(): die Methodebar() ist mit dem Attribut [[dispatcher]] markiert und zeigt damitan, dass bar() keinerlei Logik hält, sondern lediglich weiterleiten (dis-patchen) wird, zu den anderem Methoden, welche die Logik beinhalten.Das Attribut [[dispatcher]] hat keinerlei Funktionalität, ausser, dasssie dem Anwender einen Hinweis darauf gibt, was diese Methode macht.
• ebenso wie es einen [[dispatcher]] gibt, gibt es also nun Logik-tragendeFunktionen oder Methoden, zu welchen dispatched wird, diese sind mitdem Attribut [[dispatched_to]]markiert – wiederum ist dieses Attributlediglich ein Hinweis an den Anwender und könnte dementsprechend aus-gelassen werden, es tragt keine weitere Funktionalität. Die beiden Logik-tragenden Methoden sind:
– int bar(tag<int>) und– std::string bar(tag<std::string>)
• bei einem genauen Blick auf den Funktionsteil des [[dispatcher]] siehtman, dass es die ge-tag-ten Methoden [[dispatched_to]] aufruft, bzw.an diese weiterleitet. Diese letzteren Methoden sind implementationsab-hängig, basierend auf dem type T, mit welchem die Klasse Foo<> instanzi-iert ist.
– zu diesem Zweck gibt es eine weitere (Mini-)Klasse template<classT> struct tag{}; welche auch wiederum zum größten Teilnur “deskriptiven” Charakter hat, um anzudeuten, dass hier eintag-dispatching stattfindet.
15.4.TEMPLATEMETAPROGRAMMIERUNG129
std::is_same<std::string,T>::value,//ifStringTypeisstd::stringstd::fstream,//thenstream_typeisstd::fstreamstd::wfstream//elseitisstd::wfstream>::typestream_type;
staticconstexprunsignedintvalue=sizeof(typenamestring_type::value_type);
};
15.4TemplateMetaProgrammierung
TemplateMetaProgrammierungbestehtausmehrerenTeilendieindennäch-stenKapitelnbesprochenwerden
15.5SFINAE
Einein“Metaprogrammierungskreisen”häufiggeseheneAbkürzungistSFINAE–wobeidiesesMonstrumanAbkürzungfür“Substitutionfailureisnotanerror”steht(“SubstitutionFailureIsNotanError”2014).
BeiSFINAEgehtesumfolgendesPrinzip:
ManmachtsichdieGarantiedesStandardszunutze,dass,fürdenFall,indemeinTemplate-Argumentungültigist,keinFehlerausgelöst,sonderndieserschlichtübergangenwird.
GanzgrundsätzlichgehtesbeiSFINAEumfolgendes:
Ifaninvalidargumentorreturntypeisformedwhenafunctiontemplateisinstantiatedduringoverloadresolution,thefunctiontem-plateinstantiationisremovedfromtheoverloadresolutionsetanddoesnotresultinacompilationerror.
Kurzgesagt:
•währenddesEinsetzensvonTempalte-ArgumentenindieTemplate-Klassenwerdenpotentiellvieletemplate-KlassenvomCompilerangelegt
•diese“ausgefüllten”Template-Klassenlandenimsog.“OverloaodResolu-tionSet”.
•beidieserOperationkönnenFehlerentstehen(informvon“ill-formed”classes)–diesewerdenschlichtübergangen.
•Voilà!DiesesAussortierendesCompilersvonill-formedclassesbewusstzunutzenistSFINAE.
132CHAPTER15.C++
ImNormalfallwirdnämlichdietemplateclassXüberalldort,wosieverwen-detwird,vomCompiler(u.U.auchvieleMale)instantiiertnurumamSchlussallediese–bisaufeine–wiederzuverwerfen.
C++11erlaubteineeinmaligeSpezialisierungaufdiesichandereCode-Teilestützenkönnenmit:
externtemplateclassstd::vector<MyClass>;
AllerdingsbeisstsichnundiesesKonzeptmitder“silentdegredation”dadurchdiesesVorgeheneinevolleSpezialisierungunddamiteinevolleInstantiierungvorgenommenwird.
15.7StaticDispatching/Tagdispatch
Beimstaticdispatchingbzw.auchtagdispatchinggehtesdarum,verschiedeneFunktionen(oderMembers)mittagszuannotierenund,jenachBedarf,gezieltauszuführen.
Angenommen,manhatdasfolgendeProblem:
EsgibteinKlassen-Templatetemplate<classT>FoowelcheeineMember-Methodebar()hat.
NungibteszweiunterschiedlicheInstanziierungenfürdenContainerFoo:ein-malalsFoo<std::string>undeinmalalsFoo<int>.
BasierendaufdieserInstanziierungsollennunzweikomplettunterschiedlicheMethoden(imSinnevonunterschiedlichenImplementierungen)derMethodebar()aufgerufenwerden.
Diesließesich–indiesemBeispiel–,auchdurchpartielleSpezialisierunger-reichen,dennochgreiftdasBeispielindemSinne,alsdassdietagdispatching-TechnikauchinanderenFälleneingesetztwerdenkann;nichtnurindiesemFall.
Einmember-dispatch-pattern,umdieseszuerreichenkönntez.B.soaussehen:
1#include<type_traits>2
3//C++11Proofofconceptofdifferentimplementationsof4//membermethodsfordifferenttypesofclassinstances.5
6template<classT>structtag{};7
8template<classT>9structFoo{
130 CHAPTER 15. C++
In der Standard-Library von C++11 gibt es z.B. eine Meta-Funktionstd::enable_if<>.
Ihre Definition wird in etwa so aussehen:
template <bool Condition, typename T = void>struct enable_if {}; // no members
template <typename T>struct enable_if<true, T> { using type = T; }; // type member
Beispiel-Aufruf:
typename std::enable_if<std::is_floating_point<T>::value>
Wenn nun T von einem is_floating_point-Typ ist, so ist ein Type Trait ::typedefiniert, ansonsten nicht.
Dieses Konstrukt nun lässt sich an verschiedenen Stellen einsetzen um z.B. unterbestimmten Bedingungen Funktionen ein- und auszuschalten, oder unter bes-timmten Bedingungen andere Überladungen anzubieten:
• std::enable_if kann als zusätzliches Argument einer Funktion verwendetwerden (aber nicht bei Operatoren-Überladungen)
• als Rückgabewert (daher aber nicht Konstruktoren und Destruktiren)
• oder als Klassen-Template oder Funktionstemplateparameter
Als Hintergrundlektüre siehe auch:
• http://en.cppreference.com/w/cpp/types/enable_if• http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html
15.6 Silent Degredation
Unter silent degredation bzw. “incomplete instantiation” versteht man folgendesPrinzip: Wenn eine Member-Methode einer Template-Klasse nie verwendet wird,so wird diese auch niemals instanziiert. (Alexandrescu 2000, S.13)
Damit lassen sich also höher-geordnete Klassen schreiben, die nach wie vor kom-pilierfähig bleiben, obwohl einige ihrer Member-Methoden eigentlich ill-formedwären – aber nur, falls diese benutzt werden würden!
15.6. SILENT DEGREDATION 131
15.6.1 Beispiel
Angenommen man hat eine Klasse DoItAll mit folgender implementation:
1 template <class Type>2 class DoItAll {3 Type member_;45 public:67 /* CTOR, DTOR */8 DoItAll(Type t): member_{t} {}9 ~DoItAll() {}
1011 /* Methods */12 inline Type plus(Type other) const { return member_ + other; }13 inline Type div(Type other) const { return member_ / other; }14 };
Angenommen, DoItAll würde folgendermaßen genutzt werden:
1 DoItAll<int> doitall_int{8};23 std::cout << doitall_int.plus(34) << std::endl; // 424 std::cout << doitall_int.div(4) << std::endl; // 2
Oder auch so:
1 DoItAll<std::string> doitall_str{"this is"};23 std::cout << doitall_str.plus(" a string") << std::endl; // "this is a string"
…so wäre bis hierhin alles in Ordnung und würde sauber kompilieren – trotzdessen, dass std::string / std::string ill-formed und kein gütliger Aufrufwäre!
Das Geheimnis dahinter ist, dass Methoden von Template Klassen erst in demMoment konkret instantiiert werden, in dem sie auch tatsächlich genutzt werden,d.h. wenn an keiner Stelle doitall_str.div("some string") aufgerufen wird,wird diese Methode auch nicht instantiiert und die Klasse bleibt kompilierfähig.
Dies ist das Geheimnis hinter silent degredation bzw. “incomplete instantiation”und erlaubt wiederum sehr flexible Klassen zu gestalten.
15.6.2 Bemerkung
Mit C++11 gibt es eine Möglichkeit, Kompilierzeit zu sparen, indem manden Compiler mit extern template anweisen kann, sich darauf zu verlassen,dass eine volle Instantiierung/Spezialisierung einer Klasse an anderer Stellevorgenommen wird und an dieser Stelle nicht zu instantiieren.
Recommended