| | In the fall of 1997, having finished my book Inside the Java Virtual Machine, I brought my first JavaWorld column -- Under the Hood -- to a close. I had spent a year and a half immersed in the Java virtual machine, and wanted to turn my attention to a new writing project. For my new project, I decided to combine what I knew about Java with what I knew about good software development practices in general. I wanted to try and capture whatever it is that makes software "good" from the programmer's perspective, apply it to Java, and put it all down in a book. | Part of the problem with Java performance is the JVM and compiler technology that comprise a portion of the platform. That is, interpreted languages are inherently slower than compiled native execution. Over the last four years, the Java platform's performance has improved with the advent of JIT (just-in-time) compiler technology, improved garbage collection, adaptive compilation, and the greater speed of underlying hardware. However, the advances in speed have in part been offset by the complexity of the Java applications that are being developed. The speed of the Java platform is actually increasing while developers are designing applications that require more complexity, speed, and scalability. Some issues that are labeled as Java performance problems are actually design problems that have nothing to do with Java. | The speaker did not, however, elaborate on what actually constitutes a good object-oriented, thread-safe design. That is the aim of this new column. Through the articles of the Design Techniques column, I hope to answer the question: What is a good Java program design, and how do you create one? | In designing fields, the main rule of thumb is to avoid using one variable to represent multiple attributes of a class. You can violate this rule by denoting special values within a variable, each with its own special meaning. | Joshua Bloch: In my experience, there is too much monolithic software construction. Someone says that he wants to design a record-oriented file system, and does it. He starts designing the record-oriented file system and sees where it leads him, rather than follow this decomposition you speak of. Decomposition into subsystems is important, but as important is to have each subsystem be a well-designed, freestanding abstraction. That's where I feel like a preacher on a soapbox. | In this article, I'll discuss how to take advantage of one of the more interesting design opportunities made possible by Java's linking model: dynamic extension. As a background to the design guidelines, I'll give an overview of Java's linking model, touching on topics such as name spaces, forName(), and class loaders. | The Design by Contract (DBC) software development technique ensures high-quality software by guaranteeing that every component of a system lives up to its expectations. As a developer using DBC, you specify component contracts as part of the component's interface. The contract specifies what that component expects of clients and what clients can expect of it. | | Farewell to 'Design Techniques' This final installment of Design Techniques gives a brief history of the column, tracing its development and maturation, a topical index of the column's back issues, links to related discussion forum topics, and a hint of what's to come. (1,500 words) Bill Venners, April 1999 | Frankly, when I coined the terms Design Markers and Design Choices in the original Design Markers proposal, I had not yet heard of Explicit Programming and only later chanced upon its manifesto on the Web. It was immediately obvious that both shared a strategy of coining a name for each design choice and explicitly referencing those names in program source code. The second leg of the strategy was to embed the description of how to implement each design choice in the source. Each "how-to" description is factored out to a well-known place in the code. The coined name is the link between the many places in the code that reflect a particular design choice and its single implementation description. ELIDE calls these coined names modifiers and Design Markers calls them, well ... design markers. | Editor's note: In "Building Tag Clouds in Perl and PHP," author Jim Bumgardner says that to some, tag clouds would seem to be a fad. But as he demonstrates in this new, downloadable PDF from O'Reilly, the skills you learn in constructing your own tag clouds will also enable you to create other kinds of innovative, Web-2.0-style interfaces. To give you a sampling of what you'll find in the PDF, we've excerpted this section on tips for designing the most effective tag clouds. | Question: How do you take all the technobabble and all the business needs and actually build the e-commerce system? That is the subject of this paper. Whether you're a manager, designer, or down-in-the-bits developer, we hope this paper will help you understand the issues involved in building large, scalable Java 2 Enterprise Edition (J2EE) e-commerce systems, and that it will familiarize you with some design patterns to address those issues. We'll start at a high level and spiral down, so on any section, just read for as much detail as you need. The idea is to jumpstart your system planning and design and help you avoid several traps we've learned about through experience. Read on, and hopefully you'll find some answers to questions you don't yet know you have. | In this article we describe a controlled experiment designed to test and quantify those two claimed benefits, by comparing an application designed using a conventional 4-layer approach with an application of equivalent functionality developed with Naked Objects. | We are proud to provide this patterns/strategies repository to the community. Feel free to post any useful design tips you know! | Object slicing is defined as the conversion of an object into something with less information (typically a superclass). In C++ it occurs when an object is passed by value and copying the parameter value results in an upcast and it is considered a bad thing, as it may result in very subtle bugs. Object slicing throws away information. But in some situations this may be exactly what we want. In Java, objects are passed by reference, and all methods are virtual, so object slicing will not occur inadvertently. Even if you upcast an object, its real type is not forgotten, that's the definition of polymorphism. | The objective is to present a new design pattern - namely, Pipeline to Visitor. This pattern is supposed to handle the issue of building software components in a way that makes the software very maintainable. The pipeline to visitor design pattern is best suited in the business logic tier. | If Java is truly to replace COBOL as an enterprise-wide standard, then it needs to be as easy to write as COBOL and as fast a C++ at runtime. In my experience with all of these implementations, I have found that Java at the command level is clearly easier to learn than C++, however, Java the platform is complicated. As far as runtime performance, only through a combination of application server clustering and application construct performance tuning can Java expect to approach the runtime performance of C++. | The article does attempt to provide a new perspective on the architecture. Applying the perspective on existing applications might let you find missing roles and optimize the performance of standardized roles. The perspective will help new applications to be conscious of the standard internal roles and their hierarchical division. This reduces complexity of the design and provides high degree of modularity and encapsulation and fights against crisscross references between objects, Thus, we just tried to visualize a role based tree perspective that can be recursively applied using standardized roles that share common concerns. | Many J2EE developers are too inflexible in pursuing what they regard as being prescribed design patterns, even if they produce poor outcomes. For example, many J2EE developers won't consider using stored procedures, regardless of their potential benefits in a particular case. For example, it's sometimes possible to implement some persistence logic-not business logic-in 10 lines of PL/SQL or Transact SQL that might require dozens or even hundreds of lines of Java to do far less efficiently with entity beans. We need to approach problems with an open mind, and should be prepared to use the simplest and most efficient approach. I think it's always a mistake to let technology choice, rather than business requirements, drive a solution. | The approach presented in this article can be seen as a lightweight variant of Domain Specific Modeling (DSM) [10]. DSM is targeted at large scale projects and especially product families. This approach is for small to medium size projects (< 10 developers, < 1 year). It tries to cut the investments and learning curve to a minimum, by using a pragmatic solution. | Ken Arnold: Yes, at some point a design is so simple it doesn't work anymore, right? I think the fundamental way you get simple, yet sufficient, systems is to ask yourself some questions. First, what does the user need to accomplish? Let me back up and explain what I mean by user. I have this really weird radical notion. Every great idea starts off with an absolutely radical notion. I am immodest enough to think I have this great idea. And the radical notion that founds it is that programmers are people. Now if you accept this premise, then the next step is to say that designing tools for programmers, including languages, APIs, and compilers, is a human factors problem. And so we should ask the same kinds of questions that people ask about graphical user interfaces (GUIs). Is it easy to do what you need to do? Is it natural? Are simple things simple? Are complicated things complicated? Are dangerous things hard to do? Are common things easy to do? Are similar things done in a way that is naturally similar to the person? | The Strategy design pattern basically consists of decoupling an algorithm from its host, and encapsulating the algorithm into a separate class. More simply put, an object and its behavior are separated and put into two different classes. This allows you to switch the algorithm that you are using at any time. | This time of year, there's plenty of leftover wrapping paper sitting around. Why not put it to good use? If you create interfaces, you may have heard of paper prototyping. It's a technique that lets you mock up, test, and refine a design -- totally on paper -- before you write a line of code. Figure 1 shows an example of a paper prototype screen, and the second half of this article has more details about the method. But first, we begin with some signs that paper prototyping might be right for your project. | The Java Beans property pattern has become a common programming practice for developers in a wide range of applications, from desktop applications, to EJB and web service components. There is a wide range of proposals to provide language support to streamline this design pattern. | Temporary objects are those that have a short lifetime and generally serve no useful purpose other than to act as containers for other data. Programmers generally use temporary objects to pass compound data to -- or return it from -- a method. Part 1 explored how temporary object creations could have a serious negative impact on a program's performance and showed how certain class interface design decisions virtually guarantee temporary object creation. By avoiding those interface constructs, you can dramatically reduce the need to create temporary objects that can sap your program's performance. | Interacting with a dynamically loaded class When Cat invokes scurry() on the Rodent reference myToy, the JVM does a dynamic bind and executes Mouse's implementation of scurry(). The application prints out "Mouse scurrying.". This is true even though Cat didn't know about Mouse at compile time. At compile time, Cat knew only about Rodent. This is the most common way to interact with a dynamically loaded class: to invoke methods defined in a supertype (superclass or superinterface) of the dynamically loaded class on an instance of that class. | I like programming problems where you think, "There has to be something really interesting over there, but I can't see it clearly." All you can do is move one step over there, with a small bit of code, and start exploring to see it more clearly. And maybe it actually wasn't there, it was over here. Or it had a different shape than you thought initially. Maybe it wasn't interesting at all, and you didn't waste a lot of time. | Class 'Class' Where casts, instanceof, and instance method invocations give you a taste of runtime class information, class java.lang.Class gives you a feast: Instances of class java.lang.Class represent the most abundant source of runtime class information in the JVM. Once you have a reference to an object's Class instance, you have access to a wealth of information about that object's class. | Have an opinion about the design principles presented in this article? Discuss this article in the Articles Forum topic, CLR Design Choices. | So what are class members good for? In my opinion, the best mindset to cultivate when designing Java programs is to think objects, objects, objects. Focus on designing great objects, and think of classes primarily as blueprints for objects -- the structure in which you define the instance variables and instance methods that make up your well-designed objects. Besides that, you can think of classes as providing a few special services that objects can't provide, or can't provide as elegantly. Think of classes as: | Software development as 'conversation' I was recently a guest at an object-oriented design seminar taught by Bruce Eckel and Larry O'Brien. At one point in their seminar, Bruce and Larry gave the attendees a two-page "statement of work" for a software project. The attendees separated into groups of four or five, and each group began discussing how it would design software to meet the requirements set out in the statement of work. I roamed from group to group, listening and participating in the discussions. While each group had its own personality, the groups had much in common. In particular, I saw in all the groups the same basic process in action, a process I'd seen over and over in real software projects on which I'd worked. I like to call this process "the conversation." | When I talk about design in the Design Techniques column, I am talking about the activities that take place during step two of the above list. To give you a better idea of what I mean by each phase, I describe each individually in the next four sections. | In "Release It!", Michael T. Nygard shows you how to design and architect your application for the harsh realities it will face. You'll learn how to design your application for maximum uptime, performance, and return on investment. | Interfaces and the 'diamond problem' One justification of interfaces that I had heard early on was that they solved the "diamond problem" of traditional multiple inheritance. The diamond problem is an ambiguity that can occur when a class multiply inherits from two classes that both descend from a common superclass. For example, in Michael Crichton's novel Jurassic Park, scientists combine dinosaur DNA with DNA from modern frogs to get an animal that resembled a dinosaur but in some ways acted like a frog. At the end of the novel, the heros of the story stumble on dinosaur eggs. The dinosaurs, which were all created female to prevent fraternization in the wild, were reproducing. Chrichton attributed this miracle of love to the snippets of frog DNA the scientists had used to fill in missing pieces of the dinosaur DNA. In frog populations dominated by one sex, Chrichton says, some frogs of the dominant sex may spontaneously change their sex. (Although this seems like a good thing for the survival of the frog species, it must be terribly confusing for the individual frogs involved.) The dinosaurs in Jurassic Park had inadvertently inherited this spontaneous sex-change behavior from their frog ancestry, with tragic consequences. | Bill Venners: On the subject of interfaces, the GoF book includes some UML class diagrams. UML diagrams seem to mix interface and implementation. When you look at it, you often see the design of the code. It isn't necessarily obvious what's API and what's implementation. If you look at JavaDoc, by contrast, you see the interfaces. Another place I see the lack of differentiation between interface and implementation is XP. XP talks about the code. You're changing this amorphous body of code with test- driven development. When should the designer think about interfaces versus the whole mass of code? | Bill Venners: C++ has a lot of stuff in it. The more features that a designer puts into a language or library, the more power the users get, but also the more surface area they get. There are more features users have to know about, even if it is knowing they just want to ignore certain features. As a designer of a language or library, how do you decide what features to leave in what to leave out? | The third occasion where defining contracts using Boolean expressions raises issues is non-functional contracts. Maybe I shouldn't go into this too much, because this is more of a research issue. Nevertheless, once you have completely expressed all the functional contracts—the contracts that specify what the input may be to operations, what outputs are legitimate, and what globally consistency constraints must be maintained—you might still want to express as part of the specification things like: this operation will always execute in less than half a millisecond, or this particular component will never use more than 300 kilobytes. These are performance contracts, and it's a quite interesting research area. I think there will be usable results in this area in the next few years, but it falls beyond the realm of Design by Contract as it is generally understood in practice today. | With this installment of Design Techniques, I begin a series of articles that will focus on the design of classes and objects. In this series I will discuss the following: designing classes for proper object initialization, finalization, and cleanup; designing fields and methods, in general; and designing class fields and methods, in particular. I won't address the design of class hierarchies in these first few installments -- rather, I will focus only on the design of individual classes. | Bill Venners: You listed several API design principles in your talk at the New York XML SIG. I'd like to walk through them and get your comments. You said, "It's the class's responsibility to enforce its class invariants." | Josh Bloch: I think you have no choice but to trust that objects implement their contracts. Once people start violating their contracts, the whole world falls apart. A simple example: Equal objects must have equal hash codes. If you created types for which this isn't true, hash tables and hash sets wouldn't work. | The second installment of the Artima JavaOne interview series is about the importance of design in preventing future problems. Cameron Purdy is founder and CEO of Tangosol, maker of the enterprise Java data grid software, Coherence. (Shortly before JavaOne, Oracle announced that it would acquire Tangosol.) | On October 27, 2004, Bill Venners met with Erich Gamma at the OOPSLA conference in Vancouver, Canada. In this interview, which will be published in multiple installments in Leading-Edge Java on Artima Developer, Gamma gives insights into software design. In this first installment, Gamma describes gives his opinion on the appropriate ways to think about and use design patterns, and describes the difference between patterns libraries, such as GoF, and an Alexandrian pattern language. | At a meeting of the New York XML SIG in September, 2002, Harold unveiled an XML processing API of his own design: the XOM (XML Object Model) API. On Cafe au Lait and Cafe con Leche, Harold described XOM like this: | Ken Arnold has done a lot of design in his day. While at Sun Microsystems, Arnold was one of the original architects of Jini technology and the original lead architect of JavaSpaces. Prior to joining Sun, Arnold participated in the original Hewlett-Packard architectural team that designed CORBA. While at University of California, Berkeley, he created the Curses library for terminal-independent, screen-oriented programs. In Part I of this interview, which has been published in six weekly installments, Arnold explains why there's no such thing as a perfect design, suggests questions you should ask yourself when you design, and proposes the radical notion that programmers are people. In Part II, Arnold discusses the role of taste and arrogance in design, the value of other people's problems, and the virtue of simplicity. In Part III, Arnold addresses the concerns of distributed systems design, including the need to expect failure, avoid state, and plan for recovery. In Part IV, Arnold describes the basic idea of a JavaSpace, explains why fields in entries are public, why entries are passive, and how decoupling leads to reliability. In Part V, Arnold discusses the data-driven nature of JavaSpaces, how JavaSpaces lets you "throw in a grain and watch it grow," and why iteration isn't supported in the JavaSpace interface. In this sixth and final installment, Arnold discusses whether to prohibit subclassing, whether to use Cloneable or copy constructors, and when to use marker interfaces. | I grabbed this from the bottom of the state pattern one. Use it here as the first example of composition for a purpose in design patterns. | Design Patterns: Elements of Reusable Object-Oriented Software Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Also know as the "Gang of Four") This, the grandaddy of all Design Patterns books, is my favorite design book. It describes 23 design patterns common to object oriented programs. Its examples are in C++ and Smalltalk, but it is very practical for Java programmers. In fact, many of the patterns in this book are incorporated into the architecture of the Java API. If you buy one design book, it should be this one. | One way my design sense has changed is that I now think of design to a great extent in terms of contracts. Most people agree that private data is a good thing. In your Effective C++ guideline, "Avoid data members in the public interface," you give three justifications for private data. You say private data provides consistency, because every accessible member is always a function. You mention private data gives you control over accessibility. Private data can, for example, be read only. But the "big gun," using your words, is that private data provides functional abstraction. I could, for example, replace a function that returns a private data member with a computation that calculates the same value. | The workshop combines lectures, guided exercises, and team-based independent work to demonstrate how object-oriented design with patterns and idioms can work in a production environment. As with all Bruce Eckel's seminars, the emphasis will be on getting you "thinking in" objects. | Summary: This course teaches object-oriented design through design guidelines, idioms, and patterns. Each guideline, idiom, and pattern will be explained and justified, and then discussed by the students. This discussion is an integral part of the workshop, aimed at facilitating a conversation about design among peers that can help everyone to learn from each other's experiences and perspectives. | Class Entry is an interesting example of a naked object. Explain the reasoning behind them. Any methods I've ever put into entries are for convenience. Because when you don't control your data, you can't guarantee that you can fulfill a contract. In summary, naked messengers are quite contrary to the whole thrust of object-oriented design, where responsibilities are divided among various objects, and each object promised to fulfill the obligations outlined in its contract. Talk about the increment method in ChatMessage and perhaps the getFactory method in UIDescriptor. Private data is key to enabling an object to fulfill its contract. | It was a very important property of interfaces that they are very strict. That wasn't just me deciding to be nasty. That was the world is madness if the contracts aren't strict. Because then all of a sudden--the whole notion of object-oriented programming falls apart. You lose the ability to unplug this and plug that in. If you don't know what the shape of the plug is, how do you know it can plug in? | The thing is that this is object-oriented API design is designing with types, in which you attach semantics to types, whose contracts are expressed in terms of behavior. Designing a context free langauge, or a regular language, an XML schema or XML DTD, or a network protocol, etc, is data model design, in which you define what the data can look like and what the meaning of it is. | As virtualization software improves, other benefits of a virtualized deployment environment become apparent, too. In this interview with Artima, Shayne Higdon, marketing vice president of DataSynapse, describes one close to developers' concerns: The ability to outsource the scaling of an application to the virtualization layer. | When a contract enforcement test, such as the assert()s in the example, fails, it is said to fire, and the code is said to have violated its contract, and be in a violated state or an invalid state. By definition, the firing of a contract violation within a component is a message from that code?s author(s) that states precisely and absolutely that the component has violated its design, and no future expectations about its behaviour can be made, and no guarantees given. As Christopher Diggins points out [5], ?design flaws are transitive. There is no known method in software engineering able to predict that a detected design flaw in a particular area has not corrupted the design of the rest of the software including the other assertions potentially causing them to falsely accept incorrect contracts". I will examine this issue in some rigour in part 2, with respect to precondition violations, and their potential recoverability. | The Law of the Big Three has played, and continues to play, an important role in C++. However, we think that there is good reason to leave the destructor out of both the discussion and the implementation when possible, leading to a derivative "Law of the Big Two". The reason is that often, unadorned pointers should be avoided as class members?to be replaced by smart pointers. Either way, the role of copy constructors and copy assignment operators is often forgotten or ignored; it's our hope that this article may help address that in some small way. | In fact, in most properly done use cases, there are no failure modes! This astonishing statement is not as shocking as it might, at first, appear. Most computer programs use error messages as a way to mask programmer laziness. The vast majority of "errors" could actually be handled just fine by the program itself. The error message is printed primarily because the programmers were too lazy to figure out how to handle the error, so they pushed the work onto the user. Take the class-is-full scenario. A lazy designer would say "Oh well, the class you want is full. That's just too bad. Nothing I can do about it" and classify this case as a failure scenario: A competent designer would work out a solution such as our waiting-list strategy. It's your job as a designer to solve the user's problems, not to push the problems back at the user. Alan Cooper goes so far as to say that well-written programs shouldn't print error messages at all. I'm not sure whether that goal is possible, but I'll bet you could eliminate 90% of the error messages from most programs, and end up with a more usable system as a consequence. | Proxies in software are similar to proxies in real life. You might create a distributed object proxy. Such a proxy is designed to make its clients think that they are directly interacting with the object, when in reality the object lives in a process on a remote machine. The proxy manages the intricacies of communicating with the distributed object while ensuring that the client remains blissfully ignorant of these details. | All of these features would be great, at least from my standpoint. I could build them all into my Email class, but that would result in a pretty bloated class, with lots of if statements. I'm also not totally oblivious to the needs of others—many people would want to turn off my pet features. An inheritance hierarchy would certainly be unworkable. What I want is the ability to dynamically specialize email handling—something that the decorator design pattern affords. | Much of the enthusiasm for each new programming paradigm that emerges is driven by academics who relish the intellectual challenge but who don't have to build working code to a fixed deadline. This is particularly true of Object Oriented Design (OOD). There is no pure-bred, definitive programming standard called Object Orientation—which makes for both flexibility and confusion in the development of software. | Timing is everything. Write tests first, and you can get as good levels of unit test coverage as anyone could expect. Write tests after, and, well, you probably won't write nearly as many tests. That's only one reason to chose test-driven development (TDD) over test-after development (TAD). In this article, I'll discuss where testability and design are aligned with one another and where they are not. | Welcome to OnMicrosoft—conversations with thought leaders in Microsoft technologies. In this session, Brad Abrams and Krzysztof Cwalina discuss Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, Second Edition, the definitive resource for .NET developers and architects designing class library frameworks—updated for the new language features of the .NET Framework 3.0 and 3.5. | This wikipedia page has a longer discussion of these and other brace styles, and includes a few comments about their origins and motivations. My own experience is that the first two styles are the most common. The examples and tutorials that you might find on Sun's own site uses the K&R; style almost exclusively, and it is hard to argue with their influence on a language they steer. As I cut my teeth on C code originally and learned Java from Sun's tutorial pages, my fingers do a K&R-style; opening-brace-and-return automatically. Naturally, my current workplace uses the Allman style. Fortunately, when they want to beat me up about it, we have an Eclipse formatter configuration that makes the adjustments. |
|