tools.subsys.Handler ... 2011-08-15 10:53:07,201 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,212 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,214 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,218 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,226 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,227 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,229 [||94] INFO translator.bar.Hrglbrmft ... HOW TO GET FROM HERE TO THERE ... 1. Separate different invocations/threads 2. Determine which log file lines belong to which layer 3. Calculate length of each invocation 4. Visualize ✔ ✔ ✔ (c) 2011 Victor Volle ([email protected])
tools.subsys.Handler ... 2011-08-15 10:53:07,201 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,212 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,214 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,218 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,226 [||94] INFO tools.subsys.Handler ... 2011-08-15 10:53:07,227 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,228 [||94] INFO translator.bar.Hrglbrmft ... 2011-08-15 10:53:07,229 [||94] INFO translator.bar.Hrglbrmft ... HOW TO GET FROM HERE TO THERE ... 1. Separate different invocations/threads 2. Determine which log file lines belong to which layer 3. Calculate length of each invocation 4.Visualize? ✔ ✔ ✔ (c) 2011 Victor Volle ([email protected])
for charts (and scientific data) as well • GraphViz • better, if you need an automatic layout • Plain Old Java • Cumbersome and boring (yes, that is an important criteria) CANDIDATES (c) 2011 Victor Volle ([email protected])
foo.left = rectangle1.right foo.width = 200 and foo.right would be calculated (or vice versa) and if we could do something like ... foo.below(rectangle1, 60) foo 60px (c) 2011 Victor Volle ([email protected])
boring. • Clojure 㱺 never did grok Lisp • Ruby 㱺 aah, always wanted to really learn Ruby! • Scala flatMap [B, That] (f: (A) ⇒ Traversable[B])(implicit bf: CanBuildFrom[List[A], B, That]) : That 㱺 this is a method signature, no thanks, next time perhaps (c) 2011 Victor Volle ([email protected])
@id = ... end def begin_x ... end def end_x ... end def width ... end end graph_object.rb class name file name generate getter&setter public methods instance variable (no declaration necessary) ”constructor” (somewhat) (c) 2011 Victor Volle ([email protected])
should "be able to calculate bottom and center, if top and height are given" do go = GraphObject.new() go.top_y = 10 go.height = 30 assert_equal(40, go.bottom_y) assert_equal(25, go.center_y) end end TESTS graph_object_test.rb “import” “extends” namespace method invocation first parameter (String) second parameter (a Block) (c) 2011 Victor Volle ([email protected])
"a" => 100, "b" => 200 } map.each do |key, value| puts "#{key} is #{value}" end a block “parameter” gets invoked for each line in the file multiple parameter are possible (c) 2011 Victor Volle ([email protected])
self[i] return value if yield(value) end return nil end end [1, 3, 5, 7, 9].find {|v| v*v > 30 } ==> 7 BLOCKS invoke the block (c) 2011 Victor Volle ([email protected])
@width ... elsif defined? @center_x ... end end FIRST IDEA: PROPERTIES check which properties are defined calculate the other properties (c) 2011 Victor Volle ([email protected])
LIKE, ... what if “a.end_x” is not known (yet)? ... WE WILL ALWAYS BE ABLE TO BUILD EACH ELEMENT’S POSITION ON KNOWN POSITIONS OF OTHER ELEMENTS ... (c) 2011 Victor Volle ([email protected])
= $defaultHeight b.top_y = 0 b.begin_x = lambda { a.end_x + 50 } a.width = $defaultWidth a.height = $defaultHeight a.top_y = 0 a.begin_x = 0 ShowGraph.new() LAMBDA ... AND INSTANCE VARS two_rectangles.rb b.height = lambda { width * 2 } NameError: undefined local variable or method `width' for main:Object (root) at /Users/vivo/workspaces/any/vgraph2/vgraph2-base/ src/main/ruby/two_rectangles.rb:16 call at org/jruby/RubyProc.java:274 call at org/jruby/RubyProc.java:229 height at ./graph_object.rb:105 call at org/jruby/RubyProc.java:274 _bottom_y at ./graph_object.rb:217 send at org/jruby/RubyKernel.java:2092 method_missing at ./graph_object.rb:122 bounds at ./graph.rb:22 each at org/jruby/RubyArray.java:1603 bounds at ./graph.rb:20 initialize at ./show_graph.rb:19 (root) at /Users/vivo/workspaces/any/vgraph2/vgraph2-base/ src/main/ruby/two_rectangles.rb:20 load at org/jruby/RubyKernel.java:1063 (root) at -e:1 (c) 2011 Victor Volle ([email protected])
to get into the scope of that object ... SECOND IDEA b.height = lambda { width * 2 } b.height = lambda { b.width * 2 } (c) 2011 Victor Volle ([email protected])
to get into the scope of that object ... SECOND IDEA b.height = lambda { width * 2 } b.height = lambda { b.width * 2 } class << b def height; width * 2 end end the class of object ‘b’ (c) 2011 Victor Volle ([email protected])
a Class class class height() Graph- Object @name b class a Object Class class class height() Graph- Object @name b class super- class (c) 2011 Victor Volle ([email protected])
a Class class class height() Graph- Object @name b class a Object Class class class height() Graph- Object @name b class super- class a Object Class Module class class height() Graph- Object @name b class super- class super- class (c) 2011 Victor Volle ([email protected])
a Class class class height() Graph- Object @name b class a Object Class class class height() Graph- Object @name b class super- class a Object Class Module class class height() Graph- Object @name b class super- class super- class a Object Class Module class class height() Graph- Object @name b class super- class super- class class super- class class (c) 2011 Victor Volle ([email protected])
Object @name b class super- class super- class class super- class class height() << b super- class a “singleton” class, or “eigenclass” (c) 2011 Victor Volle ([email protected])
to get into the scope of that object ... SECOND IDEA b.height = lambda { width * 2 } b.height = lambda { b.width * 2 } class << b def height; @width * 2 end end the class of object ‘b’ but now ‘height’ is a method (c) 2011 Victor Volle ([email protected])
width elsif ... else raise InsufficientDefinitionError ... end ... end end SECOND IDEA: METHODS is the method defined? return value (a symbol) throw ... (c) 2011 Victor Volle ([email protected])
width elsif ... else raise InsufficientDefinitionError ... end ... end end SECOND IDEA: METHODS but if we define ‘end_x’ ... (c) 2011 Victor Volle ([email protected])
width elsif ... else raise InsufficientDefinitionError ... end ... end end SECOND IDEA: METHODS this will be true (c) 2011 Victor Volle ([email protected])
width elsif ... else raise InsufficientDefinitionError ... end ... end end SECOND IDEA: METHODS this will be true D’oh! (c) 2011 Victor Volle ([email protected])
... ... method_missing SECOND IDEA+ def _begin_x ... def _end_x ... def method_missing(method_symbol, *args, &block) method_name = method_symbol.to_s internal_meth = "_#{method_name}" send internal_meth end method_missing gets invoked whenever a method is called, that is not defined (remember, we use a dynamic language) (c) 2011 Victor Volle ([email protected])
go.end_x + $x } go2.width = 100 if width and begin_x are now methods (kinda), can we assign values to them? but width= and begin_x= are methods (c) 2011 Victor Volle ([email protected])
value.call() end else self.eigenclass.send(:define_method, “begin_x”) do value end end end setter a lambda (or something very much alike) creates a new method (c) 2011 Victor Volle ([email protected])
else self.eigenclass.send(:define_method, “end_x”) do value end end end SECOND IDEA++ since all setters are nearly alike, we again use method_missing (c) 2011 Victor Volle ([email protected])
(1) def _begin_x if self.respond_to? :end_x if self.respond_to? :width ... if “begin_x” is called (and not defined), method_missing will be called: def method_missing(method_symbol, *args, &block) # method_name = method_symbol.to_s ... internal_meth = "_#{method_name}" send internal_meth (c) 2011 Victor Volle ([email protected])
lambda { a.end_x + $x } b.width = 100 if “begin_x” is called (and not defined), method_missing will be called: if value.respond_to? :call self.eigenclass.send(:define_method, getter_name) do value.call() end else # self.eigenclass.send(:define_method, getter_name) do value end end (c) 2011 Victor Volle ([email protected])
the fly • We can add/replace methods on each objects • We can have methods like ‘findByNameAndAddress” that are implemented on the fly by using “method_missing” • classes are objects, functions are objects • all these are very powerful and dangerous mechanisms (lets replace “wait()” on class “Object” in Java while multiple threads are running ...) (c) 2011 Victor Volle ([email protected])