中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > Web开发 > JSP > 综合文章
Automated Error Prevention @ JDJ
作者:未知 时间:2005-08-10 21:35 出处:Java频道 责编:chinaitpower
              摘要:Automated Error Prevention @ JDJ

Software errors cause not only system functionality problems, but also delayed releases, budget overruns, decreased development team productivity, and blemished corporate reputations. Errors are especially serious when they occur in code built upon WebSphere, which is typically at the core of critical business systems. If errors occur so close to the core of a business system, they will impact virtually every aspect of the system.

Automated Error Prevention (AEP) is a well-defined and highly accepted methodology for preventing errors. AEP helps you prevent errors in an automated fashion. This article describes how to apply AEP to WebSphere development.

Understanding AEP
AEP is a logical and practical application of W. Edwards Deming's principles of Total Quality Management, a process that revolutionized the manufacturing industry in the 1930s and that has been used to successfully improve quality and productivity in a number of industries ever since. Deming found that the key to improving quality and reducing inefficiency is to stop chasing after defects one by one, and instead prevent defects by improving the production line process that permits defects to be introduced. The following process improvement approach lies at the heart of AEP:

  1. Detect an error.
  2. Isolate the cause of the error.
  3. Locate the point in the process that created the error.
  4. Implement practices to prevent the error from recurring.
  5. Monitor for improvements.
The greatest obstacle to implementing this process in the software industry is that many of the required tasks can be difficult, time-consuming, and expensive. However, it is now possible to automate most of the required tasks, thanks to recent developments in open source software tools, commercial software tools, and books/articles that explain how to build your own automation scripts or tools.

So how does AEP fit into the software life cycle? If you look at the software life cycle illustrated in Figure 1, you will see that the life cycle circulates through a number of stages. At each stage, a variety of different error prevention practices work together to stop errors. These practices include coding standards enforcement, unit testing, integration testing, load testing, connectivity verification, and monitoring. When one of these practices exposes an error, that error is analyzed, then the process that allowed the error is modified so that it prevents the same type of error from recurring.

This creates a feedback loop in which each error found serves as a catalyst for process improvement and error prevention. For example, assume that load testing reveals a performance problem caused by a critical piece of Java code that uses String instead of StringBuffer for nonconstant strings. Using AEP, you would not only correct this specific piece of code, but also implement and automatically enforce a new coding standard that forbids use of that inefficient coding construct. In this way, the AEP feedback loop helps prevent an entire class of performance problems.

Applying AEP During Business System Development
As Figure 1 shows, there are a variety of AEP practices that prevent and expose errors, which fuels the AEP feedback loop. This article focuses on the practices most critical to WebSphere development. For more information on the other AEP practices listed in Figure 1, visit www.parasoft.com/jsp/aep/aep.jsp.

Following WebSphere Coding Standards
You can prevent many errors by following recommended WebSphere coding standards as you write code for new functionality, customization, and integration. These standards help you avoid writing code that is technically valid and correct, but likely to cause functionality, performance, or scalability problems on WebSphere Application Server. The following WebSphere coding standards are among those recommended in the IBM white paper "WebSphere Application Server Development Best Practices for Performance and Scalability."

  • Release HttpSessions when finished.
  • Minimize synchronization in servlets.
  • Do not use SingleThreadModel.
  • Reuse datasources for JDBC connections.
  • Release JDBC resources when done.
  • Minimize use of System.out.println.
  • Avoid String concatenation "+=".
  • Reuse EJB homes.
  • Do not use Beans.instantiate() to create new bean instances.

    The complete list of standards, as well as the justification for each standard, is available at www-3.ibm.com/software/webservers/ appserv/ws_bestpractices.pdf.

    Documenting Interfaces with Design by Contract
    Another AEP practice, Design by Contract (DbC), prevents integration problems. Integration is an especially error-prone phase for business system projects. These projects typically involve a moderate amount of time developing code around the middleware - the heart of the system - then a great deal of time trying to ensure that the glue code, existing or purchased components, and other hardware and software interact successfully. Even if each part is solid in and of itself, problems in the interfaces between the components can cause system functionality problems - especially if the problem occurs in a critical or frequently used interface.

    Design-by-contract involves formally documenting each unit's interface requirements and assumptions. When each unit's interfaces are clearly documented in a contract, developers are less likely to introduce errors by writing code that incorrectly interfaces with other units. In addition, if the code is compiled with a DbC-enabled compiler such as iContract or Parasoft's Jcontract, you receive automatic and immediate notification if interface problems arise during test executions. This allows you to perform an extensive amount of interface verification with a relatively minor investment of time and effort.

    Figure 2 illustrates where contracts (represented by small squares) should be added to units (represented by circles). Ideally, contracts specify requirements that must be satisfied before the unit executes, after the unit executes, and (optionally) at various points during execution.

    Building and Extending Test Cases
    Another way to prevent errors in WebSphere is to create tests that expose errors at the unit, submodule, module, and system levels, and use those tests to build a comprehensive error prevention test suite. This test suite can automatically expose problems introduced by a system modification - even problems that are the result of strange, unexpected side effects.

    One advantage of having such a test suite is that it allows you to expose each error as early as possible. Consequently, you can fix it when it is fastest, easiest, and cheapest to do so - as well as reduce the chance for it to cause additional bugs (from code interactions or code reuse).

    An even greater benefit of this test suite is that it fuels the AEP feedback loop. Each time it exposes an error, it helps you identify an error-prone part of your development process. You can then prevent an entire class of errors by modifying the process so that it does not allow the same type of error to recur.

    As Figure 3 shows, the error prevention test suite creation process can be a natural progression that begins with building unit tests, then extending those tests so that they verify the submodule, the module, and then the entire system. You start by creating test cases that verify a unit (for example, a Java class). Once the unit is verified, you have a set of test cases that essentially freezes the correct functionality of the unit; if a change introduces an error into the unit, the test cases will expose it. Next, you extend the unit test cases so that they verify the submodule, then the module, then the entire system. Because you are extending and reusing test cases, you create a test suite that will automatically alert you if a modification introduces a problem into any aspect of the system.

    For a more detailed look at how to develop such a test suite, consider an example. Assume we are developing a business system that provides our partners with a way to view inventory and order supplies. The partners access the application through a browser, and then beans access the database to perform the requested operations and deliver the results to the partners' browsers.

    The moment each bean is completed, we perform unit testing - including white-box and black-box testing - to verify that it is robust and correct. This involves creating a test harness and any necessary stubs for external resources, sending test inputs using a unit testing tool such as JUnit or Parasoft's Jtest, then verifying the outputs. This general unit testing process is illustrated in Figure 4. We perform this process for each bean we write. Because we have created test cases that freeze the correct behavior of each unit, we can instantly verify whether code modifications introduce unit-level problems by running the applicable tests. Thus, by collecting all of these test cases and running them on a regular basis (e.g., nightly), we establish the foundation of an error prevention test suite. In addition, the verified input/output relationships serve as known checkpoints that we can use to verify the success of our submodule, module, and system tests.

    If any errors are exposed at the unit level, we not only correct the errors, but also use AEP to prevent classes of similar errors from recurring. For instance, if we found that an error occurred because we used assignment in an if statement condition when we should have used equality [i.e., we wrote if (a=b) when we should have written if (a==b)], we could create and enforce a coding standard that forbids the use of assignment in if statement conditions. We could then check this standard automatically as we write code to ensure that code containing this problem is never added to the source code repository and integrated into the system. This is just one of many possible ways that the AEP feedback loop can be used to prevent errors through process improvement.

    We start extending the unit test cases when we have created enough beans to have a submodule. A submodule is a collection of units that are related, but not yet complete enough to be executed outside of a testing framework. As shown in Figure 5, the submodule in this example includes several related beans that are running on WebSphere, but are not yet accessible from a Web server. They will eventually connect to a database, but the database is not yet available.

    To test this submodule, we combine and extend the available unit test cases. For instance, assume we have a set of unit test cases for Bean A, Bean B, and Bean C - three beans that work together. Each test case has a test input and an expected output. To build a submodule test case from available unit test cases, we use a tool such as JUnit to invoke Bean A with a unit test input, verify the output at Bean A's checkpoint, send that output to Bean B, verify the output at Bean B's checkpoint, send that output to Bean C, then verify the output at Bean C's checkpoint. Each resulting submodule test case is a combination of multiple unit test cases we previously created for each bean. We already know the correct reference values for each checkpoint as a result of our unit testing, so verifying the output at each step is simply a matter of checking whether the values achieved during the test execution match the expected values. In other words, we create new test cases by reusing and extending the checkpoints established during unit testing.

    In addition, because the submodule is designed to send or retrieve data from the database, we want to verify whether that functionality operates correctly. The database is not yet available, but we can start verifying this functionality by configuring each submodule test case to write database calls to a file that serves as a database stub. This creates a new checkpoint that exposes incorrect database calls.

    If submodule testing exposes an error, we correct the code, as well as apply AEP to determine which process allowed the error, then implement a new quality control measure that prevents the same type of error from recurring. For instance, assume that we find problems in the interface between units. If we did not already use design-by-contract to document and verify interfaces, we could improve our process by incorporating design-by-contract and then using automated tools to verify whether or not we were adding sufficient contracts to each unit. If we were already using design-by-contract, we could implement an additional process improvement measure, such as requiring additional verification checkpoints that compare actual data values to expected ones.

    Once the database is connected to the submodule, we have a complete module and can start extending the submodule tests into module tests (see Figure 6). At this point, we have tests that span multiple units, and checkpoints at each unit as well as at the stubbed connection to the database. To extend these tests, we reuse the submodule tests that feed inputs through the units and check the values at the established checkpoints, and then we verify whether each of those tests performs the expected database operation. The database operation can be verified using SQL, a database verification tool such as DbUnit or Parasoft's DataRecon, or by checking the values collected by a JDBC sniffing tool.

    If a module test exposes an error, we correct the code and implement AEP to prevent classes of similar errors from recurring. For instance, assume our tests reveal that application data is not being stored properly in the database. In this case, we would implement AEP by creating a range of test cases that verify whether code is correctly adding records to the database. We would also modify our testing process to require that each database-related test case explicitly verify whether the correct data is being stored in the database.

    Once we can execute the system as a user would - in this case through a browser that interacts with our modules through a Web server - we can start extending our various module test cases into system test cases (see Figure 7). System-level tests should initiate and monitor simulated user transactions. These tests watch how a transaction travels through a system's interfaces, and then verify the result of those interactions. If the transaction functions correctly, all checkpoints will contain the expected values. Because each system-level transaction is a chain of complex interactions, I recommend that you focus on verifying one transaction at a time. A reasonable goal is to verify a representative sample of the most critical and popular user transactions, one at a time. At the least, your test suite should exercise every system entry point that the user interface provides and exercise a representative sample of the possible input types for each entry point.

    To create system-level test cases that check the established checkpoints as well as the interface with the user, we extend the beginning and end of our module tests. First, we configure a test client to invoke the module with the previously tested inputs. The test client can be a Web testing tool or an actual user exercising the application from a browser. Because the test is using the previously tested inputs, we can verify data values throughout the system by checking whether the actual value at each checkpoint corresponds to the expected value.

    In addition to verifying the existing checkpoints, we create additional checkpoints - one that verifies whether the module was invoked appropriately, and one that verifies the response returned to the client. For this application, verifying the response involves checking the page sent to the client after each test action. Verification might include content verification, code validation, accessibility verification, and so on. Tools such as Watchfire's Bobby, the W3C validators, and Parasoft's WebKing can automate this verification process.

    By extending the unit test cases to span the entire system, we establish a test suite that remembers the results of every checkpoint we ever verified, and instantly notifies us when a system modification introduces a problem into any part of the system. Many methods of system testing focus solely on verifying whether a user action produced the expected result, but this is not always an accurate assessment of whether the desired operation executed correctly. Consider a case in which the user action is supposed to record user information into the database, then send the user a confirmation message. If our system tests check only whether the user action produced the expected confirmation page, we could miss critical problems such as an interface problem that prevents the data from being recorded in the database.

    The test suite we created, with its extensive system of checkpoints, instead targets that problem as soon as it occurs. The problem can then be fixed immediately, while the modification is still fresh in the developer's mind and before the error has a chance to spawn additional errors as a result of code interactions and reuse. More important, the process that allowed the error could be immediately repaired to prevent the introduction of similar database-application interface problems throughout this project and future projects.

    The same general strategy can be applied to create system-wide test suites for business systems with different architectures. For example, if your module interacts with a legacy system or other resource outside of the submodule, you would verify that resource as we verified the database in the example. If your system is deployed as a Web service, you would exercise it using a test client, verify internal checkpoints throughout the system, then verify the HTTP traffic response to check the result. The verification logistics vary based on system architecture, but the effect is the same: a comprehensive test suite that automatically exposes errors as soon as possible.

    Conclusion
    With a comprehensive test suite that immediately and automatically exposes errors, you can apply AEP to prevent errors in two ways:

  • You can identify and repair specific coding errors before they spawn additional errors as a result of code reuse and code interactions.
  • You can identify and improve error-prone processes to prevent the introduction of additional errors.

    Parasoft Automated Error Prevention Solutions

    Parasoft Automated Error Prevention solutions provide a proven, cost-effective way to reduce the risk of business system failures by identifying and preventing errors. Solutions are available for Web applications, Web services, Java, C/C++, .NET, and databases. Each complete turnkey solution seamlessly incorporates error prevention into the full business system life cycle, and combines technologies and training to:

  • Prevent development, deployment, and operational errors by automating practices such as coding standards enforcement, unit testing, functional testing, integration testing, load testing, security verification, and monitoring.
  • Leverage work between development stages and development team members to reduce the overall amount of time and effort spent in production.
  • Provide project management with the information required for managing the production, deployment, and maintenance of business systems.
  • 关闭本页
     
    首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
    Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有