You are on page 1of 6

A Case Study on Code Generation of an ERP

System from Event-B
N´estor Cata˜no

Tim Wahls

Madeira Interactive Technologies Institute
Funchal, Caminho da Penteada, 9020-105, Portugal

Department of Mathematics and Computer Science
Dickinson College
Carlisle, Pennsylvania USA 17013

Abstract—Most code generation tools for Event-B are designed for generating small, in-memory applications such as
embedded controllers. In this work, we investigate whether the
EventB2SQL tool (Wang and Wahls, LNCS 8702) can generate
satisfactory code for the OpenBravo POS ERP (Enterprise
Resource Planning) system by replacing the database core of
the system with code generated from an Event-B model. We
describe our methodology for generating code with EventB2SQL
and enhancements to EventB2SQL that improve the performance
of the generated code, and present empirical results and a user
study comparing the performance of OpenBravo POS as is and
with its core replaced by code generated by EventB2SQL.
Index Terms—Event-B, code generation, ERP, database

Event-B [1] and formal methods in general have seen relatively widespread use in the development of reactive systems
such as railway controllers [2]. Such systems share a number
of characteristics:
• they are relatively small,
• they do not manipulate large volumes of data,
• they do not need to have persistent state. That is, data
manipulated by the system need not be saved to persistent
As such, most code generators for Event-B (as described in
Section II-D) do not support generating applications that manage large volumes of data in a persistent fashion. In this work,
we conducted a case study designed to determine whether a
new Event-B code generation tool – EventB2SQL [3] – can
generate satisfactory code for such applications, and if not,
whether the tool can be improved to do so. We do not expect
that generated code can be made to run as fast as a good
quality hand-coded implementation, so we set a tentative goal
of achieving running times for the generated code that were
within one order of magnitude of the times for hand-written
code for the same database tasks. We chose to work with an
Enterprise Resource Planning (ERP) system called OpenBravo
POS (Point of Sale) [4] for a number of reasons.
• OpenBravo POS has a significant database component.
• OpenBravo POS is an open-source system, providing us
with the access needed for comparing performance in an
easily automated way
• OpenBravo POS is widely used, with over 274,000 downloads of the current version (2.30.2) as of Jan. 2015 [4].

perhaps most importantly, the authors had already written
an Event-B model (the Inventory Model) for the core
OpenBravo POS functionality, and discharged the associated proof obligations with the Rodin platform. While
we added a few events for generating reports during
the case study, most of the model was written before
the development of EventB2SQL, and so is not biased
towards executability.
To demonstrate the applicability of Event-B in reasoning
about business systems, we added an invariant to the Inventory
Model that requires the resale price of each product to be
greater than the purchase price of that product. We then
adjusted the guards of the appropriate events, used the Rodin
provers to verify that no state of the model violated the
invariant, generated code for the model using EventB2SQL,
and then wrote JUnit tests to confirm that the generated code
maintained the invariant.

A. Event-B
Event-B [1] is a method for modeling and analysing software systems based on Refinement Calculus. Event-B relies
on Action Systems [5], a formalism describing the behaviour
of a system by the atomic actions that the system carries out.
An Event-B model is comprised of a static and a dynamic part.
The static part defines the context of the system (constants and
carrier sets and their properties) and the state space (variables,
their types and properties). Carrier sets introduce types (sets of
values) that are used by the model, but are not further defined.
The dynamic part defines all possible events, including one
computing the initial state. An event is comprised of a guard
and a set of actions. The guard represents conditions that must
hold in a state for the event to trigger. The actions compute
new values for state variables, thus performing an observable
state transition.
B. OpenBravo POS
OpenBravo [4] is a Point of Sale application (POS) that
enables retailers to buy and to sell goods, to create purchase
and sales orders, and to generate inventory and many other
reports. OpenBravo POS is an open source system that runs
under Mac OS, Linux, and Windows. The implementation

Each event is translated to a Java method that executes as a database transaction. all tuples. The application is specified in IS-UML – a UML variant in which operations are specified via B-annotated UML diagrams. Event-B operations are translated to SQL queries. Neither of these case studies employed a code generator. product inventory. One significant difference from EventB2SQL is that when using UB2SQL. An Event-B machine (abstract or refinement) and the carrier sets. which can then be executed directly over the database representation of the model’s state. As Event-B operations are frequently composed. we are aware of only three that can handle models written at a similar level of abstraction as those translatable by EventB2SQL. They stress the importance of proper tool support in applying formal methods. so it was convenient for us to replace OpenBravo POS’s Model with the code generated by EventB2SQL from the Inventory Model of Section III. EventB2SQL uses integer identifiers to refer to tuples. Products are organised into three categories: 1) resale products with associated purchase and sale prices 2) manufactured products with a sale price only 3) consumable products with a purchase price only The invariant on the sale and purchase price of resale products mentioned at the end of Section I is shown in Figure 1. sets and relations (that is. The value of each constant and machine variable is stored in a column of type int in a database table that always has exactly one row. The Inventory Model is organised into one abstract machine (Event-B model) and four machine refinements. The EventB2Java tool [9] can translate abstract Event-B machines to JML-annotated Java implementations. the user essentially defines the structure of the database in UML. products. For example. The entire state of the model is stored in the database. Further. Numerous case studies on the use of Event-B in developing industrial software systems have been completed. returning true if the translation of the event guard was satisfied and the method was able to execute. and sales . The original version of EventB2SQL (as described in [3]) used a highly normalized database structure that guaranteed that no object was ever stored in the database more than once. Finally. Purchase orders are defined over products and providers. The method has return type boolean. Neither of these tools provide support for data persistence. To achieve this. Carrier sets are translated as both generic type parameters of the generated class and tables in the database. the Inventory Model stores information about customers. and additional relations defined over these sets. If the guards are satisfied. particularly for larger and more complex systems. [12] uses B modeling and refinement in the development of database applications. T HE I NVENTORY M ODEL The Inventory Model is an Event-B model of the database core of OpenBravo POS. pprice is a function mapping a product and provider (supplier) pair to the purchase price. the authors of [13] use Event-B to develop and verify a vehicle control system for the platooning problem (one or more autonomous vehicles following a lead vehicle). D. Related Work Of the many code generators for B and Event-B. sets and relations. as otherwise the identifier would have nothing to refer to. The JeB tool [10] translates Event-B models to JavaScript for animation and simulation. while EventB2SQL generates the structure from the Event-B model. In particular. customers and providers. any EventB structure more complex than an integer or boolean) were assigned unique integer identifiers and were always referred to indirectly via this identifier. making the generated code suitable for use in multi-threaded and clientserver applications. [7] is a Rodin plugin [8] for generating Java database applications (using JDBC) from Event-B models. purchase and sales orders. and sprice is a function mapping a product to the sale price. The fact that objects were always referred to via identifiers meant that all intermediate results had to be stored in the database. and provides a series of reports with statistics about inventory. The authors of [14] used Event-B to redevelop the core of a commerical air traffic information system. as did the frequent retrievals of the value of a tuple. As described in the following paragraphs. set and relation object already existed in the database imposed a significant performance overhead. Additionally. this resulted in significant database overhead and negated any advantage gained from the lack of redundancy in the database design. With a few exceptions. The first machine refinement introduces sales and purchase orders with the aid of sets sorder and porder .follows the MVC (Model-View-Controller) software design pattern [6]. payments. product taxes. product providers. the user implements the concrete model using JDBC code generated by the tool. respectively. The UB2SQL tool [11]. As the original version of OpenBravo POS does not require the sale price of a product to be greater than the purchase price. III. making it persistent. As such. we did not include this invariant in the version of the Inventory Model used in benchmarking and the user study. the method executes database updates corresponding to the actions in the body of the event. C. allowing the generated code to manipulate and store Java objects. The tool translates the data model from UML to B and then to SQL tables. The abstract machine includes products. An automated refinement process translates the abstract B model to a relatively concrete one. payments and the like. Each event is translated as a database transaction. we were concerned that the code generated by EventB2SQL would run too slowly to be useful in practice. EventB2SQL can generate code for both the MySQL and SQLite database engines. or false otherwise. set or relation by identifier. constants and axioms of any contexts that the machine sees are translated to a single Java class. UB2SQL does not (yet) produce full Java/JDBC code for the model automatically. and neither considered systems with persistent state. EventB2SQL EventB2SQL [3]. checking whether each new tuple.

and “packaged” its result as an identifier. This checked that the code generated by the tool was correct (which was the case for our test suite) and allowed us to measure the performance of the generated code. so its inverse (∼) is used to find all order items for the order. T HE C ASE S TUDY A. retrieving a ticket by ticket identifier (Figure 2).inv29 ∀prod · prod ∈ resale ⇒ (∀prov · (prod 7→ prov ) ∈ dom(pprice) ∧ prod ∈ dom(sprice) ⇒ pprice(prod 7→ prov ) < sprice(prod )) Fig. the code generated for each Event-B operation assumes that the query generated for each operand returns the value of that operand. number of units and total price for each product in a sales order to machine variable the ticket. adding a new product. After this modification. If the result already existed in the database. the generated code returned the identifier of the existing object. An Event-B event for retrieving a ticket. we implemented code for randomly generating customers. The fourth refinement adds reports on the stock (inventory of products) to the Inventory Model. The third refinement features payment for sale and purchase orders. user perceptions of the responsiveness of the system are more important than running times for batch processing. 2. event get ticket any ord where grd1 ord ∈ sorder then act1 the ticket := {oi · oi ∈ sorderitem sorder ∼ [{ord }] | (sorderitem product(oi ) 7→ ( (sprice(sorderitem product(oi )) 7→ sorderitem quantity(oi )) 7→ sprice(sorderitem product(oi ))∗ sorderitem quantity(oi )))} end customer. Our next step was to eliminate checks for whether an object assigned to a machine variable already existed in the database. and the code generated by the current version of EventB2SQL. we present these timing results for various data sizes for the existing OpenBravo POS implementation. we re-ran our JUnit test suite as a quick check of correctness. the generated code added the object to the database with a new identifier. In order to measure our progress as we implemented various optimizations and enhancements to EventB2SQL (described in Section IV-B). adding a ticket (sales order). This change also allows objects assigned to machine variables to be mutated. 1. IV. Next. See Section V-B for details. we chose 5 OpenBravo POS operations that seemed likely to be frequently used in practice: adding a new Over the course of the case study. respectively.e. In the code generated by the . For an interactive system such as OpenBravo POS. After completing each enhancement. Event get ticket (Figure 2) from the last machine refinement uses a set comprehension to assign the price. we implemented a timing framework for executing the chosen operations for both the existing OpenBravo POS implementation and the code generated by EventB2SQL from the Inventory Model. each with a quantity and unit price). we made significant performance and functionality enhancements to EventB2SQL. The second refinement organises products and customers into different categories and introduces product taxes based on those categories. Fig. Query results need only be “packaged” as identifiers when the result is assigned to an Event-B machine variable. Enhancements to EventB2SQL orders over products and customers. with each ticket randomly containing between 1 and 10 ticket lines (products. and then to write JUnit tests for each method in the generated code. the generated code was quite slow – it took about 10 minutes to add 100 customers to the database on our test machine. Unfortunately. we also conducted a small user study in which human subjects were asked to use both the hand-coded OpenBravo POS system and a version of OpenBravo POS with its core database handling code replaced by code generated by EventB2SQL to perform a small set of tasks. the original version of EventB2SQL always referenced sets. If not. and retrieving the inventory of a product by name and location. Methods Our first step in conducting the case study was to use the original version of EventB2SQL to translate the Inventory Model to a database application. As described in Section II-C. An Event-B invariant stating that the sale price of each resale product is greater than the purchase price from any supplier. In the current version of EventB2SQL. This introduced the possibility of some database redundancy (for example. The code generated for each EventB operation used these identifiers to retrieve the values of operands. Hence. B. In Section V-A. if some set is both the value of a machine variable and an element of a powerset). products and tickets. permitting further optimizations. sorderitem sorder is a function from order items (ticket lines) to sales orders. but this disadvantage is outweighed by running time improvements. an element of a powerset). Then. relations and tuples via an integer identifier. 1) Performance Enhancements to EventB2SQL: Our first performance improvement was achieved by eliminating storage of intermediate results and most checks for duplicate objects. the code generated by the original version of EventB2SQL. the time needed to add 100 customers using the generated code dropped from 10 minutes down to about 2 minutes. using total boolean functions cashin and cashout from sorder and porder . Functions sorderitem product and sorderitem quantity return the product and quantity for an order item. or when the result is to be stored as part of some larger object (i.

EventB2SQL can now generate code for the get ticket event. . but it does significantly simplify writing client code for code generated from Event-B models that work with text (such as the Inventory Model). the number of customers was set to 20% of the number of tickets and the number of products was set to 10% of the number of tickets. After this case study. . we found and corrected a number of errors and omissions in the model over the course of the case study: • the event for adding a manufactured product did not add the product to a warehouse. profiling the generated code revealed that the remaining running time was dominated by executing set extensions (literal set expressions). The generated code: • evaluates the query for the domain of the bound variable. To correctly implement the simultaneous assignment semantics of Event-B the generated code calculates the set of elements to be inserted into or deleted from the value of each machine variable before performing any database modifications. Each operation was repeated 5 times for each data size. The primary benefit of all 8 of these optimizations is that they make the running time depend on the number of elements to be inserted or deleted. although this code is quite expensive to execute. Running times were measured using Java’s System. and the times reported below are averages over these 5 runs. The code generated by the original version of EventB2SQL inserts all elements of a set extension into a temporary (in-memory) table. storing the results in a temporary table. and an object identifier always referred to the same immutable object. we implemented code generation for set comprehensions in EventB2SQL (for cases where the bound variable ranges over a known and finite set).previous version of EventB2SQL. Another important lesson is the need to try tools on realworld examples in addition to the kinds of toy examples often employed in academic work. For adding and getting tickets. Lessons Learned Although all proof obligations for the Inventory Model had previously been discharged. 20000. and a constant nullstring of type STRING to be translated as "". This does not quite have the effect of making String a built-in type in Event-B (as string operations such as concatenation and substring are not available for use in modeling). C. executing v := v ∪ s requires constructing a completely new object for v ∪ s in the database. the query generated for small set extensions (9 elements or less) is now the union of the individual queries for each element. it is clear that the performance of code generated by the original version of EventB2SQL is not acceptable for most applications. The code generated by EventB2SQL(O) is much slower.String. 2000. the code generated by the original version of EventB2SQL (EventB2SQL(O)). • uses a loop to execute the query for the expression over the bound variable for each element of the domain. Thus. These kinds of errors emphasize the need for tools such as EventB2SQL that facilitate validation (checking that the model captures user requirements) in addition to verification tools. The optimizations made possible by mutation include: • v := v ∪ s is now executed by inserting elements of s that do not already occur in v into the value of v. each operation was executed for data sizes 1000.lang.currentTimeMillis() method. so there was no way to increase the inventory of manufactured products • taxes were not being calculated correctly • resale and consumable products could have only one provider. and creating a temporary table takes approximately 100 milliseconds on our test machine. Hence. and • returns a query that selects all elements of that table. For example. The time needed to add 100 customers to the database was now down to just under 9 seconds. without the optimization for ∪. Hence. B − (range subtraction) and B (range restriction). The get ticket event in the Inventory Model (Figure 2) is written using a set comprehension over the lines of the ticket. • v := v \ s by deleting elements of s from v • v := v ∩ s by deleting elements of v \ s from v • v := s C − v (domain subtraction) by deleting tuples from v with first component equal to some value in s • v := s C v (domain restriction) by deleting tuples from v with first component equal to some value in dom(v) \ s • similar optimizations for C − (relational override). even if this object contains only a few more tuples than the value of v. the generated code now rarely needs to create a temporary table when executing a set extension. For the OpenBravo and EventB2SQL(C). In this situation. we had not actually observed any performance issues in our test suites. which did not match the behavior of OpenBravo • there was no way to add multiple order items (lines) to a sales order (ticket). See Section V-A for timing results. Although we were concerned about the performance of the code generated by EventB2SQL. rather than the overall size of the set or relation. so it was not feasible to execute the benchmarks over the same range of data sizes. timing results for this code . so the same object identifier could occur (for example) as the value of a machine variable and as an element of a powerset – thus creating an alias. Objects were never duplicated. As set extensions in Event-B models typically contain only a few elements. all objects were immutable. R ESULTS A. At this point. mutating the object referred to by the machine variable would (incorrectly) change the powerset. 3000 . To avoid the creation of temporary tables. Benchmarking We benchmarked the 5 chosen OpenBravo POS operations using the hand-coded OpenBravo POS implementation (OpenBravo). V. 2) Other Enhancements to EventB2SQL: The current version of EventB2SQL features an option that allows a carrier set called STRING to be translated automatically as type java. and the code generated by the current version of EventB2SQL (EventB2SQL(C)). Full benchmarking results are presented in Section V-A.

EventB2SQL(C) was slower by a factor of about 4.2. OpenBravo POS stores all ticket lines for a ticket as a BLOB (Binary Large OBject). Because the times for EventB2SQL(O) are so large. .5 for all data sizes.5 lines per ticket. Timing results for adding customers for smaller data sizes. adding a sales order) with two versions of OpenBravo POS – the original hand-coded implementation. 6. while adding a customer using EventB2SQL(C) adds rows to 11 tables (the table holding the variable customer .6 and OpenBravo POS 2. For adding and getting tickets. and the tables holding the 9 functions that return some attribute of a customer. adding a customer. the set comprehension used in getting tickets (as shown in Figure 2) is expensive to execute. and the tables storing ticket lines grow quickly with an average of 5. . once again the poor performance of EventB2SQL(O) makes EventB2SQL(C) and OpenBravo POS indistinguishable for small data sizes (Figure 5). and a version with the database core replaced with the code generated by .2 for 1000 products. the time for EventB2SQL(C) is about 2. the code generated by EventB2SQL(C) stores each ticket line twice – once in the table for the carrier set for ticket lines and once in the table representing the set of all lines that are included in tickets.4 GHz processor. 100.8 GB of memory and a dual-core Intel Pentium D 3. EventB2SQL(C) runs more slowly than OpenBravo by a factor of about 4. Fig. and by a factor of 22.7 times greater than for OpenBravo POS. Figures 3 and 4 give running times for adding customers.8. the carrier set CUSTOMER.1 for retrieving 1000 tickets.600 3500 OpenBravo EventB2SQL(C) EventB2SQL(O) 500 OpenBravo EventB2SQL(C) EventB2SQL(O) 3000 2500 400 2000 300 1500 200 1000 100 0 500 20 30 40 50 60 70 80 90 100 Fig. getting tickets is the one operation for which we did not achieve goal of having code generated by EventB2SQL(C) perform within an order of magnitude of OpenBravo. but this factor becomes smaller as the data size increases. running more slowly by a factor of 2.04 (64 bit). For retrieving product inventories.4 times greater than for OpenBravo for all data sizes. running times for EventB2SQL(C) start at about 9. In each of the following graphs. Nine volunteers were asked to complete three tasks (adding a product.4 is relatively good performance. Additionally. 60. 40. Due to space limitations. . OpenBravo and EventB2SQL(C) are indistinguishable in Figure 3. In Figure 4. This is not the case for EventB2SQL(C). 8000 OpenBravo EventB2SQL(C) 7000 6000 1200 5000 1000 4000 800 3000 600 2000 400 1000 200 0 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000 0 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000 Fig. Java 1. User Study We conducted a small user study to gain some intuition on the usability of the generated code.1 for 20000 tickets. 1800 OpenBravo EventB2SQL(C) 1600 1400 0 20 30 40 50 60 70 80 90 100 Fig. Timing results for adding customers for larger data sizes. are for data sizes 20. we present only the graphs for adding customers and getting tickets. and about 4.30. the X-axis is the data size and the Y-axis is the average running time in seconds.8 for 20000 products. 4. 3. Additionally. Retrieving each ticket line with EventB2SQL(C) requires a separate database query. 5. Adding a customer in OpenBravo adds a row to one database table. The machine was running Ubuntu 14. Running times for adding products follow a similar pattern. B. Timing results for getting tickets for larger data sizes. For adding tickets. Timing results for getting tickets for smaller data sizes. As shown in Figure 6. so the time needed for adding a ticket does not depend on how many lines the ticket has. Hence. EventB2SQL(C) is slower than OpenBravo by a factor of 7. All timing data was collected on an otherwise idle Dell OptiPlex 745 with 4. MySQL 5.

Eds. EventB2SQL(C).. 17. [9] V. 2007. pp. and the schemas were reset to this state for each user session.” in Software Engineering and Formal Methods.-P. 4. ser. Hence. British Computer Society. An important first step in proving the soundess of the translation performed by EventB2SQL is proving that the SQL query generated for each Event-B operation is equivalent to that operation. Gamma. Rigorous Development of Complex Fault-Tolerant Systems [FP6 IST511599 RODIN project].” 2015. B. the users in the study found the version using generated code to be slower for each task than the hand-coded version. pp. vol. Butler. and E. they identified the version of OpenBravo POS that used generated code as being slower. LNCS. “From a B formal specification to an executable code: Application to the relational database domain. 2015.. 1. and M. the generated code is in general inserting into many more tables than is the hand-coded implementation. users were asked to rate the performance difference for each task on a scale from 0 (no difference) to 5 (extreme difference. mitigating the costs of applying formal methods. 253–279. N. Both versions used the same MySQL installation. Wahls. Of course. [12] ——. Mammar and R.. pp. 2013. [7] Q. [3] Q. D.” Siemens Transportation Systems. [13] F. 1994. “The EventB2SQL tool homepage. 2006. As noted in Section V-A. Rezazadeh.-R. 265–270. We have completed a preliminary version of this proof by hand. Butler. 1995. Inc. A.” http://sourceforge. and so on. pp. R. leveraging EventB2SQL’s ability to generate code that uses SQLite databases. The results of the user study are presented in Table I. 1991. Souquieres. [11] A. We have demonstrated that formal methods can be applied successfully in the development of an ERP system. Jacquot. “Translating Event-B machines to database applications. 1–22. C.” in An Extended EntityRelationship Model. Boston. R EFERENCES [1] J. Giannakopoulou and G. 2006. no. so that all properties verified to hold for the Event-B model also hold for code generated from that model. Code generation tools for Event-B must be sound. 571–576. “Redevelopment of an industrial case study using Event-B and Rodin. including the generation of code that is usable in practice. ser. with a separate logical database (schema) for each. Wahls. LNCS. The user study was performed on a dual-monitor system with one version of OpenBravo POS on each monitor. Jacquot. J. 2011. The last column is the average rating for each task. 4. . and J. We also plan a case study on using EventB2SQL to develop an Android application. ser. [15] M. “UB2SQL: A tool for building database applications using UML and B formal method.” in Third NASA Formal Methods Symposium. Yang. 70–89. our benchmarks show highly significant improvements in the performance of the generated code over the course of the case study. Applying formal methods in the development of systems that manage volumes of persistent data has advantages over traditional software development – notably the ability to verify correctness and security properties of such systems. we were able to achieve our goal of generating code that was no more than an order of magnitude slower than the handcoded implementation for all data sizes tested. VI. The ability to automatically generate database designs and back-end code for such systems saves considerable time in the development process. Conclusion Although the code generated by EventB2SQL for the Inventory Model is still slower than the corresponding hand-coded functionality in OpenBravo POS. vol. Sala¨un. Johnson. Rueda. Evans. http: //users. May 2015.. Gogolla. vol. [10] F. Springer.” Structured Programming. J. [6] E. and J. B. Laleau. Back and K. so achieving significantly better performance for adding tickets. For four of the five tasks chosen for benchmarking (all except retrieving tickets). Sere. FACSFMI’07. vol.html. New York. [4] “OpenBravo POS.dickinson. M.” in Proceedings of the 2007 International Conference on Formal Methods in Industry. [5] R. Romanovsky. [14] A. Eds. more work in this area is needed. Wang and T. “JeB: Safe simulation of EventB models in JavaScript. vol. F UTURE W ORK AND C ONCLUSION A. Rating 1 0. 2006. slower version is unusable). In each case where a user noticed a difference. a number of users were unable to detect any performance differences between the generated code and handcoded implementation for modest data sizes. N.” Journal of Database∼wahlst/eventb2sql/eventb2sql. pp. vol. Design patterns: elements of reusable object-oriented software. so users could switch freely between the two versions. Future Work While we have made progress in improving the performance of the code generated by EventB2SQL. In our user study. “Scaling up with Event-B: A case study. 100 products and 5000 tickets.-P. pp. no. Wang and T. Modeling in Event-B: System and Software Design. using the formal SQL semantics given in [15]. but only by a barely noticeable amount overall. “Code generation for Event-B. and C. Cata˜no. T.89 1 TABLE I U SER STUDY RESULTS FOR ADDING A CUSTOMER . 48. USA: Addison-Wesley Longman Publishing Co. The most critical area for improvement identified during this case study is in executing set comprehensions. Each schema contained the same collection of 500 customers. Technol. 2014.” Inf. USA: Cambridge University Press. Helm.Task Customer Product Sale 0 2 2 5 1 5 6 1 2 2 1 2 3 0 0 1 4 0 0 0 5 0 0 0 Avg. NY. ser. ADDING A PRODUCT AND REGISTERING A SALE . Vlissides.” Software Tools for Technology Transfer. Springer. the generated code must exhibit acceptable performance.. MA. Softw..” 2013 20th Asia-Pacific Software Engineering Conference (APSEC). Troubitsyna. Jones. Apr. R. 2010. Rivera. As they worked with both versions. Business rules can be verified in a similar manner. 17–30. Abrial. Bobaru et al. LNCS. 12. 8702. 767. The column labeled 0 contains the number of users who did not notice a performance difference for each task. and on average rated the performance differences as barely noticeable. column 1 the number of users who found a barely noticeable difference. Yang and J.. “Formal semantics of SQL. 1998. [8] M. customers and products and for getting the inventory of a product does not seem feasible without radical changes to the translation performed by the EventB2SQL tool. pp. “Stepwise Refinement of Action Systems. Users retrieved all products and customers in the process of adding a sales order. Eds. [2] “Saet meteo: new driverless metro line 14 in paris (ratp). 99–120.