SlideShare une entreprise Scribd logo
1  sur  60
Télécharger pour lire hors ligne
Interpreter 
implementation 
               of
                     Immad Naseer,
 advice weaving      Ryan Golbeck and
                     Gregor Kiczales.
                     University of British Columbia



                                                      1
Aspect­oriented programming (AOP)
provides linguistic mechanisms for modularizing 
crosscutting concerns.




                                                   2
Let's look at an example
Consider a web application with two kinds of users: administrators and regular 
users. We have to ensure that certain functionality can only be accessed by 
administrators and the rest only by a logged in user.




                                                                                  3
public class AdminController {
  public void handleCreateUser() {
    if(getLoggedInUser() == null || !getLoggedInUser().isAdmin())
      throw new AccessViolationException();

        // rest of code
    }

    public void handleRemoveUser() {
      if(getLoggedInUser() == null || !getLoggedInUser().isAdmin())
        throw new AccessViolationException();

        // rest of code
    }
}



             public class ProductController {
               public void handleBuyProduct() {
                 if(getLoggedInUser() == null)
                   throw new AccessViolationException();

                     // rest of code
                 }

                 public void handleSellProduct() {
                   if(getLoggedInUser() == null)
                     throw new AccessViolationException();

                     // rest of code
                 }
             }                                                        4
Access authorization
public aspect AccessAuthorization {

    before(): call(* *Controller.handle*(..))
          { ... }

    before(): call(* AdminController.handle*(..))
          { ... }

    after returning(User user):
                   call(void User.login(..)) &&
                   target(user)
          { ... }

    after returning(User user):
                   call(void User.logout(..)) &&
                   target(user)
          { ... }
}

                                                    5
Access authorization
public aspect AccessAuthorization {

    before(): call(* *Controller.handle*(..))
          { ... }

    before(): call(* AdminController.handle*(..))
          { ... }

    after returning(User user):
                   call(void User.login(..)) &&
                   target(user)
          { ... }

    after returning(User user):
                   call(void User.logout(..)) &&
                   target(user)
          { ... }
}

                                                    6
Access authorization
public aspect AccessAuthorization {

    before(): call(* *Controller.handle*(..))
          { ... }

    before(): call(* AdminController.handle*(..))
          { ... }

    after returning(User user):
                   call(void User.login(..)) &&
                   target(user)
          { ... }

    after returning(User user):
                   call(void User.logout(..)) &&
                   target(user)
          { ... }
}

                                                    7
Access authorization
public aspect AccessAuthorization {

    before(): call(* *Controller.handle*(..))
          { ... }

    before(): call(* AdminController.handle*(..))
          { ... }

    after returning(User user):
                   call(void User.login(..)) &&
                   target(user)
          { ... }

    after returning(User user):
                   call(void User.logout(..)) &&
                   target(user)
          { ... }
}

                                                    8
Terminology
                                            advice

before(): call(* User.login(..)) { ...
}



     pointcut                public void testProductBuy() {
                               u = User.find(“joe”);
                               u.login(“pass”);
                               ...
                               Product.buy(u, 12);
    join point shadows
                               ...
                             }

                                                         9
Terminology
                                            advice

before(): call(* User.login(..)) { ...
}



     pointcut                public void testProductBuy() {
                               u = User.find(“joe”);
                               u.login(“pass”);
                               ...
                               Product.buy(u, 12);
    join point shadows
                               ...
                             }

                                                         10
Advice weaving
coordinates execution of advice around, before or 
after applicable join points.




                                                     11
Rewriting based advice weaving
approaches rewrite the code    public void testProductBuy() {
at potentially advised join        u = User.find(“joe”);
point shadows (JPS) to             before_advice();
                                   u.login(“pass”);
invoke the advice (guarded         ...
by residual dynamic checks)        if (some_guard())
                                       some_other_before_advice();
                                   Product.buy(u, 12);
                                   }
                               }




                                                                     12
Rewriting based advice weaving
approaches rewrite the code    public void testProductBuy() {
at potentially advised join        u = User.find(“joe”);
point shadows (JPS) to             before_advice();
                                   u.login(“pass”);
invoke the advice (guarded         ...
by residual dynamic checks)        if (some_guard())
                                       some_other_before_advice();
                                   Product.buy(u, 12);
                                   }
                               }




                                                                     13
Rewriting based advice weaving
approaches rewrite the code    public void testProductBuy() {
at potentially advised join        u = User.find(“joe”);
point shadows (JPS) to             before_advice();
                                   u.login(“pass”);
invoke the advice (guarded         ...
by residual dynamic checks)        if (some_guard())
                                       some_other_before_advice();
                                   Product.buy(u, 12);
                                   }
                               }




                                                                     14
When (and how) to weave?
                                  interpreter 
compile time          load time        JIT




           runtime boundary




                                                 15
When (and how) to weave?
                                                          interpreter 
compile time                load time                          JIT

  eg. ajc



Rewrites the bytecode or source code of the application at compile time

+ no scanning and rewriting overhead at runtime

­ no “late weaving”

­ requires a global scan of the program ==> 
                               not suited for incremental development
                                                                          16
When (and how) to weave?
                                                 interpreter 
compile time              load time                   JIT

                          eg. ajc ltw



Rewrites the bytecode as part of class loading

+ allows “late weaving”

­ scanning and rewriting overhead at runtime ==>
           leads to slower applications startup

­ not suited for incremental development
                                                                17
When (and how) to weave?
                                           interpreter 
 compile time         load time                 JIT




Rewriting based weaving can impact application startup.




                                                          18
When (and how) to weave?
                                               interpreter 
 compile time            load time                  JIT




Non­rewriting based weaving can lead to faster startup but at the 
cost of reduced execution efficiency.

It has to do advice lookup and potential execution at each join point 
(note: NOT join point shadow!)

                                                                         19
When (and how) to weave?
                                              interpreter 
 compile time          load time                   JIT




VMs face a similar tradeoff between application startup and good 
steady state performance which is why they use the interpreter/JIT 
combination.




                                                                      20
When (and how) to weave?
                                               interpreter 
 compile time           load time                   JIT




We believe that having a combination of interpreter based non­
rewriting weaving and JIT based rewriting weaving might balance the 
startup/steady state efficiency trade off for aspect­oriented programs.




                                                                          21
When (and how) to weave?
                                                interpreter 
 compile time            load time                   JIT




In this talk, we focus on the interpreter part of the equation and present 
the design, implementation and evaluation of an interpreter based non­
rewriting weaver.




                                                                              22
Interpreter based weaving
­ should require minimum to no work from the static compiler

­ should require minimum work from the class loader

­ should “fail fast”

    (as data shows most join points are not advised)




                                                               23
An example

before(): call(* *Controller.handle*(..)) { ... }
                                                               advice
before(): call(* AdminController.handle*(..)) { ... }
after returning(User u): call(* User.login(..)
                         && target(u) { ... }
after returning(User u): call(* User.logout(..))
                         && target(u) { ... }



             invokevirtual   void   Database.establishConnection();
joinpoint    invokevirtual   void   PrintStream.println(..);
             invokevirtual   void   User.login(..);
stream
             invokevirtual   void   AdminController.handleCreateUser();
             invokevirtual   void   Logger.warn();
                                                                        24
An example
before(): call(* *Controller.handle*(..)) { ... }
before(): call(* AdminController.handle*(..)) { ... }
after returning(User u): call(* User.login(..)
                         && target(u) { ... }
after returning(User u): call(* User.logout(..))
                         && target(u) { ... }



             invokevirtual   void   Database.establishConnection();
             invokevirtual   void   PrintStream.println(..);
             invokevirtual   void   User.login(..);
             invokevirtual   void   AdminController.handleCreateUser();
             invokevirtual   void   Logger.warn();
                                                                    25
An example
before(): call(* *Controller.handle*(..)) { ... }
before(): call(* AdminController.handle*(..)) { ... }
after returning(User u): call(* User.login(..)
                        && target(u) { ... }
after returning(User u): call(* User.logout(..))
                        && target(u) { ... }



             invokevirtual   void   Database.establishConnection();
             invokevirtual   void   PrintStream.println(..);
             invokevirtual   void   User.login(..);
             invokevirtual   void   AdminController.handleCreateUser();
             invokevirtual   void   Logger.warn();
                                                                    26
Looking up advice at a join point
before(): call(* *Controller.handle*(..)) { ... }
before(): call(* AdminController.handle*(..)) { ... }
after returning(User u): call(* User.login(..)
                        && target(u) { ... }
after returning(User u): call(* User.logout(..))
                        && target(u) { ... }



             invokevirtual   void   Database.establishConnection();
             invokevirtual   void   PrintStream.println(..);
             invokevirtual   void   User.login(..);
             invokevirtual   void   AdminController.handleCreateUser();
             invokevirtual   void   Logger.warn();
                                                                    27
What property to dispatch on?
  before(): call(* *Controller.handle*(..)) { ... }
                                                               Static type of 
  before(): call(* AdminController.handle*(..)) { ... }
                                                               target type 
  after returning(User u): call(* User.login(..)               pattern
                             && target(u) { ... }
  after returning(User u): call(* User.logout(..))
                             && target(u) { ... }



                  invokevirtual   void   Database.establishConnection();
Static type of 
                  invokevirtual   void   PrintStream.println(..);
target            invokevirtual   void   User.login(..);
                  invokevirtual   void   AdminController.handleCreateUser();
                  invokevirtual   void   Logger.warn();
                                                                              28
What property to dispatch on?
 before(): call(* *Controller.handle*(..)) { ... }
                                                           Target name 
 before(): call(* AdminController.handle*(..)) { ... }
                                                           pattern
 after returning(User u): call(* User.login(..)
                         && target(u) { ... }
 after returning(User u): call(* User.logout(..))
                         && target(u) { ... }



              invokevirtual   void   Database.establishConnection();
Target name
              invokevirtual   void   PrintStream.println(..);
              invokevirtual   void   User.login(..);
              invokevirtual   void   AdminController.handleCreateUser();
              invokevirtual   void   Logger.warn();
                                                                      29
What property to dispatch on?
 before(): call(* *Controller.handle*(..)) { ... }
                                                           Return type 
 before(): call(* AdminController.handle*(..)) { ... }
                                                           pattern
 after returning(User u): call(* User.login(..)
                         && target(u) { ... }
 after returning(User u): call(* User.logout(..))
                         && target(u) { ... }



              invokevirtual   void   Database.establishConnection();
Return type
              invokevirtual   void   PrintStream.println(..);
              invokevirtual   void   User.login(..);
              invokevirtual   void   AdminController.handleCreateUser();
              invokevirtual   void   Logger.warn();
                                                                          30
We chose to dispatch on the 

static type of target (STT)
as it is available on all but one kind of join point.




                                                        31
Associating advice with types

Database
                  before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                  before(): call(* AdminController.handle*(..)) { ... }
Logger
                  after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                  after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                     32
Associating advice with types

                  point to no advice
Database
                           before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                           before(): call(* AdminController.handle*(..)) { ... }
Logger
                           after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                           after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                              33
Associating advice with types

Database
                  before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                  before(): call(* AdminController.handle*(..)) { ... }
Logger
                  after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                  after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                     34
Associating advice with types

Database
                  before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                  before(): call(* AdminController.handle*(..)) { ... }
Logger
                  after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                  after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                     35
When do we associate advice with 
types?
Database
                  before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                  before(): call(* AdminController.handle*(..)) { ... }
Logger
                  after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                  after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                     36
When do we associate advice with 
types?
                  Type Pattern Tables (TPTs)
Database
                  before(): call(* *Controller.handle*(..)) { ... }

PrintStream
                  before(): call(* AdminController.handle*(..)) { ... }
Logger
                  after returning(User u): call(* User.login(..)) && target(u) { ... }
User
                  after returning(User u): call(* User.logout(..)) && target(u) { ... }
AdminController




                                                                                     37
Type Pattern Table Lists (TPTL)
are constructed for each type as it is loaded by the VM 
and point to all those TPTs whose type pattern match 
the type's name




                                                           38
*.tnp list

  Consider the following advice
  before(): execution(* *.main(String)) {
                ...
  }


   Wildcard STT type pattern   Non­wildcard target name pattern




                                                                  39
We store the list of applicable advice (or no advice) in a per method
shadow cache
so that we don't have to do the advice lookup when 
seeing the same join point shadow for the second time




                                                                        40
class AdminController

    TPT List 



                AdminController TPT        *Controller TPT


                before(): call(* ...        before(): call(* ...




                                   public void createUser(String userName, String password) {
createUser's shadow cache                ...
                                    4        invokevirtual Database.establishConnection();
    4 | NOT_INITIALIZED                  ...
  12 | NULL                         12      invokevirtual AdminController.initialize(String)
  18 | thunk for calling                 ...
         advice                     18      invokevirtual AdminController.handleCreateUser(...)
                                         ...
                                                                                             41
                                   }
Implementation
We implemented our design on JikesRVM 2.9.2 including 
support for

 ­ all five kinds of advice;
 
  ­ all kinds of join points except the initialization
     family of join points and advice­execution;
   
  ­ and only the singleton aspect instantiation model



We did not implement support for thisJoinPoint and inter­type 
declarations.

                                                                 42
Baseline compiler as interpreter model


The machine code generated by a baseline compiler looks like
the unrolling of the machine code that would be run by an 
interpreter.


We don't use any information that wouldn't be available to an 
interpreter.




                                                                 43
Evaluation setup
An optimized compiled instance of JikesRVM 2.9.2 but with the 
adaptive optimization system turned off.




                                                                 44
Measuring the performance of different paths




                                               45
Measuring the performance of different paths




                                               46
Measuring the performance of different paths




                                               47
Measuring the performance of different paths




                                               48
Measuring the performance of different paths




                                               49
Measuring the performance of different paths
The per join point overhead ranges from 28% to 462%; since most 
DJPs  are unadvised, the overhead will be closer to 28% more than 
90% of  the time




                                                                     50
Comparative micro benchmarks




      unadvised                before call




                                                 51
      cflow                    multiple advice
Comparative micro benchmarks




                  unadvised
                               52
Comparative micro benchmarks




                  before call
                                53
Comparative micro benchmarks




                before call in cflow
                                       54
Comparative micro benchmarks

 The startup times of the interpreter are shorter than for the ajc ltw by
  600­700ms  across most of the benchmarks.

  The infrastructure loading cost for ajc has not been factored out and is 
   loaded in the 600­700ms headstart.

 




                                                                            55
Comparative micro benchmarks




            before call – lots of classes
                                            56
Comparative micro benchmarks
The “lots of classes” benchmark shows that the ajc ltw has to do a 
noticeable amount of work for each class that is loaded.

This benchmark is also better approximates real life applications where 
not all the code that is loaded is run.




                                                                      57
Conclusion
We presented the design, implementation and evaluation of an 
interpreter based non­rewriting weaving approach.

Our evaluation clearly shows that interpreter based non­rewriting 
weaving is feasible to implement. 

While we cannot say anything definitive about the performance of the 
complete hybrid system, the evaluation results do suggest that the 
complete hybrid system might provide a good balance between faster 
startup and good steady state performance.



                                                                     58
Questions?




             59
60

Contenu connexe

Tendances

Cut your Dependencies - Dependency Injection at Silicon Valley Code Camp
Cut your Dependencies - Dependency Injection at Silicon Valley Code CampCut your Dependencies - Dependency Injection at Silicon Valley Code Camp
Cut your Dependencies - Dependency Injection at Silicon Valley Code CampTheo Jungeblut
 
Cut your Dependencies with Dependency Injection for East Bay.NET User Group
Cut your Dependencies with Dependency Injection for East Bay.NET User Group Cut your Dependencies with Dependency Injection for East Bay.NET User Group
Cut your Dependencies with Dependency Injection for East Bay.NET User Group Theo Jungeblut
 
Enforce Consistency through Application Infrastructure
Enforce Consistency through Application InfrastructureEnforce Consistency through Application Infrastructure
Enforce Consistency through Application InfrastructureFlorin Coros
 
2010 06-24 karlsruher entwicklertag
2010 06-24 karlsruher entwicklertag2010 06-24 karlsruher entwicklertag
2010 06-24 karlsruher entwicklertagMarcel Bruch
 
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)Theo Jungeblut
 

Tendances (7)

Cut your Dependencies - Dependency Injection at Silicon Valley Code Camp
Cut your Dependencies - Dependency Injection at Silicon Valley Code CampCut your Dependencies - Dependency Injection at Silicon Valley Code Camp
Cut your Dependencies - Dependency Injection at Silicon Valley Code Camp
 
Cut your Dependencies with Dependency Injection for East Bay.NET User Group
Cut your Dependencies with Dependency Injection for East Bay.NET User Group Cut your Dependencies with Dependency Injection for East Bay.NET User Group
Cut your Dependencies with Dependency Injection for East Bay.NET User Group
 
Enforce Consistency through Application Infrastructure
Enforce Consistency through Application InfrastructureEnforce Consistency through Application Infrastructure
Enforce Consistency through Application Infrastructure
 
2010 06-24 karlsruher entwicklertag
2010 06-24 karlsruher entwicklertag2010 06-24 karlsruher entwicklertag
2010 06-24 karlsruher entwicklertag
 
Dynamic virtual evironments
Dynamic virtual evironmentsDynamic virtual evironments
Dynamic virtual evironments
 
Vaadin7
Vaadin7Vaadin7
Vaadin7
 
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)
Lego For Engineers - Dependency Injection for LIDNUG (2011-06-03)
 

En vedette

En vedette (6)

Technical application of nonwoven
Technical application of nonwovenTechnical application of nonwoven
Technical application of nonwoven
 
Kidswear categories
Kidswear categories Kidswear categories
Kidswear categories
 
Nonwovens & its applications
Nonwovens & its applicationsNonwovens & its applications
Nonwovens & its applications
 
Classification of textiles
Classification of textilesClassification of textiles
Classification of textiles
 
Kidswear
KidswearKidswear
Kidswear
 
Some lessons of Weaving
Some lessons of WeavingSome lessons of Weaving
Some lessons of Weaving
 

Similaire à AOP Weaving Techniques

JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 
Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9Ismar Silveira
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptSeok-joon Yun
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsAzul Systems, Inc.
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalDroidcon Berlin
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!Stacy Devino
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsBurt Beckwith
 
TWINS: OOP and FP - Warburton
TWINS: OOP and FP - WarburtonTWINS: OOP and FP - Warburton
TWINS: OOP and FP - WarburtonCodemotion
 
SOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietySOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietyChris Weldon
 

Similaire à AOP Weaving Techniques (20)

SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9Paradigmas de linguagens de programacao - aula#9
Paradigmas de linguagens de programacao - aula#9
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScript
 
Introduction to-java
Introduction to-javaIntroduction to-java
Introduction to-java
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
Annotation processing tool
Annotation processing toolAnnotation processing tool
Annotation processing tool
 
Modern c++
Modern c++Modern c++
Modern c++
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
 
CDI and Weld
CDI and WeldCDI and Weld
CDI and Weld
 
Gwt.create
Gwt.createGwt.create
Gwt.create
 
Thomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-finalThomas braun dependency-injection_with_robo_guice-presentation-final
Thomas braun dependency-injection_with_robo_guice-presentation-final
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!Async task, threads, pools, and executors oh my!
Async task, threads, pools, and executors oh my!
 
Mattbrenner
MattbrennerMattbrenner
Mattbrenner
 
Under the Hood: Using Spring in Grails
Under the Hood: Using Spring in GrailsUnder the Hood: Using Spring in Grails
Under the Hood: Using Spring in Grails
 
TWINS: OOP and FP - Warburton
TWINS: OOP and FP - WarburtonTWINS: OOP and FP - Warburton
TWINS: OOP and FP - Warburton
 
SOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO ProprietySOLID - Not Just a State of Matter, It's Principles for OO Propriety
SOLID - Not Just a State of Matter, It's Principles for OO Propriety
 
meet.js - QooXDoo
meet.js - QooXDoomeet.js - QooXDoo
meet.js - QooXDoo
 

Dernier

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 

Dernier (20)

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 

AOP Weaving Techniques