Contents

Preface

I. Context

1. Philosophy: Philosophy Matters

1.1 Culture? What Culture?

1.2 The Durability of Unix

1.3 The Case against Learning Unix Culture

1.4 What Unix Gets Wrong

1.5 What Unix Gets Right

1.5.1 Open-Source Software

1.5.2 Cross-Platform Portability and Open Standards

1.5.3 The Internet and the World Wide Web

1.5.4 The Open-Source Community

1.5.5 Flexibility All the Way Down

1.5.6 Unix Is Fun to Hack

1.5.7 The Lessons of Unix Can Be Applied Elsewhere

1.6 Basics of the Unix Philosophy

1.6.1 Rule of Modularity: Write simple parts connected by clean interfaces.

1.6.2 Rule of Clarity: Clarity is better than cleverness.

1.6.3 Rule of Composition: Design programs to be connected with other programs.

1.6.4 Rule of Separation: Separate policy from mechanism; separate interfaces from engines.

1.6.5 Rule of Simplicity: Design for simplicity; add complexity only where you must.

1.6.6 Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.

1.6.7 Rule of Transparency: Design for visibility to make inspection and debugging easier.

1.6.8 Rule of Robustness: Robustness is the child of transparency and simplicity.

1.6.9 Rule of Representation: Fold knowledge into data, so program logic can be stupid and robust.

1.6.10 Rule of Least Surprise: In interface design, always do the least surprising thing.

1.6.11 Rule of Silence: When a program has nothing surprising to say, it should say nothing.

1.6.12 Rule of Repair: Repair what you can—but when you must fail, fail noisily and as soon as possible.

1.6.13 Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.

1.6.14 Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.

1.6.15 Rule of Optimization: Prototype before polishing. Get it working before you optimize it.

1.6.16 Rule of Diversity: Distrust all claims for “one true way”.

1.6.17 Rule of Extensibility: Design for the future, because it will be here sooner than you think.

1.7 The Unix Philosophy in One Lesson

1.8 Applying the Unix Philosophy

1.9 Attitude Matters Too

2. History: A Tale of Two Cultures

2.1 Origins and History of Unix, 1969–1995

2.1.1 Genesis: 1969–1971

2.1.2 Exodus: 1971–1980

2.1.3 TCP/IP and the Unix Wars: 1980–1990

2.1.4 Blows against the Empire: 1991–1995

2.2 Origins and History of the Hackers, 1961–1995

2.2.1 At Play in the Groves of Academe: 1961–1980

2.2.2 Internet Fusion and the Free Software Movement: 1981–1991

2.2.3 Linux and the Pragmatist Reaction: 1991–1998

2.3 The Open-Source Movement: 1998 and Onward

2.4 The Lessons of Unix History

3. Contrasts: Comparing the Unix Philosophy with Others

3.1 The Elements of Operating-System Style

3.1.1 What Is the Operating System’s Unifying Idea?

3.1.2 Multitasking Capability

3.1.3 Cooperating Processes

3.1.4 Internal Boundaries

3.1.5 File Attributes and Record Structures

3.1.6 Binary File Formats

3.1.7 Preferred User Interface Style

3.1.8 Intended Audience

3.1.9 Entry Barriers to Development

3.2 Operating-System Comparisons

3.2.1 VMS

3.2.2 MacOS

3.2.3 OS/2

3.2.4 Windows NT

3.2.5 BeOS

3.2.6 MVS

3.2.7 VM/CMS

3.2.8 Linux

3.3 What Goes Around, Comes Around

II. Design

4. Modularity: Keeping It Clean, Keeping It Simple

4.1 Encapsulation and Optimal Module Size

4.2 Compactness and Orthogonality

4.2.1 Compactness

4.2.2 Orthogonality

4.2.3 The SPOT Rule

4.2.4 Compactness and the Strong Single Center

4.2.5 The Value of Detachment

4.3 Software Is a Many-Layered Thing

4.3.1 Top-Down versus Bottom-Up

4.3.2 Glue Layers

4.3.3 Case Study: C Considered as Thin Glue

4.4 Libraries

4.4.1 Case Study: GIMP Plugins

4.5 Unix and Object-Oriented Languages

4.6 Coding for Modularity

5. Textuality: Good Protocols Make Good Practice

5.1 The Importance of Being Textual

5.1.1 Case Study: Unix Password File Format

5.1.2 Case Study: .newsrc Format

5.1.3 Case Study: The PNG Graphics File Format

5.2 Data File Metaformats

5.2.1 DSV Style

5.2.2 RFC 822 Format

5.2.3 Cookie-Jar Format

5.2.4 Record-Jar Format

5.2.5 XML

5.2.6 Windows INI Format

5.2.7 Unix Textual File Format Conventions

5.2.8 The Pros and Cons of File Compression

5.3 Application Protocol Design

5.3.1 Case Study: SMTP, a Simple Socket Protocol

5.3.2 Case Study: POP3, the Post Office Protocol

5.3.3 Case Study: IMAP, the Internet Message Access Protocol

5.4 Application Protocol Metaformats

5.4.1 The Classical Internet Application Metaprotocol

5.4.2 HTTP as a Universal Application Protocol

5.4.3 BEEP: Blocks Extensible Exchange Protocol

5.4.4 XML-RPC, SOAP, and Jabber

6. Transparency: Let There Be Light

6.1 Studying Cases

6.1.1 Case Study: audacity

6.1.2 Case Study: fetchmail’s -v option

6.1.3 Case Study: GCC

6.1.4 Case Study: kmail

6.1.5 Case Study: SNG

6.1.6 Case Study: The Terminfo Database

6.1.7 Case Study: Freeciv Data Files

6.2 Designing for Transparency and Discoverability

6.2.1 The Zen of Transparency

6.2.2 Coding for Transparency and Discoverability

6.2.3 Transparency and Avoiding Overprotectiveness

6.2.4 Transparency and Editable Representations

6.2.5 Transparency, Fault Diagnosis, and Fault Recovery

6.3 Designing for Maintainability

7. Multiprogramming: Separating Processes to Separate Function

7.1 Separating Complexity Control from Performance Tuning

7.2 Taxonomy of Unix IPC Methods

7.2.1 Handing off Tasks to Specialist Programs

7.2.2 Pipes, Redirection, and Filters

7.2.3 Wrappers

7.2.4 Security Wrappers and Bernstein Chaining

7.2.5 Slave Processes

7.2.6 Peer-to-Peer Inter-Process Communication

7.3 Problems and Methods to Avoid

7.3.1 Obsolescent Unix IPC Methods

7.3.2 Remote Procedure Calls

7.3.3 Threads—Threat or Menace?

7.4 Process Partitioning at the Design Level

8. Minilanguages: Finding a Notation That Sings

8.1 Understanding the Taxonomy of Languages

8.2 Applying Minilanguages

8.2.1 Case Study: sng

8.2.2 Case Study: Regular Expressions

8.2.3 Case Study: Glade

8.2.4 Case Study: m4

8.2.5 Case Study: XSLT

8.2.6 Case Study: The Documenter’s Workbench Tools

8.2.7 Case Study: fetchmail Run-Control Syntax

8.2.8 Case Study: awk

8.2.9 Case Study: PostScript

8.2.10 Case Study: bc and dc

8.2.11 Case Study: Emacs Lisp

8.2.12 Case Study: JavaScript

8.3 Designing Minilanguages

8.3.1 Choosing the Right Complexity Level

8.3.2 Extending and Embedding Languages

8.3.3 Writing a Custom Grammar

8.3.4 Macros—Beware!

8.3.5 Language or Application Protocol?

9. Generation: Pushing the Specification Level Upwards

9.1 Data-Driven Programming

9.1.1 Case Study: ascii

9.1.2 Case Study: Statistical Spam Filtering

9.1.3 Case Study: Metaclass Hacking in fetchmailconf

9.2 Ad-hoc Code Generation

9.2.1 Case Study: Generating Code for the ascii Displays

9.2.2 Case Study: Generating HTML Code for a Tabular List

10. Configuration: Starting on the Right Foot

10.1 What Should Be Configurable?

10.2 Where Configurations Live

10.3 Run-Control Files

10.3.1 Case Study: The .netrc File

10.3.2 Portability to Other Operating Systems

10.4 Environment Variables

10.4.1 System Environment Variables

10.4.2 User Environment Variables

10.4.3 When to Use Environment Variables

10.4.4 Portability to Other Operating Systems

10.5 Command-Line Options

10.5.1 The -a to -z of Command-Line Options

10.5.2 Portability to Other Operating Systems

10.6 How to Choose among the Methods

10.6.1 Case Study: fetchmail

10.6.2 Case Study: The XFree86 Server

10.7 On Breaking These Rules

11. Interfaces: User-Interface Design Patterns in the Unix Environment

11.1 Applying the Rule of Least Surprise

11.2 History of Interface Design on Unix

11.3 Evaluating Interface Designs

11.4 Tradeoffs between CLI and Visual Interfaces

11.4.1 Case Study: Two Ways to Write a Calculator Program

11.5 Transparency, Expressiveness, and Configurability

11.6 Unix Interface Design Patterns

11.6.1 The Filter Pattern

11.6.2 The Cantrip Pattern

11.6.3 The Source Pattern

11.6.4 The Sink Pattern

11.6.5 The Compiler Pattern

11.6.6 The ed pattern

11.6.7 The Roguelike Pattern

11.6.8 The ’Separated Engine and Interface’ Pattern

11.6.9 The CLI Server Pattern

11.6.10 Language-Based Interface Patterns

11.7 Applying Unix Interface-Design Patterns

11.7.1 The Polyvalent-Program Pattern

11.8 The Web Browser as a Universal Front End

11.9 Silence Is Golden

12. Optimization

12.1 Don’t Just Do Something, Stand There!

12.2 Measure before Optimizing

12.3 Nonlocality Considered Harmful

12.4 Throughput vs. Latency

12.4.1 Batching Operations

12.4.2 Overlapping Operations

12.4.3 Caching Operation Results

13. Complexity: As Simple As Possible, but No Simpler

13.1 Speaking of Complexity

13.1.1 The Three Sources of Complexity

13.1.2 Tradeoffs between Interface and Implementation Complexity

13.1.3 Essential, Optional, and Accidental Complexity

13.1.4 Mapping Complexity

13.1.5 When Simplicity Is Not Enough

13.2 A Tale of Five Editors

13.2.1 ed

13.2.2 vi

13.2.3 Sam

13.2.4 Emacs

13.2.5 Wily

13.3 The Right Size for an Editor

13.3.1 Identifying the Complexity Problems

13.3.2 Compromise Doesn’t Work

13.3.3 Is Emacs an Argument against the Unix Tradition?

13.4 The Right Size of Software

III. Implementation

14. Languages: To C or Not To C?

14.1 Unix’s Cornucopia of Languages

14.2 Why Not C?

14.3 Interpreted Languages and Mixed Strategies

14.4 Language Evaluations

14.4.1 C

14.4.2 C++

14.4.3 Shell

14.4.4 Perl

14.4.5 Tcl

14.4.6 Python

14.4.7 Java

14.4.8 Emacs Lisp

14.5 Trends for the Future

14.6 Choosing an X Toolkit

15. Tools: The Tactics of Development

15.1 A Developer-Friendly Operating System

15.2 Choosing an Editor

15.2.1 Useful Things to Know about vi

15.2.2 Useful Things to Know about Emacs

15.2.3 The Antireligious Choice: Using Both

15.3 Special-Purpose Code Generators

15.3.1 yacc and lex

15.3.2 Case Study: Glade

15.4 make: Automating Your Recipes

15.4.1 Basic Theory of make

15.4.2 make in Non-C/C++ Development

15.4.3 Utility Productions

15.4.4 Generating Makefiles

15.5 Version-Control Systems

15.5.1 Why Version Control?

15.5.2 Version Control by Hand

15.5.3 Automated Version Control

15.5.4 Unix Tools for Version Control

15.6 Runtime Debugging

15.7 Profiling

15.8 Combining Tools with Emacs

15.8.1 Emacs and make

15.8.2 Emacs and Runtime Debugging

15.8.3 Emacs and Version Control

15.8.4 Emacs and Profiling

15.8.5 Like an IDE, Only Better

16. Reuse: On Not Reinventing the Wheel

16.1 The Tale of J. Random Newbie

16.2 Transparency as the Key to Reuse

16.3 From Reuse to Open Source

16.4 The Best Things in Life Are Open

16.5 Where to Look?

16.6 Issues in Using Open-Source Software

16.7 Licensing Issues

16.7.1 What Qualifies as Open Source

16.7.2 Standard Open-Source Licenses

16.7.3 When You Need a Lawyer

IV. Community

17. Portability: Software Portability and Keeping Up Standards

17.1 Evolution of C

17.1.1 Early History of C

17.1.2 C Standards

17.2 Unix Standards

17.2.1 Standards and the Unix Wars

17.2.2 The Ghost at the Victory Banquet

17.2.3 Unix Standards in the Open-Source World

17.3 IETF and the RFC Standards Process

17.4 Specifications as DNA, Code as RNA

17.5 Programming for Portability

17.5.1 Portability and Choice of Language

17.5.2 Avoiding System Dependencies

17.5.3 Tools for Portability

17.6 Internationalization

17.7 Portability, Open Standards, and Open Source

18. Documentation: Explaining Your Code to a Web-Centric World

18.1 Documentation Concepts

18.2 The Unix Style

18.2.1 The Large-Document Bias

18.2.2 Cultural Style

18.3 The Zoo of Unix Documentation Formats

18.3.1 troff and the Documenter’s Workbench Tools

18.3.2 TEX

18.3.3 Texinfo

18.3.4 POD

18.3.5 HTML

18.3.6 DocBook

18.4 The Present Chaos and a Possible Way Out

18.5 DocBook

18.5.1 Document Type Definitions

18.5.2 Other DTDs

18.5.3 The DocBook Toolchain

18.5.4 Migration Tools

18.5.5 Editing Tools

18.5.6 Related Standards and Practices

18.5.7 SGML

18.5.8 XML-DocBook References

18.6 Best Practices for Writing Unix Documentation

19. Open Source: Programming in the New Unix Community

19.1 Unix and Open Source

19.2 Best Practices for Working with Open-Source Developers

19.2.1 Good Patching Practice

19.2.2 Good Project- and Archive-Naming Practice

19.2.3 Good Development Practice

19.2.4 Good Distribution-Making Practice

19.2.5 Good Communication Practice

19.3 The Logic of Licenses: How to Pick One

19.4 Why You Should Use a Standard License

19.5 Varieties of Open-Source Licensing

19.5.1 MIT or X Consortium License

19.5.2 BSD Classic License

19.5.3 Artistic License

19.5.4 General Public License

19.5.5 Mozilla Public License

20. Futures: Dangers and Opportunities

20.1 Essence and Accident in Unix Tradition

20.2 Plan 9: The Way the Future Was

20.3 Problems in the Design of Unix

20.3.1 A Unix File Is Just a Big Bag of Bytes

20.3.2 Unix Support for GUIs Is Weak

20.3.3 File Deletion Is Forever

20.3.4 Unix Assumes a Static Filesystem

20.3.5 The Design of Job Control Was Badly Botched

20.3.6 The Unix API Doesn’t Use Exceptions

20.3.7 ioctl(2) and fcntl(2) Are an Embarrassment

20.3.8 The Unix Security Model May Be Too Primitive

20.3.9 Unix Has Too Many Different Kinds of Names

20.3.10 File Systems Might Be Considered Harmful

20.3.11 Towards a Global Internet Address Space

20.4 Problems in the Environment of Unix

20.5 Problems in the Culture of Unix

20.6 Reasons to Believe

A. Glossary of Abbreviations

B. References

C. Contributors

D. Rootless Root: The Unix Koans of Master Foo

Colophon

Index

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.151.21