400 likes | 504 Views
Round-trip engineering. Presentation by Jason Kealey jkealey@shade.ca University of Ottawa. Round-trip engineering. Problem statement Presentation Goals Tools and techniques Implementation level transformations Design to Implementation and back. Requirements to Design and back.
E N D
Round-trip engineering Presentation by Jason Kealeyjkealey@shade.caUniversity of Ottawa
Round-trip engineering • Problem statement • Presentation Goals • Tools and techniques • Implementation level transformations • Design to Implementation and back. • Requirements to Design and back. • Automatic test generation • Conclusion
Problem Statement • First year: • Introduction to Java and UML Class Diagrams • Second year: • Overview of other UML diagrams (architectural, sequence, activity, etc.) • Third year: • Design patterns, more advanced OOAD • Functional (Use cases) and non-functional requirements • Fourth year: • Software development process • Software engineering capstone project
Problem Statement • Once you have gone through the SEG program, you know you have to think before coding (UML modeling), so you do it. • But you know you can’t plan everything ahead of time, so you get to work with only a partial design. And that’s OK! • However, once you hit implementation, how many of you actually go and review your requirements, use cases or software architecture? • In other words, you learned what you should be doing, but how many of you are actually doing it?
Problem Statement • How are you going to write conformance tests from your requirements if they aren’t even up to date anymore? • You probably can’t refer to the documentation to write your system tests either! • What happens when someone else works on the project? School: it doesn’t happen. Work: precious resources wasted due to difficult maintenance.
Problem Statement • Why aren’t you keep your earlier software artefacts up to date? • Time pressure (especially true in industry) • Duplication of effort • Requires too much discipline • Laziness • Other people don’t update, so my updates are worthless. • Use of waterfall • Who cares about tests anyways? • We only test during the “testing phase” – but we’re already late on delivery, so we don’t test at all.
Problem Statement • Some of the above reasons are simply bad, but others are justifiable. • Duplication of effort: • Artefact maintenance is redundant • Artefact maintenance is error-prone • Developers don’t see the added-value immediately and can’t verify the correctness of their modifications as easily as code. • What does that tell me? • Redundant tasks deserve to be automated.
Solution • Automatic generation of software engineering artefacts from more abstract ones. (forward engineering) • Inference of abstract artefacts from concrete ones (reverse engineering) • Automatic synchronization of artefacts from requirements, to design, to code, to tests. • Round-trip engineering • Refactoring of any artefact impacts others. Changes are propagated automatically.
Solution • This is all well and nice, but the current state of software engineering is far from this utopia. • However, some interesting tools and techniques currently exist to bridge the gap between the various software development artefacts. • Transformations are easier to do on concrete artefacts. Hence, the most advanced tools work close to the implementation level.
Goals • Today’s talk aims at presenting a few interesting tools and techniques that are useful to the time-pressured software engineer. • Many tools are imperfect, but you could get to work on them! (Open source projects, graduate studies) • The discussion aims at staying close to concrete details so that the tools are useful in real-world situations. However, the closer you are to high-level requirements, the transformations are unavoidably more abstract.
Implementation-level transformations • A common task in today’s business world is to create data-driven web applications. • Many different DBMSs exist for persistence • Various programming/scripting languages are used. • Possibility to interweave SQL code with business logic and HTML output.
Implementation-level transformations • This is bad for many reasons. • Maintainability • Extensibility • Testability • By keeping the model, the view and the business logic intertwined in the same code, it becomes especially hard to evaluate the impact of database changes on the project. • Solution: split into a three-tiered application. Manipulate objects instead of DataTables.
Implementation-level transformations • Our old friend redundancy comes over and points out that creating classes that correspond to database tables is long and error-prone. • Persisting the modified elements back into the database is also redundant. • Solution: Automation! (you had to see this coming) • Discussion of how to map • http://www.agiledata.org/essays/mappingObjects.html
Implementation-level transformations • Let us focus on Hibernate, for this talk. • The basic benefit of using Hibernate is that it will automate the persistence of Java objects torelational databases. • Java Classes (Objects, attributes) • Hibernate mapping file • Database (Tables, columns, rows) • Creating these manually is still tedious, we can obtain even more automation.
Implementation-level transformations • Hibernate (forward engineering): • Given Java classes (with annotations), it can generate both the mappings and the database. • Hibernate (reverse engineering): • Given a database, it can generate both the mappings and the Java classes. • Hibernate Synchronizer (plug-in): • Given changes to mappings, it reflect those changes to the code. • Depending on the context (Greenfield project versus software evolution), all transformations are useful.
Implementation-level transformations • Tools: • Hibernate, NHibernate • http://www.hibernate.org • Middlegen • http://boss.bekk.no/boss/middlegen/ • Gentle.NET • http://www.mertner.com/confluence/ • J2EE Container managed persistence • http://java.sun.com/developer/technicalArticles/ebeans/EJB20CMP/ • Object Databases • http://en.wikipedia.org/wiki/List_of_object-oriented_database_management_systems
Implementation-level transformations • Another common problem is writing parsers for particular formats (file formats or pseudo-code for example). • You’ve used tools to generate C-based parsers from BNF grammars in SEG2101. • Lex/Yacc • Flex/Bison • The basic concept is to define the abstract grammar and have the parser/interpreter code generated automatically. This code can either be used directly or integrated into other projects.
Implementation-level transformations • These exist for other languages as well. • JavaCC/JJTree, ANTLR, SableCC • Many of these can generate code in multiple languages (Java, C++, C#, Python, etc.). • http://en.wikipedia.org/wiki/List_of_compiler-compilers • Before writing your own parser for a known language, you should try to find its BNF grammar. For example, JavaCC’s grammar repository provides grammars for Java, SQL,C/C++, Rational Rose Petal files, RTF, VHDL, Visual Basic, etc.
Design to implementation • In a previous tutorial, I mentioned the Eclipse Modeling Framework (EMF) as a code generator. The basic concept is simple. Given a UML Class diagram, generate equivalent Java code. • Overview: • http://www.eclipse.org/emf/docs.php?doc=references/overview/EMF.html • Features: • Can import from XMI, XSD, Annotated Java • Conditional re-generation • Can generate simple Eclipse-based editors • Runtime features: • Integrated two-way reference management • Great notification mechanism • Automated persistence to XML (XMI). • Reflective API
Design to implementation • Because EMF is so simple to use, work you put into your model is quickly propagated to your implementation and the model is always in synch. • Other tools exist to achieve the same goal, such as ArgoUML. Because code generation is not a difficult task, generators exist for many different languages. • EMF is tremendously useful but it does not generate code representing the behaviour of the application. • I strongly recommend that the underlying model layer in an MVC architecture be at least partially generated.
Design to implementation • One can model the behavioural aspects using state machines, for example. However, I have not played with any tools which generate code from these. • If we want to generate more than just the model layer, we can investigate domain-specific generators. By defining fine-grained models, we can generate much more. • For example, the Eclipse Generic Modeling Environment generates graphical editors based on EMF and GEF from models. • http://wiki.eclipse.org/index.php/GMF_Tutorial
Design to implementation • Many other alternatives exist to generate graphical editors for custom notations. • Generic Modeling Environment (GME) • Xactium’s XMF-Mosaic • Telelogic Tau G2 (for UML profiles) • Rational Software Architect (for UML profiles) • If you work in an environment where you are constantly producing similar software (simple websites for example), you development process could be improved by writing your own code generator from a custom notation.
Implementation to design • Many tools offer the possibility to reverse engineer UML class diagrams from code, but none have impressed me enough to be worth presenting here. • One can also reverse engineer other UML diagrams such as state machines from code. • Work has been done in reverse engineering behavioural models from execution traces.
Requirements to design • There is lots of research in this area but only one that I wish to present in detail: Aspects. • Gunter Mussbacher has provided an excerpt of a talk he made this summer for your perusal. • The talk follows the methodology presented by Ivar Jacobson in his book which recommends deriving Aspects from Use Cases.
Requirements to design • An example Aspect (AspectJ notation): • http://www.eclipse.org/aspectj/doc/released/progguide/language-anatomy.html#an-example-aspect • Aspect-Oriented Development is gaining steam. Furthermore, it is not limited to Java: most major languages have their own implementation. • http://en.wikipedia.org/wiki/Aspect-oriented_programming#Implementations
Requirements to design • There are transformations that generate an high-level design from use cases. Notably, UCEd is a tool made by Stéphane Somé and his students that can generate finite state machines from use cases. • The GUI is not wonderful, but I mention it here because I wrote a transformation from UCEd use cases to Use Case Maps • The tool I worked on for my capstone project is useful to evaluate candidate architectures. The transformation is not automated, however.
Design to requirements • Other than Aspects which I mentioned previously, I don’t have interesting tools to present for this. • There is lots of research in this domain but many introduce new notations or impose methodologies to recover requirements from the design. • Textual requirements are very hard to reverse engineer, but some things are easier: • High-level use cases from acceptance tests
Automatic test generation • Acceptance tests • If requirements are defined with enough formalism (using pre-post conditions) and traceability is kept onto the design/code, it may be possible to automatically generate these. No tools to recommend. • You can ease the pain of writing these tests manually by using tools such as FitNesse. • http://fitnesse.org/FitNesse.TwoMinuteExample • Tools exist to automate UI testing, for both web-based UIs and conventional applications. The most sophisticated tools can track controls even if they move in the user interface. (Better than reproducing pixel-precise clicks.)
Automatic test generation • System Tests • Annotations and OCLs can be used to automate some tests, or at least their infrastructure. • http://www.eclipse.org/emf/docs.php?doc=references/overview/EMF.Validation.html • Unit tests • Annotations can also be used to automatically test an implementation in the context of design by contract. • http://www.cs.iastate.edu/~leavens/JML/
Conclusion • There are lots of tools out there to help facilitate the developer’s life. • No single person has in-depth experience with all of these tools, that is why sharing your experiences is a important aspect of the software engineering practice.