Metaprogrammierung und Reflection

42
Wer nutzt die PHP-Reflection API? Und für was?

Transcript of Metaprogrammierung und Reflection

Page 1: Metaprogrammierung und Reflection

Wer nutzt die PHP-Reflection API?Und für was?

Page 2: Metaprogrammierung und Reflection

Fragen können jederzeit gestellt werden

Page 3: Metaprogrammierung und Reflection

Metaprogrammierung und Reflection

Tool-Entwicklung für und mit PHP

Stefan Marr PHP Unconference

26./27. April 2008

Page 4: Metaprogrammierung und Reflection

1. Begriffsklärung

2. Open Implementations– Metaprogrammierung und Frameworkdesign

3. Relevante Sprachfeatures von PHP

4. Reflection und Runkit für die Tool-Entwicklung

5. Zusammenfassung

Agenda

Page 5: Metaprogrammierung und Reflection

METAPROGRAMMIERUNG UND REFLECTION

Kurze Begriffsklärung zur Einleitung

Page 6: Metaprogrammierung und Reflection

Verarbeitendes SystemComputational

System

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world)

reasons aboutand acts upon

representation of/returning information about

• Daten repräsentieren Domäne• Programm beschreibt

Veränderungen• Interpreter führt Programm aus

• Domäne• Buchhaltung, Kundendaten,

Logistik, Webinhalte, …

nach [1]

Page 7: Metaprogrammierung und Reflection

Kausal verbundenes System

• Ursache-Wirkungsbeziehung zwischen System und Domäne

• Direkte wechselseitige Auswirkungen

• Regellungstechnik• Klimaanlagen• Autopiloten• …

ComputationalSystem

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world)

reasons aboutand acts upon

causally connectedrepresentation

nach [1]

Page 8: Metaprogrammierung und Reflection

Meta-System

• Spezielle Domäne: Programme• Meta-Programme und -system

arbeiten auf Basis-Programmen und -systemen

• Compiler• Code-Transformation,

Generierung• …

Base System

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world )

reasons aboutand acts upon

representation of/returning information about

Meta System

Interpreter

State(Data)

Behavior(Program )

reasons aboutand acts upon

representation of/returning information about

nach [1]

Page 9: Metaprogrammierung und Reflection

Reflektives System

• Spezielle Meta-Systeme• Selbstrepräsentation bestimmter

Strukturen• Kausal verbunden

• Reflektives Verhalten• Introspection (beobachten)• Intercession

(Selbstveränderung)

ComputationalSystem

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world )

reasons aboutand acts upon

causally connectedrepresentation

reasons aboutand acts upon

representation of/returning information about

nach [1]

Page 10: Metaprogrammierung und Reflection

Meta- und Reflektive SystemeComputational

System

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world)

reasons aboutand acts upon

representation of/returning information about

ComputationalSystem

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world)

reasons aboutand acts upon

causally connectedrepresentation

Base System

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world )

reasons aboutand acts upon

representation of/returning information about

Meta System

Interpreter

State(Data)

Behavior(Program )

reasons aboutand acts upon

representation of/returning information about

ComputationalSystem

Interpreter

State(Data)

Behavior(Program )

Domain(some part of the world )

reasons aboutand acts upon

causally connectedrepresentation

reasons aboutand acts upon

representation of/returning information about

Kausal verbunden

Meta-System

Reflektiv

nach [1]

Page 11: Metaprogrammierung und Reflection

OPEN IMPLEMENTATIONSMetaprogrammierung und Moduldesign

Page 12: Metaprogrammierung und Reflection

• Verstecken von Implementierungsdetails– Vereinfachung des Client-

Codes• Verringerung von

Abhängigkeiten zwischen Modulen und Clients– Erhöhung der

Wiederverwendbarkeit– Client-Code lesbarer und

verständlich ohne Wissen über unterliegende Implementierung

Abstraktion in einer Black Box

Page 13: Metaprogrammierung und Reflection

• Geeignete Implementierungsstrategie abhängig von der Art der Nutzung des Moduls

• Implementierungs-entscheidungen – selten dokumentiert– für bestimmte Fälle

ungeeignet– nicht anpassbar– zu starke Abstraktion

• Client weiß meist am besten welche Strategie geeignet wäre

Probleme der Black Box

Page 14: Metaprogrammierung und Reflection

• Implementierungs-entscheidungen nicht im Interface sichtbar, aber:– Performanceauswirkungen

• Abbildung von High-Level auf Low-Level Funktionen vielfältig möglich– Beeinflussen Performance– Entscheidung daher

feststehend, aber nicht verborgen

Keine 100%ige Black Box möglich

Page 15: Metaprogrammierung und Reflection

• Neuimplementierung von Interfacefunktionen– Um gewünschte Eigenschaften zu

erreichen– Code wird größer und komplexer

• „Code zwischen den Zeilen“– Behandelt Probleme die eigentlich

vom Interface verborgen werden sollten

– Basiert auf undokumentierten Interna, verborgen vom Interface, aber dem Programmierer bekannt

Probleme und Workarounds

Page 16: Metaprogrammierung und Reflection

Lösung: Reflektive Module

Basis Interface

• Bietet Funktionalität an

• Das WASMeta Interface• Ermöglicht Steuerung

des Basis Interfaces• Das WIE

Page 17: Metaprogrammierung und Reflection

Reflektive Module/Programme

• Vorteile– Schnittstellennutzung

jetzt wieder als Black Box– Konfiguration bzw.

Implementierungsstrategie der Black Box vom Client wählbar

• Programmierer können sich auf Modulnutzung konzentrieren

• Optimierung/Konfiguration separat möglich

Page 18: Metaprogrammierung und Reflection

• Frameworks– Aufteilung in Client API und Framework API

– Konfigurationsdateien, Konstanten, Parameter, Flags, …

• Dependency Injection als Pattern verbreitet

• Funktionen mit Callbacks altbekannt

Umsetzungsmöglichkeiten

Page 19: Metaprogrammierung und Reflection

• Frameworks sollten Erweiterungs- bzw. Spezialisierungspunkte anbieten– Problematische Teile vom Client anpassbar

• Anpassung, Konfiguration über Meta-APIs

• Design trotzdem nicht mit den zu kapselnden Details überfrachten– Auf geeignete Trennung zwischen WAS und WIE

achten

ZusammenfassungOpen Implementations

Page 20: Metaprogrammierung und Reflection

RELEVANTE SPRACHFEATURES VON PHP

Magic Methods und die Reflection API

Page 21: Metaprogrammierung und Reflection

• Dynamische Object-Properties– __g e t ( ) , __s e t ( )

• Werden verwendet wenn die angefragten Properties nicht vorhanden sind

• z. B. für Validierung und Vermeidung von unspezifizierten Properties

• __i s s e t ( ) , __u n s e t ( )

• __c l o n e ( ) : ändert Semantik von c l o n e• __t o S t r i n g ( ) , __s l e e p ( ) ,

__wa k e u p ( ) , __s e t _s t a t e ( )

Magic Methods

Page 22: Metaprogrammierung und Reflection

• __a u t o l o a d ( $ c l a s s Na me )– Ermöglicht echtes Lazy-loading von Klassen

– Implementiert eigene Laderoutine

• __c a l l ( $ me t h o d Na me , $ a r g s )– Ermöglicht echtes Late-Binding

– Instanzverhalten zur Laufzeit entscheidbar

• __c a l l S t a t i c ( $ me t h o d Na me , $ a r g s )– La t e - Bi n d i n g f ü r Kl a s s e n me t h o d e n

Magic Methods

Page 23: Metaprogrammierung und Reflection

Reflection APIKlassendiagramm der Reflection API von PHP 5.2

+getName() : string+isPublic () : bool+isPrivate() : bool+isProtected() : bool+isStatic () : bool+isDefault() : bool+getModifiers() : int+getValue(in object : object) : mixed+setValue(in object : object, in value : mixed)+getDeclaringClass() : ReflectionClass+getDocComment() : string

ReflectionProperty

+getName() : string+isInternal() : bool+isUserDefined() : bool+isInstantiable () : bool+hasConstant(in name : string) : bool+hasMethod(in name : string) : bool+hasProperty(in name : string) : bool+getFileName() : string+getStartLine() : int+getEndLine() : int+getDocComment() : string+getConstructor() : ReflectionMethod+getMethod(in name : string) : ReflectionMethod+getMethods() : ReflectionMethod[]+getProperty(in name : string) : ReflectionProperty+getProperties() : ReflectionProperty[]+getConstants() : array+getConstant(in name : string) : mixed+getInterfaces() : ReflectionClass[]+isInterface() : bool+isAbstract() : bool+isFinal() : bool+getModifiers() : int+isInstance(in object : object) : bool+newInstance(in args : mixed) : object+newInstanceArgs(in args : array) : object+getParentClass() : ReflectionClass+isSubclassOf (in class : ReflectionClass) : bool+getStaticProperties() : array+getStaticPropertyValue(in name : string, in default : mixed = null) : mixed+setStaticPropertyValue(in name : string, in value : mixed)+getDefaultProperties() : array+isIterateable() : bool+implementsInterfaces(in name : string) : bool+getExtension() : ReflectionExtension+getExtensionName() : string

ReflectionClass

ReflectionObject

+invoke(in object : object, in ... : mixed) : mixed+invokeArgs(in object : object, in args : mixed) : mixed+isFinal() : bool+isAbstract() : bool+isPublic () : bool+isPrivate() : bool+isProtected() : bool+isStatic () : bool+isConstructor() : bool+isDestructor() : bool+getModifiers() : int+getDeclaringClass() : ReflectionClass

ReflectionMethod

+getName() : string+isPassedByReference() : bool+getDeclaringClass() : ReflectionClass+getClass() : ReflectionClass+isArray() : bool+allowsNull() : bool+isPassedByReference() : bool+isOptional () : bool+isDefaultValueAvailable () : bool+getDefaultValue() : mixed

ReflectionParameter

+getName() : string+getVersion() : string+getFunctions() : ReflectionFunction[]+getConstants() : array+getINIEntries() : array+getClasses() : ReflectionClass[]+getClassNames() : array+info() : string

ReflectionExtension

+getName() : string+isInternal() : bool+isDisabled() : bool+isUserDefined() : bool+getFileName() : string+getStartLine() : int+getEndLine() : int+getDocComment() : string+getStaticVariables() : array+invoke(in args : mixed, in ... : mixed) : mixed+invokeArgs() : mixed+returnsReference() : bool+getParameters() : ReflectionParameter[]+getNumberOfParameters() : int+getNumberOfRequiredParameters() : int

ReflectionFunction

func_get_arg()func_get_args()func_num_args()is_subclass_of()get_parent_class()get_class()get_class_methods()get_object_vars()get_class_vars()class_exists()interface_exists()function_exists()method_exists()property_exists ()get_declared_classes()get_declared_interfaces()get_included_files()get_required_files()ini_set()ini_get()get_defined_constants()get_defined_functions()get_defined_vars()call_user_func()call_user_func_array()create_function()eval()

<<functions>>

Page 24: Metaprogrammierung und Reflection

ReflectionPropertyReflectionClass

ReflectionObject

ReflectionMethod

ReflectionParameter

ReflectionExtension

func_get_arg()func_get_args()func_num_args()is_subclass_of()get_parent_class ()get_class()get_class_methods()get_object_vars()get_class_vars()class_exists()interface_exists()function_exists()method_exists()property_exists ()get_declared_classes()get_declared_interfaces()get_included_files()get_required_files()ini_set()ini_get()get_defined_constants()get_defined_functions()get_defined_vars()call_user_func()call_user_func_array()create_function()eval()

<<functions>>

ReflectionFunction

Page 25: Metaprogrammierung und Reflection

ReflectionPropertyReflectionClass

ReflectionObject

ReflectionMethod

ReflectionParameter

ReflectionExtension

func_get_arg()func_get_args()func_num_args()is_subclass_of()get_parent_class()get_class()get_class_methods()get_object_vars()get_class_vars()class_exists()interface_exists()method_exists ()property_exists()get_declared_classes ()get_declared_interfaces()get_included_files()get_required_files()ini_set()ini_get()get_defined_constants()get_defined_functions()get_defined_vars()

<<functions>>

ReflectionFunction

PHP System Runtime Data

ReflectionPHP Core

Classes Objects ...

PH

P V

irtu

al M

achi

ne

with

Sys

tem

Lev

el E

xte

nsio

ns

Page 26: Metaprogrammierung und Reflection

REFLECTION UND RUNKIT FÜR DIE TOOL-ENTWICKLUNG MIT PHP

phpCrow, ezcReflection und isvcRunkit

Page 27: Metaprogrammierung und Reflection

splash

Page 28: Metaprogrammierung und Reflection

• Generierten Code ausführen: e v a l ( )

• Funktionen erstellen: c r e a t e _f u n c t i o n ( )

• Dynamische Aufrufe:– c a l l _u s e r _f u n c t i o n ( )– c a l l _u s e r _f u n c t i o n _a r r a y ( )– c a l l _u s e r _me t h o d ( )– c a l l _u s e r _me t h o d _a r r a y ( )– $ f u n c t i o n Na me ( $ a , $ b ) ;

Intercession mit Standard-PHP

Page 29: Metaprogrammierung und Reflection

$ f u n c = c r e a t e _f u n c t i o n ( ' $ f o o , $ b a r ' ,' e c h o " Cr e a t e d F u n c t i o n : $ f o o

$ b a r \n " ; ' ) ;$ f u n c ( ' He l l o ' , ' Wo r l d ! ' ) ;v a r _d u mp ( a d d s l a s h e s ( $ f u n c ) ) ;c a l l _u s e r _f u n c ( $ f u n c , ' F OO' , ' b a z ' ) ;

/ / c o mmo n us ag e e xampl e , wi t h pe r f o r manc e i s s ue s !$ a v = a r r a y ( ' t h e ' , ' a ' , ' t h a t ' , ' t h i s ' ) ;a r r a y _wa l k ( $ a v ,

c r e a t e _f u n c t i o n ( ' &$ v , $ k ' , ' $ v = $ v . " ma n g o " ; ' ) ) ;

p r i n t _r ( $ a v ) ;

create_function

Page 30: Metaprogrammierung und Reflection

c l a s s I n v o k e Te s t {p u b l i c f u n c t i o n c a l l Me ( ) {

e c h o " Ye a h , y o u c a l l e d me ! \n " ;}

}

$ o = n e w I n v o k e Te s t ( ) ;$ c l a s s = n e w Re f l e c t i o n Cl a s s ( $ o ) ;$ me t h o d = $ c l a s s - >g e t Me t h o d ( ' c a l l Me ' ) ;$ me t h o d - >i n v o k e ( $ o ) ;

f u n c t i o n f o o F u n c ( $ b a r ) {e c h o " $ b a r \n " ;

}$ f u n c = ' f o o F u n c ' ;$ f u n c ( ' He l l o Wo r l d ' ) ;

Funktionen/Methoden Aufrufe

Page 31: Metaprogrammierung und Reflection

+getAnnotations()+hasAnnotation()+getType()

ezcReflectionProperty

+getAnnotations()+hasAnnotation()

ezcReflectionClass

+getAnnotations()+hasAnnotation()+getReturnType()+isMagic()+isInherited()+isOveridden()+isIntroduced()

ezcReflectionMethod

+getType()

ezcReflectionParameter

ezcReflectionClassType

«interface»ezcReflectionType

ezcReflectionAbstractType

ezcReflectionPrimitiveType ezcReflectionArrayType

ReflectionProperty ReflectionClass ReflectionMethod ReflectionParameter

ezcReflection

Page 32: Metaprogrammierung und Reflection

+getAnnotations()+hasAnnotation()+getType()

ezcReflectionProperty

+getAnnotations()+hasAnnotation()

ezcReflectionClass

+getAnnotations()+hasAnnotation()+getReturnType()+isMagic()+isInherited()+isOveridden()+isIntroduced()

ezcReflectionMethod

+getType()

ezcReflectionParameter

ezcReflectionClassType

«interface»ezcReflectionType

ezcReflectionAbstractType

ezcReflectionPrimitiveType ezcReflectionArrayType

ReflectionProperty ReflectionClass ReflectionMethod ReflectionParameter

ezcReflection

Page 33: Metaprogrammierung und Reflection

+getAnnotations()+hasAnnotation()+getType()

ezcReflectionProperty

+getAnnotations()+hasAnnotation()

ezcReflectionClass

+getAnnotations()+hasAnnotation()+getReturnType()+isMagic()+isInherited()+isOveridden()+isIntroduced()

ezcReflectionMethod

+getType()

ezcReflectionParameter

ezcReflectionClassType

«interface»ezcReflectionType

ezcReflectionAbstractType

ezcReflectionPrimitiveType ezcReflectionArrayType

ReflectionProperty ReflectionClass ReflectionMethod ReflectionParameter

ezcReflection

Page 34: Metaprogrammierung und Reflection

ezcReflection

PHP Core Functions Reflection API

PHP System Runtime DataClasses Objects ...

PH

P V

M

ezcReflection

+getAnnotations()+hasAnnotation()+getType()

ezcReflectionProperty

+getAnnotations()+hasAnnotation()

ezcReflectionClass

+getAnnotations()+hasAnnotation()+getReturnType()+isMagic()+isInherited()+isOveridden()+isIntroduced()

ezcReflectionMethod

+getType()

ezcReflectionParameter

ezcReflectionClassType

«interface»ezcReflectionType

ezcReflectionAbstractType

ezcReflectionPrimitiveType ezcReflectionArrayType

ReflectionProperty ReflectionClass ReflectionMethod ReflectionParameter

PH

P L

angu

age

Leve

l Im

ple

men

tatio

ns

Page 35: Metaprogrammierung und Reflection

ezcReflection Überblick

• Ermöglicht Reflection auf PHPDoc-Annotationen

• Erweiterte Typ-Informationen zur Laufzeit

• Aber keine direkten Laufzeit-Einflüsse der Typ-Annotationen

• Design ermöglicht beliebige Erweiterungen der Reflection API als Datenquelle mit zu nutzen– z. B. eine StaticReflection

• Genutzt für z. B. WSDL Generierung

Page 36: Metaprogrammierung und Reflection

/ * ** @we bs e r v i c e* /c l a s s He l l o Wo r l d {

/ * ** @var s t r i ng* /p r i v a t e $ h e l l o = ' He l l o ' ;/ * ** @par am s t r i ng $ name* @r e t ur n s t r i ng* @we bme t ho d* /p u b l i c f u n c t i o n g e t Gr e e t i n g ( $ n a me ) {

r e t u r n " $ t h i s - >h e l l o $ n a me ! " ;}

}

Annotationen

Page 37: Metaprogrammierung und Reflection

Intercession mit Runkit

func_get_arg()func_get_args()func_num_args()is_subclass_of()get_parent_class()get_class()get_class_methods()get_object_vars()get_class_vars()class_exists()interface_exists()method_exists ()property_exists()get_declared_classes()get_declared_interfaces()get_included_files()get_required_files()ini_set()ini_get()get_defined_constants()get_defined_functions()get_defined_vars()

<<functions>>

PHP System Runtime Data

ReflectionPHP Core

Classes Objects ...

PH

P V

irtu

al M

achi

ne

with

Sys

tem

Lev

el E

xte

nsio

ns

runkit_class_adopt()runkit_class_emancipate()runkit_constant_add()runkit_constant_redefine()runkit_constant_remove()runkit_function_add()runkit_function_copy()runkit_function_redefine()runkit_function_remove()runkit_function_rename()runkit_import()runkit_lint_file()runkit_lint()runkit_method_add()runkit_method_copy()runkit_method_redefine()runkit_method_remove()runkit_method_rename()runkit_return_value_used()runkit_sandbox_output_handler()runkit_superglobals()

<<functions>>

Runkit

Page 38: Metaprogrammierung und Reflection

ezcReflection und isvcRunkit

PHP Core Functions

PHP System Runtime DataClasses Objects ...

PH

P V

M

isvcRunkit

+emancipate()+setParentClass()+addNewMethod()+addExistingMethod()+removeMethod()

isvcRunkitClass

+getCode()+setCode()+delete()+setName()

isvcRunkitMethod

ReflectionClass ReflectionMethod

Lang

uage

Le

vel I

mp

lem

ent

atio

ns

Reflection API Runkit Extension

ezcReflection

Page 39: Metaprogrammierung und Reflection

ZUSAMMENFASSUNGMetaprogramming und Reflection

Page 40: Metaprogrammierung und Reflection

• PHP hat viele Features um Reflection einzusetzen

• Intercession über Runkit-Extension– Vorallem für Tool-Entwicklung

• Reflection hat Einflüsse auf Performance– PHP Ausführungsmodell beachten

– Besonders in Web-Anwendungen nicht erste Wahl

• Nützlich für länger lebende Prozesse/Programme– z. B. GTK+, QT, MFC oder Kommandozeilen-

Anwendungen

Zusammenfassung

Page 41: Metaprogrammierung und Reflection

Literatur

Paper zu diesem VortragG. GABRYSIAK, S. MARR, AND F. MENGE, Meta Programming and Reflection in PHP, Hasso-Plattner Institute, Universiy of Potsdam, Germany, February 2008. https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/metaprogramming/doc/

Der CodephpCrow – A PHP-PHP-IDE, February 2008.

https://instantsvc.svn.sourceforge.net/svnroot/instantsvc/branches/metaprogramming/src/MetaPHP

ezcReflection, SVN Repository, eZ Components, January 2008. http://svn.ez.no/svn/ezcomponents/experimental/Reflection

Page 42: Metaprogrammierung und Reflection

Weitere Literatur und Software

[1] R. HIRSCHFELD, Course on "Metaprogrammierung und Reflection", 2007. Lecture Material, Non-public.

[2] G. BRACHA AND D. UNGAR, Mirrors: design principles for meta-level facilities of object-oriented programming languages, in OOPSLA '04: Proceedings of the 19th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications, New York, NY, USA, 2004, ACM, pp. 331–344.

[3] S. GOLEMON, Runkit, PHP Extension, The PHP Group, January 2008. http://pecl.php.net/package/runkit

[4] A. P. GREGOR KICZALES, Open Implementations and Metaobject Protocols, MIT Press, Cambridge, MA, USA, 1996. http://www2.parc.com/csl/groups/sda/publications/papers/Kiczales-TUT95/for-web.pdf

[5] PHP DOCUMENTATION GROUP, PHP Manual, documentation, November 2007. http://www.php.net/manual/en/language.oop5.reflection.php

[6] THE PHP GROUP, PHP Extension Community Library, Project Site, January 2008. http://pecl.php.net/