Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

From Programming to Modeling And Back Again

6,369 views

Published on

Is programming = modeling? Are there differences, conceptual and tool-wise? Should there be differences? What if we programmed the way we model? Or vice versa? In this slidedeck I explore this question and introduce interesting developments in the space of projectional editing and modern parser technology. This leads to the concept of modular programming languages and a new way of looking at programming. I will demonstrate the idea with tools that are available today, for example TMF Xtext, JetBrains MPS and Intentional’s Domain Workbench.

Published in: Technology

From Programming to Modeling And Back Again

  1. 1. Programming <br />from<br />to<br />Modeling<br />…and back again<br />Markus Voelter<br />Independent/itemis<br />voelter@acm.org<br />
  2. 2. A Journey…<br />
  3. 3. „Houston,<br />we have a<br />Problem!“<br />
  4. 4. Programming <br />Languages<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  5. 5. Programming <br />Languages<br />are not<br />expressive<br />enough.<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  6. 6. Programming <br />Languages<br />are not<br />high-level<br />enough.<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  7. 7. Programming <br />Languages<br />are not<br />abstract<br />enough.<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  8. 8. Programming <br />Languages<br />are not<br />domain-specific<br />enough.<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  9. 9. Programming <br />Languages<br />are not<br />enough.<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />C<br />
  10. 10. Programming <br />Languages<br />Formats<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Ruby<br />Groovy<br />Fortran<br />json<br />C<br />HTML<br />CSS<br />yaml<br />XML<br />
  11. 11. Programming <br />Languages<br />Formats<br />Frameworks<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Django<br />Ruby<br />Groovy<br />WPF<br />Fortran<br />json<br />C<br />JEE<br />JMS<br />HTML<br />CSS<br />Rails<br />yaml<br />XML<br />lift<br />
  12. 12. Programming <br />Languages<br />Formats<br />Frameworks<br />enough.<br />are not<br />Erlang<br />C# <br />C++<br />Python<br />Java<br />Django<br />Ruby<br />Groovy<br />WPF<br />Fortran<br />json<br />C<br />JEE<br />JMS<br />HTML<br />CSS<br />Rails<br />yaml<br />XML<br />lift<br />
  13. 13. not enough?<br />for what?<br />
  14. 14. not enough?<br />for what?<br />
  15. 15. not enough?<br />for what?<br />
  16. 16. So?<br />
  17. 17. Modeling<br />… Higher Level<br />… Domain Specific<br />Concepts & Notations<br />… Code Generation<br />Interpretation<br />
  18. 18. Modeling<br />… Higher Level<br />… Domain Specific<br />Concepts & Notations<br />… Code Generation<br />Interpretation<br />Solvesthe<br />Problem!<br />
  19. 19. But:<br />
  20. 20. Different Worlds<br />Programming Tools<br />!=<br />Modeling Tools <br />
  21. 21. Different Worlds<br />Modeling Tool<br />!=<br />Modeling Tool<br />
  22. 22. Different Worlds<br />Mix Models and Programs<br />
  23. 23. Different Worlds<br />Mix Models and Programs<br />AST Navigation & Query<br />
  24. 24. Different Worlds<br />Mix Models and Programs<br />AST Navigation & Query<br />Integration of 3GL code<br />
  25. 25. Different Worlds<br />Mix Models and Programs<br />AST Navigation & Query<br />Integration of 3GL code<br />Code Constraints<br />
  26. 26. pare<br />Com<br />
  27. 27. pare<br />Com<br />
  28. 28. Domain Specific<br />Notations<br />and<br />Abstractions<br />Flexible!<br />Limited!<br />Frameworks<br />Libraries<br />(Fluent) APIs<br />
  29. 29. Graphical<br />Textual<br />Forms<br />Tables<br />Limited!<br />Flexible!<br />Textual<br />Trees<br />
  30. 30. Customize<br />Generator<br />or<br />Interpreter<br />Limited!<br />Flexible!<br />Reflection<br />Meta Programs<br />Open Compilers<br />
  31. 31. Define custom<br />Query<br />or<br />Navigate<br />or<br />Transform<br />Limited!<br />Flexible!<br />AST APIs<br />Static Analysis<br />Regex<br />
  32. 32. Custom<br />Validation<br />or<br />Error Checks<br />Limited!<br />Flexible!<br />IDE plugins<br />Static Analysis<br />Open Compilers<br />
  33. 33. Different<br />Representations<br />and<br />Projections<br />Limited!<br />Flexible!<br />Text is Text<br />Code Folding<br />Tree Views<br />Visualizations<br />
  34. 34. Mixing<br />and<br />Composing<br />Languages<br />Limited!<br />Flexible?<br />Python-to-C-like<br />Internal DSLs<br />Embed-As-String<br />Specific: LINQ<br />
  35. 35. Scalable<br />Usable<br />IDE Support<br />Mature!<br />Brittle!<br />Modeling Tools…!?<br />
  36. 36. Debugging<br />Refactoring<br />Testing<br />Mature!<br />Brittle!<br />?<br />
  37. 37. Versioning<br />Diff, Merge<br />Branching<br />Mature!<br />Brittle!<br />for some tools…<br />
  38. 38. Gets the<br />Gets some<br />Job Done!<br />Jobs done.<br />some people doubt that…<br />everybody agrees…<br />
  39. 39. Why<br />the difference?<br />
  40. 40. History?<br />
  41. 41. Modeling<br />Programming<br />
  42. 42. Modeling<br />Programming<br />… (Mostly) Textual Notations<br />… Concrete Syntax Storage<br />… (Fancy) ASCII Editors<br />… Read-Only Visualizations<br />
  43. 43. Modeling<br />Programming<br />… (Mostly) Graphical Notations<br />… Abstract Syntax Storage<br />… Projecting Editors<br />… Different editable views for model<br />… (Mostly) Textual Notations<br />… Concrete Syntax Storage<br />… (Fancy) ASCII Editors<br />… Read-Only Visualizations<br />
  44. 44. Why<br />the difference?<br />
  45. 45. It is time for …<br />
  46. 46. … a Different Perspective<br />
  47. 47. Programming<br />the waywe do<br />Modeling?<br />Modeling<br />the waywe do<br />Programming?<br />
  48. 48. Modeling<br />Programming<br />==<br />==<br />Programming<br />Modeling<br />
  49. 49. We don‘t want to<br />model,<br />we want to<br />program!<br />
  50. 50. We don‘t want to<br />model,<br />we want to<br />program!<br />… at different levels of abstaction<br />… from different viewpoints<br />… integrated!<br />
  51. 51. We don‘t want to<br />model,<br />we want to<br />program!<br />… with different degrees of <br />domain-specificity<br />… with suitable notations<br />… with suitable expressiveness<br />
  52. 52. We don‘t want to<br />model,<br />we want to<br />program!<br />And always:<br />precise and tool processable<br />
  53. 53. Where do we go from here?<br />
  54. 54. A vision for<br /><br />programming<br />
  55. 55. A vision for<br /><br />programming<br />Enabling<br /><br />Technologies<br />
  56. 56. A vision for<br /><br />programming<br />Enabling<br /><br />Technologies<br />Available<br /><br />Tooling<br />
  57. 57. <br />A vision for<br />Programming<br /><br />
  58. 58. Programming <br />Languages<br />are not<br />MODULAR<br />enough.<br />
  59. 59. Programming <br />Languages<br />are not<br />COMPOSABLE<br />enough.<br />
  60. 60. Programming <br />Languages<br />are not<br />CONFIGURABLE<br />enough.<br />
  61. 61. Programming <br />Languages<br />are not<br />ADAPTABLE<br />enough.<br />
  62. 62. Programming <br />Language Syntax<br />is not<br />FLEXIBLE<br />enough.<br />
  63. 63. Big Language?<br />withmany first class concepts!<br />
  64. 64. Small Language?<br />with a few, orthogonal<br />and poweful concepts<br />
  65. 65. a<br />b<br />c<br />d<br />e<br />f<br />g<br />h<br />i<br />j<br />k<br />l<br />Modular Language<br />with many optional,<br />composable concepts<br />
  66. 66. Modular Language<br />Likeframeworksandlibraries, <br />
  67. 67. Modular Language<br />Likeframeworksandlibraries, <br />but withsyntaxand IDE support<br />
  68. 68. Not a new idea…<br />
  69. 69.
  70. 70.
  71. 71. Growing A Language<br />(Guy L Steele)<br />
  72. 72. Language<br />Workbench<br />(Martin Fowler)<br />
  73. 73. Language<br />Workbench<br />(Martin Fowler)<br />Freely<br />define<br />languages and<br />integrate<br />them<br />
  74. 74. Language<br />Workbench<br />(Martin Fowler)<br />use<br />?<br />persistent<br />abstract<br />representation<br />
  75. 75. Language<br />Workbench<br />(Martin Fowler)<br />language ::=<br />schema<br />editors<br />+<br />generators<br />+<br />
  76. 76. Language<br />Workbench<br />(Martin Fowler)<br />?<br />projectional<br />editing<br />
  77. 77. Language<br />Workbench<br />(Martin Fowler)<br />persist<br />incomplete<br />or<br />contradictory<br />information<br />
  78. 78. Language<br />Workbench<br />(Martin Fowler)<br />powerful<br />+<br />editing<br />testing<br />refactoring<br />debugging<br />groupware<br />language definition<br />implies<br />IDE definition<br />
  79. 79. Language<br />Workbench<br />(Martin Fowler)<br />+<br />support for<br />„classical“<br />programming<br />and<br />„classical“<br />modeling<br />
  80. 80. Syntax<br />primarily<br />textual<br />
  81. 81. Syntax<br />primarily<br />textual<br />withmoresymbols<br />think: mathematics<br />
  82. 82. Syntax<br />primarily<br />textual<br />sometimes<br />box&line style<br />
  83. 83. Syntax<br />primarily<br />textual<br />sophisticated<br />visualizations<br />
  84. 84. Viewpoints<br />
  85. 85. Viewpoints<br />suitable<br />abstractions<br />and<br />notations<br />foreach<br />
  86. 86. Viewpoints<br />Integrated<br />via<br />symbolic<br />references<br />and<br />seamless<br />transitions<br />
  87. 87. Viewpoints<br />Business<br />custom<br />purpose-built<br />create/include<br />
  88. 88. Viewpoints<br />Business<br />Custom<br />Notations<br />real<br />business<br />expert integration<br />
  89. 89. Viewpoints<br />Business<br />Custom<br />Notations<br />real<br />business<br />expert integration<br />But that‘s another talk…<br />
  90. 90. Viewpoints<br />Technical<br />predefined<br />library<br />configure<br />
  91. 91. Example Languages<br />
  92. 92.
  93. 93.
  94. 94.
  95. 95.
  96. 96.
  97. 97.
  98. 98.
  99. 99.
  100. 100.
  101. 101.
  102. 102.
  103. 103.
  104. 104.
  105. 105.
  106. 106.
  107. 107.
  108. 108.
  109. 109.
  110. 110.
  111. 111.
  112. 112.
  113. 113.
  114. 114.
  115. 115.
  116. 116. (Seemingly)<br />Simple Example<br />Adding<br />matrices<br />to C in an <br />embedded<br />environment.<br />
  117. 117. Currently:<br />
  118. 118. Currently:<br />Matrices<br />not supported<br />in XML format <br />and generator<br />
  119. 119. Currently:<br />Tool team<br />would have to<br />do the extension<br />… a lot of work<br />… busy<br />… one central tool<br />
  120. 120. Currently:<br />No real <br />compiler support<br />in the resulting C code<br />… type checks<br />… operator overloading<br />… generics (matrix&lt;int&gt;)<br />… matrix syntax?<br />
  121. 121.
  122. 122. Better Solution<br />
  123. 123. Better Solution<br />generic<br /> matrix<br /> and<br /> vector<br /> types<br />
  124. 124. Better Solution<br />real<br /> matrix<br /> and<br /> vector<br /> literals<br />
  125. 125. Better Solution<br />syntax<br />highlights<br /> for<br /> vectors<br /> and<br /> matrices<br />
  126. 126. Better Solution<br /> operator<br />overloading<br />
  127. 127. Better Solution<br /> operator<br />overloading<br />static<br />optimization<br />… symmetrical matrices<br />… identity matrix<br />… diagonal matrices<br />
  128. 128. Better Solution<br />math<br />notation<br />
  129. 129. Better Solution<br />a<br />separate<br /> language<br /> module<br />used only by<br />those who<br />really need it<br />
  130. 130.
  131. 131. In addition: PLE Variability<br />annotating<br />variability<br />expressions<br />to<br /> arbitrary<br /> regions<br />
  132. 132. In addition: PLE Variability<br />annotating<br />variability<br />expressions<br />to<br /> arbitrary<br /> regions<br /> statically <br /> checked<br />
  133. 133. In addition: PLE Variability<br />annotating<br />variability<br />expressions<br />to<br /> arbitrary<br /> regions<br /> project<br /> variant<br />
  134. 134.
  135. 135. more later…<br />(tool examples)<br />
  136. 136.
  137. 137.
  138. 138. <br />Enabling<br />Technologies<br /><br />
  139. 139. <br />Enabling<br />Technologies<br /><br />Advanced<br />Parser<br />Generators<br />
  140. 140. Modeling as Programmig<br />… (Mostly) Textual Notations<br />… Concrete Syntax Storage<br />… (Fancy) ASCII Editors<br />… Read-Only Visualizations<br />
  141. 141. Custom <br />Syntax<br />Graphical<br />Textual<br />Symbolic++<br />
  142. 142. IDE<br />Support<br />Teamwork<br />Debugging<br />Custom Editors<br />
  143. 143. Complete<br />Symbolic<br />Integration<br />Goto Def<br />Find Refs<br />Refactoring<br />
  144. 144. Xtext-like Tools<br />provide editor support<br />Custom Editors<br />Teamwork<br />Goto Def<br />Find Refs<br />Refactoring<br />
  145. 145. Limited to<br />Unicode<br />how to handle<br />non-character symbols<br />
  146. 146. Graphics !=<br />Text<br />two worlds…<br />separate editors<br />… per syntax/viewpoint<br />… models can still be ref integrated<br />
  147. 147.
  148. 148. What if!<br />combine languages<br />same seq&lt;Char&gt; as<br />different tokens?<br />
  149. 149. Ambiguous!<br />Not Parsable.<br />Bad Luck.<br />
  150. 150. Traditionally:<br />Language ::=<br /> Token* | Rule*;<br />
  151. 151. Traditionally:<br />Language ::=<br /> Token* | Rule*;<br />Token ::=<br /> Character*;<br />
  152. 152. Traditionally:<br />Language ::=<br /> Token* | Rule*;<br />Token ::=<br /> Character*;<br />Rule ::=<br /> Token* | Rule;<br />
  153. 153. Traditionally:<br />Language ::=<br /> Token* | Rule*;<br />2 Phases:<br />1. Global Tokenization<br />(aka Scanning)<br />2. Grammar Recognition<br />(aka Parsing)<br />
  154. 154. Modern:<br />Language ::=<br /> Rule*;<br />Rule ::=<br /> Char* | Rule*;<br />1 Phase:<br />Grammar Recognition<br />directly on char*<br />
  155. 155. Scannerless<br />Parsing<br />No Ambiguity<br />when combining languages<br />Always Parsable.<br />(well, almost. There are some corner cases…)<br />
  156. 156.
  157. 157. <br />Enabling<br />Technologies<br /><br />Projectional<br />Editing<br />
  158. 158. text<br />… to tree<br />… to text<br />Parser-based<br />
  159. 159. Projectional<br />tree<br />… to text-lookalike (editor)<br />… to other trees … [*]<br />… to text <br />
  160. 160. Programming as Modeling<br />… (Mostly) Graphical Notations<br />… Abstract Syntax Storage<br />… Projecting Editors<br />… Different editable views for model<br />
  161. 161. Programming as Modeling<br />… (Mostly) Graphical Any kind of Notations<br />… Abstract Syntax Storage<br />… Projecting Editors<br />… Different editable views for model<br />
  162. 162. Language<br />Composition<br />There‘sno parsing.<br />Unique Language Element Identity.<br />Unlimted language composition.<br />
  163. 163. Flexible<br />Notations<br />Textual<br />like ASCII<br />treated the same<br />}<br />Graphical<br />can be mixed<br />box & line<br />Semi-Graphical<br />mathematical<br />
  164. 164. Automatic<br />IDE Extension<br />tool support is inherent<br />for languages build with<br />projectional tools<br />language definition<br />implies<br />IDE definition<br />
  165. 165. Multiple<br />Notations<br />… for the same concepts<br />e.g. in different contexts<br />or for different tasks<br />
  166. 166. Partial<br />Projections<br />… different views<br />… for different roles/people<br />… only a particular variant<br />
  167. 167. Storage<br />!= Schema<br />… store arbitraty meta data<br />change log<br />conflicting information<br />variability annotations<br />… independent of language schema!<br />… „aspects“, overlay<br />
  168. 168. Live<br />Programs<br />think: spreadsheet<br />a change to one part of program<br />can lead to (dependent) changes<br />in other parts<br />
  169. 169. Tree Editing<br />… is different from editing text<br />… try to make it feel like text<br />… takes some gettingused to<br />but: for more flexible notations a more general editing paradigm is needed<br />
  170. 170. Infrastructure<br />Integration<br />… storage is not text<br />… diff/merge must be in tool<br />… existing text tools don‘t work<br />
  171. 171. Proprietary<br />Tools<br />… no standards<br />… no interop<br />
  172. 172.
  173. 173. <br />Available<br />Tooling<br /><br />
  174. 174. <br />Available<br />Tooling<br /><br />Eclipse<br />Xtext<br />
  175. 175. http://eclipse.org/modeling<br />
  176. 176. http://eclipse.org/xtext<br />
  177. 177. Eclipse Xtext<br />Building Textual Editors<br />
  178. 178. Eclipse Xtext<br />Building Textual Editors<br />
  179. 179. Xtext: Specify Grammar<br />
  180. 180. Xtext: Gen. Meta Model<br />
  181. 181. Xtext: Constraints<br />
  182. 182. Xtext: Generated Editor<br />
  183. 183. Xtext: Generated Editor<br />Code Completion<br />
  184. 184. Xtext: Generated Editor<br />Syntax Coloring<br />Custom KeywordColoring<br />
  185. 185. Xtext: Generated Editor<br />RealtimeConstraintValidation<br />
  186. 186. Xtext: Generated Editor<br />Customizable<br />Outlines<br />
  187. 187. Xtext: Generated Editor<br />Code Folding<br />
  188. 188. Xtext: Generated Editor<br />Goto Definition <br />Find References<br />Cross-File References<br />Model as EMF<br />
  189. 189. Xtext: Generated Editor<br />
  190. 190.
  191. 191. PlatformArchitecture<br />DSL<br />
  192. 192. As you understand<br />anddevelopyour<br />PlatformArchitecture…<br />
  193. 193. Develop a language to express it!<br />
  194. 194. Language resembles architectural concepts…<br />
  195. 195. Express the applications with the language.<br />
  196. 196.
  197. 197.
  198. 198.
  199. 199. Another Story…<br />Architecture As Language<br />
  200. 200.
  201. 201. DEMO I<br />Building DSLs with Eclipse Xtext<br />
  202. 202.
  203. 203. <br />Available<br />Tooling<br /><br />
  204. 204. <br />Available<br />Tooling<br /><br />Jetbrains‘<br />Meta <br />Programming<br />System<br />
  205. 205. also do…<br />IntelliJ IDEA<br />Resharper<br />
  206. 206. released in<br />Q3 2009<br />currently <br />1.1 RC1<br />
  207. 207. licensed under<br />Apache 2.0<br />
  208. 208. Build new standalone DSLs<br />
  209. 209. Build new standalone DSLs<br />Build DSLs that reuse parts<br />of other languages<br />
  210. 210. Build new standalone DSLs<br />Build DSLs that reuse parts<br />of other languages<br />Java++<br />(MPS comes with BaseLanguage)<br />extend base language<br />
  211. 211. Build new standalone DSLs<br />Build DSLs that reuse parts<br />of other languages<br />Java++<br />(MPS comes with BaseLanguage)<br />extend base language<br />build DSLs that reuse parts<br />of BaseLanguage<br />
  212. 212. Language Extension Example<br />Java + Extension<br />
  213. 213. Language Extension Example<br />Old<br />Java<br />Java + Extension<br />ReadWriteLock l = …<br />l.readLock().lock();<br />try {<br /> //code<br />} finally {<br /> l.readLock().unlock();<br />}<br />
  214. 214. Language Extension Example<br />Old<br />New<br />Java<br />Java + Extension<br />ReadWriteLock l = …<br />l.readLock().lock();<br />try {<br /> //code<br />} finally {<br /> l.readLock().unlock();<br />}<br />ReadWriteLock l = …<br />lock (l) {<br /> //code<br />}<br />
  215. 215. Structure  Editor  Typesystem  Generator<br />
  216. 216. Structure  Editor  Typesystem  Generator<br />
  217. 217. Structure  Editor  Typesystem  Generator<br />
  218. 218. Structure  Editor  Typesystem  Generator<br />
  219. 219. Structure  Editor  Typesystem  Generator<br />
  220. 220. Structure  Editor  Typesystem  Generator<br />
  221. 221. Structure  Editor  Typesystem  Generator<br />
  222. 222. Structure  Editor  Typesystem  Generator<br />
  223. 223. Structure  Editor  Typesystem  Generator<br />
  224. 224. Language Extension Example<br />Result behaves like a native<br />base language construct<br />
  225. 225. Language Extension Example<br />Result behaves like a native<br />base language construct<br />
  226. 226. Language Extension Example<br />Translated to regular Java code<br />based on the generator<br />package jaxdemo.sandbox.sandbox;<br />import java.util.concurrent.locks.Lock;<br />public class DemoClass {<br /> private Lock lock;<br /> public DemoClass() {<br /> try {<br /> this.getLock().lock();<br /> SharedResouce.instance().doSomething();<br /> } finally {<br /> this.getLock().unlock();<br /> }<br /> }<br /> private Lock getLock() { return this.lock; }<br />}<br />
  227. 227.
  228. 228. Example Languages<br />UI Language<br />
  229. 229. Example Languages<br />HTML Templates<br />
  230. 230. Example Languages<br />Persistent Classes<br />
  231. 231.
  232. 232. DEMO I<br />Building DSLs with JetBrains MPS<br />
  233. 233.
  234. 234. <br />Available<br />Tooling<br /><br />
  235. 235. <br />Available<br />Tooling<br /><br />Intentional Software<br />Domain<br />Workbench<br />
  236. 236.
  237. 237. Version 1.0 released in<br />Dec 15, 2008<br />currently at 1.4<br />
  238. 238. Commercial<br />Product<br />
  239. 239. Eval available<br />upon request<br />
  240. 240. Statemachine Example<br />Native Projection<br />
  241. 241. Statemachine Example<br />Tabular Projection<br />
  242. 242. Statemachine Example<br />Textual DSL Projection<br />
  243. 243. Statemachine Example<br />Java Projection<br />
  244. 244. Statemachine Example<br />Ruby Projection<br />
  245. 245. Statemachine Example<br />Two projections side/side<br />
  246. 246. Statemachine Example<br />Two projections side/side<br />
  247. 247.
  248. 248. Pension Workbench Example<br />Text Editing Domain<br />
  249. 249. Pension Workbench Example<br />Insurance Mathematics Domain<br />
  250. 250. Pension Workbench Example<br />Pension Contract Rules Domain<br />
  251. 251. Pension Workbench Example<br />All in one Document<br />
  252. 252. Pension Workbench Example<br />Symbolically integrated<br />
  253. 253.
  254. 254. A Journey…<br />Arewethere?<br />
  255. 255. A Journey…<br />.coordinates<br />web email skypexinglinkedin<br />www.voelter.devoelter@acm.orgschogglad<br />http://www.xing.com/profile/Markus_Voelter<br />http://www.linkedin.com/pub/0/377/a31<br />

×