Reusability in Java

Drawer Quick Response Code in Java Reusability
134 Reusability
Making Quick Response Code In Java
Using Barcode creation for Java Control to generate, create QR Code JIS X 0510 image in Java applications.
A class or object is reusable to the extent that it can be readily employed across different contexts, either as a black-box component or as the basis of white-box extension via subclassing and related techniques The interplay between safety and liveness concerns can significantly impact reusability It is usually possible to design components to be safe across all possible contexts For example, a synchronized method that refuses to commence until it possesses the synchronization lock will do this no matter how it is used But in some of these contexts, programs using this safe component might encounter liveness failures (for example, deadlock) Conversely, the functionality surrounding a component using only unsynchronized methods will always be live (at least with respect to locking), but may encounter safety violations when multiple concurrent executions are allowed to occur The dualities of safety and liveness are reflected in some extreme views of design methodology Some top-down design strategies take a pure safety-first approach: Ensure that each class and object is safe, and then later try to improve liveness as an optimization measure An opposite, bottom-up approach is sometimes adopted in multithreaded systems programming: Ensure that code is live, and then try to layer on safety features, for example by adding locks Neither extreme is especially successful in practice It is too easy for top-down approaches to result in slow, deadlock-prone systems, and for bottom-up approaches to result in buggy code with unanticipated safety violations It is usually more productive to proceed with the understanding that some very useful and efficient components are not, and need not be, absolutely safe, and that useful services supported by some components are not absolutely live Instead, they operate correctly only within certain restricted usage contexts Therefore, establishing, documenting, advertising, and exploiting these contexts become central issues in concurrent software design There are two general approaches (and a range of intermediate choices) for dealing with context dependence: (1) Minimize uncertainty by closing off parts of systems, and (2) Establish policies and protocols that enable components to become or remain open Many practical design efforts involve some of each 1341 Closed subsystems
Bar Code Creator In Java
Using Barcode printer for Java Control to generate, create barcode image in Java applications.
An ideally closed system is one for which you have perfect static (design time) knowledge about all possible behaviors This is typically both unattainable and undesirable However, it is often still possible to close off parts of systems, in units ranging from individual classes to product-level components, by employing possibly extreme versions of OO encapsulation techniques:
Barcode Recognizer In Java
Using Barcode recognizer for Java Control to read, scan read, scan image in Java applications.
Restricted external communication All interactions, both inward and outward, occur through a narrow interface In the most tractable case, the subsystem is communication-closed, never internally invoking methods on objects outside the subsystem Deterministic internal structure The concrete nature (and ideally, number) of all objects and threads comprising the subsystem are statically known The final and private keywords can be used to help enforce this In at least some such systems, you can in principle prove informally, formally, or even mechanically that no internal safety or liveness violations are possible within a closed component Or, if they are possible, you can continue to refine designs and implementations until a component is provably correct In the best cases, you can then apply this knowledge compositionally to analyze other parts of a system that rely on this component Perfect static information about objects, threads and interactions tells you not only what can happen, but also what cannot happen For example, it may be the case that, even though two synchronized methods in two objects contain calls to each other, they can never be accessed simultaneously by different threads within the subsystem, so deadlock will never occur Closure may also provide further opportunities for manual or compiler-driven optimization; for example removing synchronization from methods that would ordinarily require it, or employing clever special-purpose algorithms that can be made to apply only by eliminating the possibility of unwanted interaction Embedded systems are often composed as collections of closed modules, in part to improve predictability, schedulability, and related performance analyses While closed subsystems are tractable, they can also be brittle When the constraints and assumptions governing their internal structure change, these components are often thrown away and redeveloped from scratch 1342 Open systems An ideal open system is infinitely extensible, across several dimensions It may load unknown classes dynamically, allow subclasses to override just about any method, employ callbacks across objects within different subsystems, share common resources across threads, use reflection to discover and invoke methods on otherwise unknown objects, and so on Unbounded openness is usually as unattainable and undesirable as complete closedness: If everything can change, then you cannot program anything But most systems require at least some of this flexibility Full static analysis of open systems is not even possible since their nature and structure evolve across time Instead, open systems must rely on documented policies and protocols that every component adheres to The Internet is among the best examples of an open system It continually evolves, for example by adding new hosts, web pages, and services, requiring only that all participants obey a few network policies and protocols As with other open systems, adherence to Internet policies and protocols is sometimes difficult to enforce However, JVMs themselves arrange that non-conforming components cannot catastrophically damage system integrity Policy-driven design can work well at the much smaller level of typical concurrent systems, where policies and protocols often take the form of design rules Examples of policy domains explored in more depth in subsequent chapters include:
QR Encoder In C#.NET
Using Barcode creation for Visual Studio .NET Control to generate, create QR Code JIS X 0510 image in VS .NET applications.
Flow For example, a rule of the form: Components of type A send messages to those of type B, but never vice versa Blocking For example, a rule of the form: Methods of type A always immediately throw exceptions if resource R is not available, rather than blocking until it is available Notifications For example, a rule of the form: Objects of type A always send change notifications to their listeners whenever updated Adoption of a relatively small number of policies simplifies design by minimizing the possibility of inconsistent case-by-case decisions Component authors, perhaps with the help of code reviews and tools, need check only that they are obeying the relevant design rules, and can otherwise focus attention on the tasks at hand Developers can think locally while still acting globally However, policy-driven design can become unmanageable when the number of policies grows large and the programming obligations they induce overwhelm developers When even simple methods such as updating an account balance or printing "Hello, world" require dozens of lines of awkward, error-prone code to conform to design policies, it is time to take some kind of remedial action: Simplify or reduce the number of policies; or create tools that help automate code generation and/or check for conformance; or create domain-specific languages that enforce a given discipline; or create frameworks and utility libraries that reduce the need for so much support code to be written inside each method Policy choices need not be in any sense "optimal" to be effective, but they must be conformed to and believed in, the more fervently the better Such policy choices form the basis of several frameworks and design patterns described throughout this book It is likely that some of them will be inapplicable to your software projects, and may even strike you as wrong-headed ("I'd never do that!") because the underlying policies clash with others you have adopted While inducing greater closedness allows you to optimize for performance, inducing greater openness allows you to optimize for future change These two kinds of tunings and refactorings are often equally challenging to carry out, but have opposite effects Optimizing for performance usually entails exploiting special cases by hard-wiring design decisions Optimizing for extensibility entails removing hard-wired decisions and instead allowing them to vary, for example by encapsulating them as overridable methods, supporting callback hooks, or abstracting functionality via interfaces that can be re-implemented in completely different ways by dynamically loaded components Because concurrent programs tend to include more in-the-small policy decisions than sequential ones, and because they tend to rely more heavily on invariants surrounding particular representation choices, classes involving concurrency constructs often turn out to require special attention in order to be readily extensible This phenomenon is widespread enough to have been given a name, the inheritance anomaly, and is described in more detail in 3333 However, some other programming techniques needlessly restrict extensibility for the sake of performance These tactics become more questionable as compilers and JVMs improve For example, dynamic compilation allows many extensible components to be treated as if they are closed at classloading time, leading to optimizations and specializations that exploit particular run-time contexts more effectively than any programmer could 1343 Documentation
QR Creation In .NET Framework
Using Barcode creator for ASP.NET Control to generate, create QR image in ASP.NET applications.
When compositionality is context-dependent, it is vital for intended usage contexts and restrictions surrounding components to be well understood and well documented When this information is not provided, use, reuse, maintenance, testing, configuration management, system evolution, and related software-engineering concerns are made much more difficult Documentation may be used to improve understandability by any of several audiences other developers using a class as a black-box component, subclass authors, developers who later maintain, modify, or repair code, testers and code reviewers, and system users Across these audiences, the first goal is to eliminate the need for extensive documentation by minimizing the unexpected, and thus reducing conceptual complexity via: Standardization Using common policies, protocols, and interfaces For example:
Printing QR Code In Visual Studio .NET
Using Barcode generator for Visual Studio .NET Control to generate, create QR Code JIS X 0510 image in Visual Studio .NET applications.
Adopting standard design patterns, and referencing books, web pages, or design documents that describe them more fully Employing standard utility libraries and frameworks Using standard coding idioms and naming conventions Clearing against standard review checklists that enumerate common errors
QR Code ISO/IEC18004 Generation In VB.NET
Using Barcode generator for .NET framework Control to generate, create QR-Code image in Visual Studio .NET applications.
Clarity Using the simplest, most self-evident code expressions For example:
Generate Code 39 Extended In Java
Using Barcode maker for Java Control to generate, create ANSI/AIM Code 39 image in Java applications.
Using exceptions to advertise checked conditions Expressing internal restrictions via access qualifiers (such as private) Adopting common default naming and signature conventions, for example that, unless specified otherwise, methods that can block declare that they throw InterruptedException
Creating Bar Code In Java
Using Barcode creation for Java Control to generate, create bar code image in Java applications.
Auxiliary code Supplying code that demonstrates intended usages For example:
Bar Code Printer In Java
Using Barcode generation for Java Control to generate, create bar code image in Java applications.
Including sample or recommended usage examples Providing code snippets that achieve non-obvious effects Including methods designed to serve as self-tests
Generating UPCA In Java
Using Barcode printer for Java Control to generate, create UPCA image in Java applications.
After eliminating the need to explain the obvious via documentation, more useful forms of documentation can be used to clarify design decisions The most critical details can be expressed in a systematic fashion, using semiformal annotations of the forms listed in the following table, which are used and further explained as needed throughout this book
EAN13 Drawer In Java
Using Barcode drawer for Java Control to generate, create European Article Number 13 image in Java applications.
Precondition (not necessarily checked)
Drawing ITF14 In Java
Using Barcode creator for Java Control to generate, create UPC Shipping Container Symbol ITF-14 image in Java applications.
USS Code 39 Generator In .NET
Using Barcode generator for Visual Studio .NET Control to generate, create Code 3/9 image in Visual Studio .NET applications.
Scanning UPC A In VS .NET
Using Barcode recognizer for .NET Control to read, scan read, scan image in VS .NET applications.
Making UPC Symbol In Visual Studio .NET
Using Barcode printer for .NET framework Control to generate, create UPC Code image in .NET applications.
Drawing DataMatrix In VB.NET
Using Barcode generation for .NET framework Control to generate, create Data Matrix ECC200 image in .NET framework applications.