Part IV: Patterns and Practices
Chapter 16: Designing for Batch
This chapter looks at some of the more technical details and the patterns and practices that could be applied to the batch jobs and the overall batch solution. These concepts can be applied on real-world projects to ensure that the batch solution is fit for purpose and supports all the necessary operability criteria. This chapter is organized into the following sections:
The Batch Architecture — Takes a brief look at a couple of different batch architectures and the differences between using a formal batch scheduler over other approaches and technologies.
Batch Job Control and Execution — Walks through batch job execution and control as well as providing a generic framework. It examines the different components and how they can provide consistent interfaces so that they can be executed in the most appropriate way.
Multiple Threads and Multiple Jobs — Discusses the key differences of multiple jobs versus multiple threads, as well as some of the challenges and configuration required.
Generic Jobs and Generic Functionality — Looks at some typical jobs that are required in today's applications and how certain processes can provide generic and re-usable functionality to reduce the overall development effort. This section also touches on scripting as an alternative to developing processes in code.
Chapter 17: Designing for Reporting
This chapter looks at some patterns and practices you can employ to improve the overall reporting within the solution. Thinking beyond the initial reporting requirements and capturing information in the database right from the start will help to ensure that the low-level data is in place and will help to support future reporting requirements. This chapter is organized into the following sections:
Maintaining Meaningful Data — This section looks at some of the specific data elements that can improve the overall reporting capabilities including Using lookup tables, recording dates and times, maintaining transaction counts and defining the master data set.
Providing an Audit Trail — This section looks at providing an audit trail at the database level. An audit trail can help during incident investigation because it contains all the changes that have been made to database records and, more importantly, who (or what) changed them. Reports of this nature can also be very useful for Service Delivery.
Chapter 18: Designing for Performance
This chapter takes a brief look at some patterns and practices you can employ to improve the solution's overall performance. The goal is to ensure that you have a good idea of where you could implement them and ensure that they are captured appropriately. This chapter is organized into the following sections:
Tuning the Database Layer — Examines a few areas within the database where performance can be improved, including indexing tables, partitioning tables and data, optimizing queries and caching database data.
Tuning the Application Layer — Examines some specific functionality that the application can implement to improve performance, including avoiding unnecessary method calls, implementing object recycling, using object pools, caching frequently used data, performing bulk operations and optimizing method processing.
Chapter 19: Designing for Resilience
This chapter looks at some practices you can employ to provide resilience against typical (and unexpected) incidents in the solution. Incidents can occur in all areas of the solution, including the core application, the batch solution, and even in the reporting components. It is important that all components be resilient and robust to reduce down-time and unnecessary outages. This chapter is organized into the following sections:
Human Error and User Behavior — Examines some of the typical failures and scenarios that can be caused by human error. This section also discusses supporting and controlling user behavior.
Handling System Failure — Examines the exception-handling techniques you can employ to provide robust processing and to recover from typical failure scenarios.
Non-Stop Processing — Examines how planning the architecture, frameworks, and infrastructure configuration can help to provide non-stop resilient processing.
Chapter 20: Designing for Monitoring
This chapter builds on the messages in Chapter 8 by looking at two of the most important diagnostic features that should be designed into an application for monitoring purposes. This chapter is organized into the following sections:
Performance Counters — Examines the different categories and types of counters as well as some alternative actions that can provide the same information. It also discusses when and where performance counters can be used and how often data is updated and sampled.
Events and Event Logs — Examines events and event logging. An event or alert is typically the trigger for incident investigation, and this section discusses the different types of events and alerts you can include in an application, including when and where to use them and the type of information they should contain.
Monitoring Configuration — Examines the monitoring configuration that should be considered for the solution. It is important to note that a critical event in one environment might not be a critical event in another. In addition, some environments may require different contextual information from others.
Chapter 21: Designing for Incident Investigation
Incident investigation is all about getting to the root cause of the problem, re-creating the issue, analyzing and defining a solution, and, ultimately, implementing that solution. This chapter is organized into the following sections:
Tracing — Examines the tracing that should be included in the solution components. It also looks at some important practices that you should consider when implementing tracing to ensure that tracing is configurable for different environments and purposes.
Investigative Tooling — Examines some of the tools that could be required during incident investigation and how they could be used to analyze the root cause effectively.
Chapter 22: Designing for Application Maintenance
This chapter examines some of the practices you can employ to ensure that your systems are maintainable. Application maintenance and development are very closely related. This chapter is organized into the following sections:
Preparing the Solution — Examines how to prepare the solution folder structure, the individual projects, and the code profiler settings that you should have switched on right from the very start of development.
Defining the Standards — Examines some of the best practice standards and guidelines, including XML comments and general commenting and coding standards.
Supporting Configurability — Examines a few areas where you can make the application easier to maintain by using configuration settings. It also looks at some options for where configuration settings can be stored, including configuration files, the system registry, and the database.
Chapter 23: Designing for Testing
This chapter takes a look at how to design your solutions to incorporate features that will help you test more efficiently and effectively, as well as ensure that the system meets the quality characteristics. This chapter is organized into the following sections:
Developer Testing Activities — Examines the types of tests performed during developer testing. It looks at some of the component groups and the high-level conditions and scenarios that could be proven before moving on.
Examining the Factory Pattern — Examines the factory pattern, which can be used to facilitate testing. The factory pattern isolates the construction of an object within the software factory itself. There are many different ways in which this can be implemented, and each has its own pros and cons.
Using Stubs and Simulators — Examines the use of stubs and simulators during testing as well as the differences between them. Stubs and simulators can help to test areas of the application that could otherwise be troublesome to set up and instigate.
Chapter 24: Designing for Deployment
Deployment is the art of ensuring the right components are installed on the right servers with the right configuration. Limiting the number of different releases will help with deployment. In this chapter we're going to briefly look at a couple of the techniques and practices that should be considered during design to ensure that the solution is deployable. This chapter is organized into the following sections:
Splitting Out Test Materials — Examines the need to completely decouple all test matter from the solution to ensure that it doesn't get deployed into production. It is probably the most important factor.
Separating the Components — Describes how separating the application components can help with deployment and especially patching or hot -fixing.
Classifying the Releases — Examines the purpose, content, and configuration of the different types of packaged releases.