1. A Philosophy Of Software Design John Ousterhout
download
https://ebookbell.com/product/a-philosophy-of-software-design-
john-ousterhout-42507470
Explore and download more ebooks at ebookbell.com
2. Here are some recommended products that we believe you will be
interested in. You can click the link to download.
A Philosophy Of Software Design Ousterhout John
https://ebookbell.com/product/a-philosophy-of-software-design-
ousterhout-john-49563888
A Philosophy Of Software Design 2nd Edition Ousterhout John
https://ebookbell.com/product/a-philosophy-of-software-design-2nd-
edition-ousterhout-john-37173268
A Philosophy Of Software Design 2nd Edition 2nd Edition John K
Ousterhout
https://ebookbell.com/product/a-philosophy-of-software-design-2nd-
edition-2nd-edition-john-k-ousterhout-53309146
Prospective Philosophy Of Software A Simondonian Study Coline
Ferrarato
https://ebookbell.com/product/prospective-philosophy-of-software-a-
simondonian-study-coline-ferrarato-10658472
3. A Philosophy Of Gun Violence Alan J Reid
https://ebookbell.com/product/a-philosophy-of-gun-violence-alan-j-
reid-44898478
A Philosophy Of Faith Belief Truth And Varieties Of Commitment Finlay
Malcolm
https://ebookbell.com/product/a-philosophy-of-faith-belief-truth-and-
varieties-of-commitment-finlay-malcolm-46348350
A Philosophy Of Struggle The Leonard Harris Reader Leonard Harris
https://ebookbell.com/product/a-philosophy-of-struggle-the-leonard-
harris-reader-leonard-harris-46669104
A Philosophy Of Sacred Nature Leon Niemoczynski Nam T Nguyen
https://ebookbell.com/product/a-philosophy-of-sacred-nature-leon-
niemoczynski-nam-t-nguyen-49438154
A Philosophy Of Comedy On Stage And Screenyou Have To Be There Shaun
May
https://ebookbell.com/product/a-philosophy-of-comedy-on-stage-and-
screenyou-have-to-be-there-shaun-may-50219166
6. A Philosophy of Software Design
John Ousterhout
Stanford University
8. Contents
Preface
1 Introduction
1.1 How to use this book
2 The Nature of Complexity
2.1 Complexity defined
2.2 Symptoms of complexity
2.3 Causes of complexity
2.4 Complexity is incremental
2.5 Conclusion
3 Working Code Isn’t Enough
3.1 Tactical programming
3.2 Strategic programming
3.3 How much to invest?
3.4 Startups and investment
3.5 Conclusion
4 Modules Should Be Deep
4.1 Modular design
4.2 What’s in an interface?
4.3 Abstractions
4.4 Deep modules
4.5 Shallow modules
4.6 Classitis
4.7 Examples: Java and Unix I/O
4.8 Conclusion
9. 5 Information Hiding (and Leakage)
5.1 Information hiding
5.2 Information leakage
5.3 Temporal decomposition
5.4 Example: HTTP server
5.5 Example: too many classes
5.6 Example: HTTP parameter handling
5.7 Example: defaults in HTTP responses
5.8 Information hiding within a class
5.9 Taking it too far
5.10 Conclusion
6 General-Purpose Modules are Deeper
6.1 Make classes somewhat general-purpose
6.2 Example: storing text for an editor
6.3 A more general-purpose API
6.4 Generality leads to better information hiding
6.5 Questions to ask yourself
6.6 Conclusion
7 Different Layer, Different Abstraction
7.1 Pass-through methods
7.2 When is interface duplication OK?
7.3 Decorators
7.4 Interface versus implementation
7.5 Pass-through variables
7.6 Conclusion
8 Pull Complexity Downwards
8.1 Example: editor text class
8.2 Example: configuration parameters
8.3 Taking it too far
8.4 Conclusion
10. 9 Better Together Or Better Apart?
9.1 Bring together if information is shared
9.2 Bring together if it will simplify the interface
9.3 Bring together to eliminate duplication
9.4 Separate general-purpose and special-purpose code
9.5 Example: insertion cursor and selection
9.6 Example: separate class for logging
9.7 Example: editor undo mechanism
9.8 Splitting and joining methods
9.9 Conclusion
10 Define Errors Out Of Existence
10.1 Why exceptions add complexity
10.2 Too many exceptions
10.3 Define errors out of existence
10.4 Example: file deletion in Windows
10.5 Example: Java substring method
10.6 Mask exceptions
10.7 Exception aggregation
10.8 Just crash?
10.9 Design special cases out of existence
10.10 Taking it too far
10.11 Conclusion
11 Design it Twice
12 Why Write Comments? The Four Excuses
12.1 Good code is self-documenting
12.2 I don’t have time to write comments
12.3 Comments get out of date and become misleading
12.4 All the comments I have seen are worthless
12.5 Benefits of well-written comments
13 Comments Should Describe Things that Aren’t Obvious from the Code
11. 13.1 Pick conventions
13.2 Don’t repeat the code
13.3 Lower-level comments add precision
13.4 Higher-level comments enhance intuition
13.5 Interface documentation
13.6 Implementation comments: what and why, not how
13.7 Cross-module design decisions
13.8 Conclusion
13.9 Answers to questions from Section 13.5
14 Choosing Names
14.1 Example: bad names cause bugs
14.2 Create an image
14.3 Names should be precise
14.4 Use names consistently
14.5 A different opinion: Go style guide
14.6 Conclusion
15 Write The Comments First
15.1 Delayed comments are bad comments
15.2 Write the comments first
15.3 Comments are a design tool
15.4 Early comments are fun comments
15.5 Are early comments expensive?
15.6 Conclusion
16 Modifying Existing Code
16.1 Stay strategic
16.2 Maintaining comments: keep the comments near the code
16.3 Comments belong in the code, not the commit log
16.4 Maintaining comments: avoid duplication
16.5 Maintaining comments: check the diffs
16.6 Higher-level comments are easier to maintain
12. 17 Consistency
17.1 Examples of consistency
17.2 Ensuring consistency
17.3 Taking it too far
17.4 Conclusion
18 Code Should be Obvious
18.1 Things that make code more obvious
18.2 Things that make code less obvious
18.3 Conclusion
19 Software Trends
19.1 Object-oriented programming and inheritance
19.2 Agile development
19.3 Unit tests
19.4 Test-driven development
19.5 Design patterns
19.6 Getters and setters
19.7 Conclusion
20 Designing for Performance
20.1 How to think about performance
20.2 Measure before modifying
20.3 Design around the critical path
20.4 An example: RAMCloud Buffers
20.5 Conclusion
21 Conclusion
Index
Summary of Design Principles
Summary of Red Flags
13. Preface
People have been writing programs for electronic computers for more than 80
years, but there has been surprisingly little conversation about how to design
those programs or what good programs should look like. There has been
considerable discussion about software development processes such as agile
development and about development tools such as debuggers, version control
systems, and test coverage tools. There has also been extensive analysis of
programming techniques such as object-oriented programming and functional
programming, and of design patterns and algorithms. All of these discussions
have been valuable, but the core problem of software design is still largely
untouched. David Parnas’ classic paper “On the Criteria to be used in
Decomposing Systems into Modules” appeared in 1971, but the state of the
art in software design has not progressed much beyond that paper in the
ensuing 45 years.
The most fundamental problem in computer science is problem
decomposition: how to take a complex problem and divide it up into pieces
that can be solved independently. Problem decomposition is the central
design task that programmers face every day, and yet, other than the work
described here, I have not been able to identify a single class in any
university where problem decomposition is a central topic. We teach for
loops and object-oriented programming, but not software design.
In addition, there is a huge variation in quality and productivity among
programmers, but we have made little attempt to understand what makes the
best programmers so much better or to teach those skills in our classes. I have
talked with several people I consider to be great programmers, but most of
them had difficulty articulating specific techniques that give them their
advantage. Many people assume that software design skill is an innate talent
that cannot be taught. However, there is quite a bit of scientific evidence that
outstanding performance in many fields is related more to high-quality
practice than innate ability (see, for example, Talent is Overrated by Geoff
Colvin).
14. For many years these issues have perplexed and frustrated me. I have
wondered whether software design can be taught, and I have hypothesized
that design skill is what separates great programmers from average ones. I
finally decided that the only way to answer these questions was to attempt to
teach a course on software design. The result is CS 190 at Stanford
University. In this class I put forth a set of principles of software design.
Students then work through a series of projects to assimilate and practice the
principles. The class is taught in a fashion similar to a traditional English
writing class. In an English class, students use an iterative process where they
write a draft, get feedback, and then rewrite to make improvements. In CS
190, students develop a substantial piece of software from scratch. We then
go through extensive code reviews to identify design problems, and students
revise their projects to fix the problems. This allows students to see how their
code can be improved by applying design principles.
I have now taught the software design class three times, and this book is
based on the design principles that emerged from the class. The principles are
fairly high level and border on the philosophical (“Define errors out of
existence”), so it is hard for students to understand the ideas in the abstract.
Students learn best by writing code, making mistakes, and then seeing how
their mistakes and the subsequent fixes relate to the principles.
At this point you may well be wondering: what makes me think I know
all the answers about software design? To be honest, I don’t. There were no
classes on software design when I learned to program, and I never had a
mentor to teach me design principles. At the time I learned to program, code
reviews were virtually nonexistent. My ideas about software design come
from personal experience writing and reading code. Over my career I have
written about 250,000 lines of code in a variety of languages. I’ve worked on
teams that created three operating systems from scratch, multiple file and
storage systems, infrastructure tools such as debuggers, build systems, and
GUI toolkits, a scripting language, and interactive editors for text, drawings,
presentations, and integrated circuits. Along the way I’ve experienced
firsthand the problems of large systems and experimented with various
design techniques. In addition, I’ve read a considerable amount of code
written by other people, which has exposed me to a variety of approaches,
both good and bad.
15. Out of all of this experience, I’ve tried to extract common threads, both
about mistakes to avoid and techniques to use. This book is a reflection of my
experiences: every problem described here is one that I have experienced
personally, and every suggested technique is one that I have used
successfully in my own coding.
I don’t expect this book to be the final word on software design; I’m sure
there are valuable techniques that I’ve missed, and some of my suggestions
may turn out to be bad ideas in the long run. However, I hope that the book
will start a conversation about software design. Compare the ideas in this
book with your own experiences and decide for yourself whether the
approaches described here really do reduce software complexity. This book is
an opinion piece, so some readers will disagree with some of my suggestions.
If you do disagree, try to understand why. I’m interested in hearing about
things that work for you, things that don’t work, and any other ideas you may
have about software design. I hope that the ensuing conversations will
improve our collective understanding of software design. I will incorporate
what I learn in future editions of this book.
The best way to communicate with me about the book is to send email to
the following address:
[email protected]
I’m interested in hearing specific feedback about the book, such as bugs or
suggestions for improvement, as well as general thoughts and experiences
related to software design. I’m particularly interested in compelling examples
that I can use in future editions of the book. The best examples illustrate an
important design principle and are simple enough to explain in a paragraph or
two. If you would like to see what other people are saying on the email
address and participate in discussions, you can join the Google Group
software-design-book.
If for some reason the software-design-book Google Group should
disappear in the future, search on the Web for my home page; it will contain
updated instructions for how to communicate about the book. Please don’t
send book-related email to my personal email address.
16. I recommend that you take the suggestions in this book with a grain of
salt. The overall goal is to reduce complexity; this is more important than any
particular principle or idea you read here. If you try an idea from this book
and find that it doesn’t actually reduce complexity, then don’t feel obligated
to keep using it (but, do let me know about your experience; I’d like to get
feedback on what works and what doesn’t).
Many people have offered criticisms or made suggestions that improved
the quality of the book. The following people offered helpful comments on
various drafts of the book: Jeff Dean, Sanjay Ghemawat, John Hartman,
Brian Kernighan, James Koppel, Amy Ousterhout, Kay Ousterhout, Rob
Pike, Partha Ranganathan, Keith Schwartz, and Alex Snaps. Christos
Kozyrakis suggested the terms “deep” and “shallow” for classes and
interfaces, replacing previous terms “thick” and “thin”, which were
somewhat ambiguous. I am indebted to the students in CS 190; the process of
reading their code and discussing it with them has helped to crystallize my
thoughts about design.
17. Chapter 1
Introduction
(It’s All About Complexity)
Writing computer software is one of the purest creative activities in the
history of the human race. Programmers aren’t bound by practical limitations
such as the laws of physics; we can create exciting virtual worlds with
behaviors that could never exist in the real world. Programming doesn’t
require great physical skill or coordination, like ballet or basketball. All
programming requires is a creative mind and the ability to organize your
thoughts. If you can visualize a system, you can probably implement it in a
computer program.
This means that the greatest limitation in writing software is our ability to
understand the systems we are creating. As a program evolves and acquires
more features, it becomes complicated, with subtle dependencies between its
components. Over time, complexity accumulates, and it becomes harder and
harder for programmers to keep all of the relevant factors in their minds as
they modify the system. This slows down development and leads to bugs,
which slow development even more and add to its cost. Complexity increases
inevitably over the life of any program. The larger the program, and the more
people that work on it, the more difficult it is to manage complexity.
Good development tools can help us deal with complexity, and many
great tools have been created over the last several decades. But there is a limit
to what we can do with tools alone. If we want to make it easier to write
software, so that we can build more powerful systems more cheaply, we must
find ways to make software simpler. Complexity will still increase over time,
in spite of our best efforts, but simpler designs allow us to build larger and
more powerful systems before complexity becomes overwhelming.
18. There are two general approaches to fighting complexity, both of which
will be discussed in this book. The first approach is to eliminate complexity
by making code simpler and more obvious. For example, complexity can be
reduced by eliminating special cases or using identifiers in a consistent
fashion.
The second approach to complexity is to encapsulate it, so that
programmers can work on a system without being exposed to all of its
complexity at once. This approach is called modular design. In modular
design, a software system is divided up into modules, such as classes in an
object-oriented language. The modules are designed to be relatively
independent of each other, so that a programmer can work on one module
without having to understand the details of other modules.
Because software is so malleable, software design is a continuous process
that spans the entire lifecycle of a software system; this makes software
design different from the design of physical systems such as buildings, ships,
or bridges. However, software design has not always been viewed this way.
For much of the history of programming, design was concentrated at the
beginning of a project, as it is in other engineering disciplines. The extreme
of this approach is called the waterfall model, in which a project is divided
into discrete phases such as requirements definition, design, coding, testing,
and maintenance. In the waterfall model, each phase completes before the
next phase starts; in many cases different people are responsible for each
phase. The entire system is designed at once, during the design phase. The
design is frozen at the end of this phase, and the role of the subsequent phases
is to flesh out and implement that design.
Unfortunately, the waterfall model rarely works well for software.
Software systems are intrinsically more complex than physical systems; it
isn’t possible to visualize the design for a large software system well enough
to understand all of its implications before building anything. As a result, the
initial design will have many problems. The problems do not become
apparent until implementation is well underway. However, the waterfall
model is not structured to accommodate major design changes at this point
(for example, the designers may have moved on to other projects). Thus,
developers try to patch around the problems without changing the overall
design. This results in an explosion of complexity.
19. Because of these issues, most software development projects today use an
incremental approach such as agile development, in which the initial design
focuses on a small subset of the overall functionality. This subset is designed,
implemented, and then evaluated. Problems with the original design are
discovered and corrected, then a few more features are designed,
implemented and evaluated. Each iteration exposes problems with the
existing design, which are fixed before the next set of features is designed.
By spreading out the design in this way, problems with the initial design can
be fixed while the system is still small; later features benefit from experience
gained during the implementation of earlier features, so they have fewer
problems.
The incremental approach works for software because software is
malleable enough to allow significant design changes partway through
implementation. In contrast, major design changes are much more
challenging for physical systems: for example, it would not be practical to
change the number of towers supporting a bridge in the middle of
construction.
Incremental development means that software design is never done.
Design happens continuously over the life of a system: developers should
always be thinking about design issues. Incremental development also means
continuous redesign. The initial design for a system or component is almost
never the best one; experience inevitably shows better ways to do things. As
a software developer, you should always be on the lookout for opportunities
to improve the design of the system you are working on, and you should plan
on spending some fraction of your time on design improvements.
If software developers should always be thinking about design issues, and
reducing complexity is the most important element of software design, then
software developers should always be thinking about complexity. This book
is about how to use complexity to guide the design of software throughout its
lifetime.
This book has two overall goals. The first is to describe the nature of
software complexity: what does “complexity” mean, why does it matter, and
how can you recognize when a program has unnecessary complexity? The
book’s second, and more challenging, goal is to present techniques you can
use during the software development process to minimize complexity.
20. Unfortunately, there isn’t a simple recipe that will guarantee great software
designs. Instead, I will present a collection of higher-level concepts that
border on the philosophical, such as “classes should be deep” or “define
errors out of existence.” These concepts may not immediately identify the
best design, but you can use them to compare design alternatives and guide
your exploration of the design space.
1.1 How to use this book
Many of the design principles described here are somewhat abstract, so they
may be hard to appreciate without looking at actual code. It has been a
challenge to find examples that are small enough to include in the book, yet
large enough to illustrate problems with real systems (if you encounter good
examples, please send them to me). Thus, this book may not be sufficient by
itself for you to learn how to apply the principles.
The best way to use this book is in conjunction with code reviews. When
you read other people’s code, think about whether it conforms to the concepts
discussed here and how that relates to the complexity of the code. It’s easier
to see design problems in someone else’s code than your own. You can use
the red flags described here to identify problems and suggest improvements.
Reviewing code will also expose you to new design approaches and
programming techniques.
One of the best ways to improve your design skills is to learn to recognize
red flags: signs that a piece of code is probably more complicated than it
needs to be. Over the course of this book I will point out red flags that
suggest problems related to each major design issue; the most important ones
are summarized at the back of the book. You can then use these when you are
coding: when you see a red flag, stop and look for an alternate design that
eliminates the problem. When you first try this approach, you may have to try
several design alternatives before you find one that eliminates the red flag.
Don’t give up easily: the more alternatives you try before fixing the problem,
the more you will learn. Over time, you will find that your code has fewer
and fewer red flags, and your designs are cleaner and cleaner. Your
experience will also show you other red flags that you can use to identify
design problems (I’d be happy to hear about these).
21. When applying the ideas from this book, it’s important to use moderation
and discretion. Every rule has its exceptions, and every principle has its
limits. If you take any design idea to its extreme, you will probably end up in
a bad place. Beautiful designs reflect a balance between competing ideas and
approaches. Several chapters have sections titled “Taking it too far,” which
describe how to recognize when you are overdoing a good thing.
Almost all of the examples in this book are in Java or C++, and much of
the discussion is in terms of designing classes in an object-oriented language.
However, the ideas apply in other domains as well. Almost all of the ideas
related to methods can also be applied to functions in a language without
object-oriented features, such as C. The design ideas also apply to modules
other than classes, such as subsystems or network services.
With this background, let’s discuss in more detail what causes
complexity, and how to make software systems simpler.
22. Chapter 2
The Nature of Complexity
This book is about how to design software systems to minimize their
complexity. The first step is to understand the enemy. Exactly what is
“complexity”? How can you tell if a system is unnecessarily complex? What
causes systems to become complex? This chapter will address those
questions at a high level; subsequent chapters will show you how to
recognize complexity at a lower level, in terms of specific structural features.
The ability to recognize complexity is a crucial design skill. It allows you
to identify problems before you invest a lot of effort in them, and it allows
you to make good choices among alternatives. It is easier to tell whether a
design is simple than it is to create a simple design, but once you can
recognize that a system is too complicated, you can use that ability to guide
your design philosophy towards simplicity. If a design appears complicated,
try a different approach and see if that is simpler. Over time, you will notice
that certain techniques tend to result in simpler designs, while others correlate
with complexity. This will allow you to produce simpler designs more
quickly.
This chapter also lays out some basic assumptions that provide a
foundation for the rest of the book. Later chapters take the material of this
chapter as given and use it to justify a variety of refinements and conclusions.
2.1 Complexity defined
For the purposes of this book, I define “complexity” in a practical way.
Complexity is anything related to the structure of a software system that
makes it hard to understand and modify the system. Complexity can take
many forms. For example, it might be hard to understand how a piece of code
works; it might take a lot of effort to implement a small improvement, or it
23. might not be clear which parts of the system must be modified to make the
improvement; it might be difficult to fix one bug without introducing another.
If a software system is hard to understand and modify, then it is complicated;
if it is easy to understand and modify, then it is simple.
You can also think of complexity in terms of cost and benefit. In a
complex system, it takes a lot of work to implement even small
improvements. In a simple system, larger improvements can be implemented
with less effort.
Complexity is what a developer experiences at a particular point in time
when trying to achieve a particular goal. It doesn’t necessarily relate to the
overall size or functionality of the system. People often use the word
“complex” to describe large systems with sophisticated features, but if such a
system is easy to work on, then, for the purposes of this book, it is not
complex. Of course, almost all large and sophisticated software systems are
in fact hard to work on, so they also meet my definition of complexity, but
this need not necessarily be the case. It is also possible for a small and
unsophisticated system to be quite complex.
Complexity is determined by the activities that are most common. If a
system has a few parts that are very complicated, but those parts almost never
need to be touched, then they don’t have much impact on the overall
complexity of the system. To characterize this in a crude mathematical way:
The overall complexity of a system (C) is determined by the complexity
of each part p (cp) weighted by the fraction of time developers spend working
on that part (tp). Isolating complexity in a place where it will never be seen is
almost as good as eliminating the complexity entirely.
Complexity is more apparent to readers than writers. If you write a piece
of code and it seems simple to you, but other people think it is complex, then
it is complex. When you find yourself in situations like this, it’s worth
probing the other developers to find out why the code seems complex to
them; there are probably some interesting lessons to learn from the
disconnect between your opinion and theirs. Your job as a developer is not
24. just to create code that you can work with easily, but to create code that
others can also work with easily.
2.2 Symptoms of complexity
Complexity manifests itself in three general ways, which are described in the
paragraphs below. Each of these manifestations makes it harder to carry out
development tasks.
Change amplification: The first symptom of complexity is that a
seemingly simple change requires code modifications in many different
places. For example, consider a Web site containing several pages, each of
which displays a banner with a background color. In many early Web sites,
the color was specified explicitly on each page, as shown in Figure 2.1(a). In
order to change the background for such a Web site, a developer might have
to modify every existing page by hand; this would be nearly impossible for a
large site with thousands of pages. Fortunately, modern Web sites use an
approach like that in Figure 2.1(b), where the banner color is specified once
in a central place, and all of the individual pages reference that shared value.
With this approach, the banner color of the entire Web site can be changed
with a single modification. One of the goals of good design is to reduce the
amount of code that is affected by each design decision, so design changes
don’t require very many code modifications.
Cognitive load: The second symptom of complexity is cognitive load,
which refers to how much a developer needs to know in order to complete a
task. A higher cognitive load means that developers have to spend more time
learning the required information, and there is a greater risk of bugs because
they have missed something important. For example, suppose a function in C
allocates memory, returns a pointer to that memory, and assumes that the
caller will free the memory. This adds to the cognitive load of developers
using the function; if a developer fails to free the memory, there will be a
memory leak. If the system can be restructured so that the caller doesn’t need
to worry about freeing the memory (the same module that allocates the
memory also takes responsibility for freeing it), it will reduce the cognitive
load. Cognitive load arises in many ways, such as APIs with many methods,
global variables, inconsistencies, and dependencies between modules.
25. System designers sometimes assume that complexity can be measured by
lines of code. They assume that if one implementation is shorter than another,
then it must be simpler; if it only takes a few lines of code to make a change,
then the change must be easy. However, this view ignores the costs
associated with cognitive load. I have seen frameworks that allowed
applications to be written with only a few lines of code, but it was extremely
difficult to figure out what those lines were. Sometimes an approach that
requires more lines of code is actually simpler, because it reduces
cognitive load.
Figure 2.1: Each page in a Web site displays a colored banner. In (a) the background color for the
banner is specified explicitly in each page. In (b) a shared variable holds the background color and each
page references that variable. In (c) some pages display an additional color for emphasis, which is a
darker shade of the banner background color; if the background color changes, the emphasis color must
also change.
Unknown unknowns: The third symptom of complexity is that it is not
obvious which pieces of code must be modified to complete a task, or what
information a developer must have to carry out the task successfully. Figure
2.1(c) illustrates this problem. The Web site uses a central variable to
determine the banner background color, so it appears to be easy to change.
However, a few Web pages use a darker shade of the background color for
emphasis, and that darker color is specified explicitly in the individual pages.
If the background color changes, then the the emphasis color must change to
match. Unfortunately, developers are unlikely to realize this, so they may
change the central bannerBg variable without updating the emphasis color.
26. Even if a developer is aware of the problem, it won’t be obvious which pages
use the emphasis color, so the developer may have to search every page in the
Web site.
Of the three manifestations of complexity, unknown unknowns are the
worst. An unknown unknown means that there is something you need to
know, but there is no way for you to find out what it is, or even whether there
is an issue. You won’t find out about it until bugs appear after you make a
change. Change amplification is annoying, but as long as it is clear which
code needs to be modified, the system will work once the change has been
completed. Similarly, a high cognitive load will increase the cost of a change,
but if it is clear which information to read, the change is still likely to be
correct. With unknown unknowns, it is unclear what to do or whether a
proposed solution will even work. The only way to be certain is to read every
line of code in the system, which is impossible for systems of any size. Even
this may not be sufficient, because a change may depend on a subtle design
decision that was never documented.
One of the most important goals of good design is for a system to be
obvious. This is the opposite of high cognitive load and unknown unknowns.
In an obvious system, a developer can quickly understand how the existing
code works and what is required to make a change. An obvious system is one
where a developer can make a quick guess about what to do, without thinking
very hard, and yet be confident that the guess is correct. Chapter 18 discusses
techniques for making code more obvious.
2.3 Causes of complexity
Now that you know the high-level symptoms of complexity and why
complexity makes software development difficult, the next step is to
understand what causes complexity, so that we can design systems to avoid
the problems. Complexity is caused by two things: dependencies and
obscurity. This section discusses these factors at a high level; subsequent
chapters will discuss how they relate to lower-level design decisions.
For the purposes of this book, a dependency exists when a given piece of
code cannot be understood and modified in isolation; the code relates in some
way to other code, and the other code must be considered and/or modified if
27. the given code is changed. In the Web site example of Figure 2.1(a), the
background color creates dependencies between all of the pages. All of the
pages need to have the same background, so if the background is changed for
one page, then it must be changed for all of them. Another example of
dependencies occurs in network protocols. Typically there is separate code
for the sender and receiver for the protocol, but they must each conform to
the protocol; changing the code for the sender almost always requires
corresponding changes at the receiver, and vice versa. The signature of a
method creates a dependency between the implementation of that method and
the code that invokes it: if a new parameter is added to a method, all of the
invocations of that method must be modified to specify that parameter.
Dependencies are a fundamental part of software and can’t be completely
eliminated. In fact, we intentionally introduce dependencies as part of the
software design process. Every time you write a new class you create
dependencies around the API for that class. However, one of the goals of
software design is to reduce the number of dependencies and to make the
dependencies that remain as simple and obvious as possible.
Consider the Web site example. In the old Web site with the background
specified separately on each page, all of the Web pages were dependent on
each other. The new Web site fixed this problem by specifying the
background color in a central place and providing an API that individual
pages use to retrieve that color when they are rendered. The new Web site
eliminated the dependency between the pages, but it created a new
dependency around the API for retrieving the background color. Fortunately,
the new dependency is more obvious: it is clear that each individual Web
page depends on the bannerBg color, and a developer can easily find all the
places where the variable is used by searching for its name. Furthermore,
compilers help to manage API dependencies: if the name of the shared
variable changes, compilation errors will occur in any code that still uses the
old name. The new Web site replaced a nonobvious and difficult-to-manage
dependency with a simpler and more obvious one.
The second cause of complexity is obscurity. Obscurity occurs when
important information is not obvious. A simple example is a variable name
that is so generic that it doesn’t carry much useful information (e.g., time).
Or, the documentation for a variable might not specify its units, so the only
28. way to find out is to scan code for places where the variable is used.
Obscurity is often associated with dependencies, where it is not obvious that
a dependency exists. For example, if a new error status is added to a system,
it may be necessary to add an entry to a table holding string messages for
each status, but the existence of the message table might not be obvious to a
programmer looking at the status declaration. Inconsistency is also a major
contributor to obscurity: if the same variable name is used for two different
purposes, it won’t be obvious to developer which of these purposes a
particular variable serves.
In many cases, obscurity comes about because of inadequate
documentation; Chapter 13 deals with this topic. However, obscurity is also a
design issue. If a system has a clean and obvious design, then it will need less
documentation. The need for extensive documentation is often a red flag that
the design isn’t quite right. The best way to reduce obscurity is by
simplifying the system design.
Together, dependencies and obscurity account for the three
manifestations of complexity described in Section 2.2. Dependencies lead to
change amplification and a high cognitive load. Obscurity creates unknown
unknowns, and also contributes to cognitive load. If we can find design
techniques that minimize dependencies and obscurity, then we can reduce the
complexity of software.
2.4 Complexity is incremental
Complexity isn’t caused by a single catastrophic error; it accumulates in lots
of small chunks. A single dependency or obscurity, by itself, is unlikely to
affect significantly the maintainability of a software system. Complexity
comes about because hundreds or thousands of small dependencies and
obscurities build up over time. Eventually, there are so many of these small
issues that every possible change to the system is affected by several of them.
The incremental nature of complexity makes it hard to control. It’s easy
to convince yourself that a little bit of complexity introduced by your current
change is no big deal. However, if every developer takes this approach for
every change, complexity accumulates rapidly. Once complexity has
accumulated, it is hard to eliminate, since fixing a single dependency or
29. obscurity will not, by itself, make a big difference. In order to slow the
growth of complexity, you must adopt a “zero tolerance” philosophy, as
discussed in Chapter 3.
2.5 Conclusion
Complexity comes from an accumulation of dependencies and obscurities. As
complexity increases, it leads to change amplification, a high cognitive load,
and unknown unknowns. As a result, it takes more code modifications to
implement each new feature. In addition, developers spend more time
acquiring enough information to make the change safely and, in the worst
case, they can’t even find all the information they need. The bottom line is
that complexity makes it difficult and risky to modify an existing code base.
30. Chapter 3
Working Code Isn’t Enough
(Strategic vs. Tactical Programming)
One of the most important elements of good software design is the
mindset you adopt when you approach a programming task. Many
organizations encourage a tactical mindset, focused on getting features
working as quickly as possible. However, if you want a good design, you
must take a more strategic approach where you invest time to produce clean
designs and fix problems. This chapter discusses why the strategic approach
produces better designs and is actually cheaper than the tactical approach
over the long run.
3.1 Tactical programming
Most programmers approach software development with a mindset I call
tactical programming. In the tactical approach, your main focus is to get
something working, such as a new feature or a bug fix. At first glance this
seems totally reasonable: what could be more important than writing code
that works? However, tactical programming makes it nearly impossible to
produce a good system design.
The problem with tactical programming is that it is short-sighted. If
you’re programming tactically, you’re trying to finish a task as quickly as
possible. Perhaps you have a hard deadline. As a result, planning for the
future isn’t a priority. You don’t spend much time looking for the best
design; you just want to get something working soon. You tell yourself that
it’s OK to add a bit of complexity or introduce a small kludge or two, if that
allows the current task to be completed more quickly.
31. This is how systems become complicated. As discussed in the previous
chapter, complexity is incremental. It’s not one particular thing that makes a
system complicated, but the accumulation of dozens or hundreds of small
things. If you program tactically, each programming task will contribute a
few of these complexities. Each of them probably seems like a reasonable
compromise in order to finish the current task quickly. However, the
complexities accumulate rapidly, especially if everyone is programming
tactically.
Before long, some of the complexities will start causing problems, and
you will begin to wish you hadn’t taken those early shortcuts. But, you will
tell yourself that it’s more important to get the next feature working than to
go back and refactor existing code. Refactoring may help out in the long run,
but it will definitely slow down the current task. So, you look for quick
patches to work around any problems you encounter. This just creates more
complexity, which then requires more patches. Pretty soon the code is a mess,
but by this point things are so bad that it would take months of work to clean
it up. There’s no way your schedule can tolerate that kind of delay, and fixing
one or two of the problems doesn’t seem like it will make much difference,
so you just keep programming tactically.
If you have worked on a large software project for very long, I suspect
you have seen tactical programming at work and have experienced the
problems that result. Once you start down the tactical path, it’s difficult to
change.
Almost every software development organization has at least one
developer who takes tactical programming to the extreme: a tactical tornado.
The tactical tornado is a prolific programmer who pumps out code far faster
than others but works in a totally tactical fashion. When it comes to
implementing a quick feature, nobody gets it done faster than the tactical
tornado. In some organizations, management treats tactical tornadoes as
heroes. However, tactical tornadoes leave behind a wake of destruction. They
are rarely considered heroes by the engineers who must work with their code
in the future. Typically, other engineers must clean up the messes left behind
by the tactical tornado, which makes it appear that those engineers (who are
the real heroes) are making slower progress than the tactical tornado.
32. 3.2 Strategic programming
The first step towards becoming a good software designer is to realize that
working code isn’t enough. It’s not acceptable to introduce unnecessary
complexities in order to finish your current task faster. The most important
thing is the long-term structure of the system. Most of the code in any system
is written by extending the existing code base, so your most important job as
a developer is to facilitate those future extensions. Thus, you should not think
of “working code” as your primary goal, though of course your code must
work. Your primary goal must be to produce a great design, which also
happens to work. This is strategic programming.
Strategic programming requires an investment mindset. Rather than
taking the fastest path to finish your current project, you must invest time to
improve the design of the system. These investments will slow you down a
bit in the short term, but they will speed you up in the long term, as illustrated
in Figure 3.1.
Some of the investments will be proactive. For example, it’s worth taking
a little extra time to find a simple design for each new class; rather than
implementing the first idea that comes to mind, try a couple of alternative
designs and pick the cleanest one. Try to imagine a few ways in which the
system might need to be changed in the future and make sure that will be
easy with your design. Writing good documentation is another example of a
proactive investment.
Other investments will be reactive. No matter how much you invest up
front, there will inevitably be mistakes in your design decisions. Over time,
these mistakes will become obvious. When you discover a design problem,
don’t just ignore it or patch around it; take a little extra time to fix it. If you
program strategically, you will continually make small improvements to the
system design. This is the opposite of tactical programming, where you are
continually adding small bits of complexity that cause problems in the future.
3.3 How much to invest?
So, what is the right amount of investment? A huge up-front investment, such
as trying to design the entire system, won’t be effective. This is the waterfall
method, and we know it doesn’t work. The ideal design tends to emerge in
33. bits and pieces, as you get experience with the system. Thus, the best
approach is to make lots of small investments on a continual basis. I suggest
spending about 10–20% of your total development time on investments. This
amount is small enough that it won’t impact your schedules significantly, but
large enough to produce significant benefits over time. Your initial projects
will thus take 10–20% longer than they would in a purely tactical approach.
That extra time will result in a better software design, and you will start
experiencing the benefits within a few months. It won’t be long before you’re
developing at least 10–20% faster than you would if you had programmed
tactically. At this point your investments become free: the benefits from your
past investments will save enough time to cover the cost of future
investments. You will quickly recover the cost of the initial investment.
Figure 3.1 illustrates this phenomenon.
Figure 3.1: At the beginning, a tactical approach to programming will make progress more quickly
than a strategic approach. However, complexity accumulates more rapidly under the tactical approach,
which reduces productivity. Over time, the strategic approach results in greater progress. Note: this
figure is intended only as a qualitative illustration; I am not aware of any empirical measurements of
the precise shapes of the curves.
Conversely, if you program tactically, you will finish your first projects
10–20% faster, but over time your development speed will slow as
complexity accumulates. It won’t be long before you’re programming at least
10–20% slower. You will quickly give back all of the time you saved at the
beginning, and for the rest of system’s lifetime you will be developing more
slowly than if you had taken the strategic approach. If you haven’t ever
worked in a badly degraded code base, talk to someone who has; they will
tell you that poor code quality slows development by at least 20%.
3.4 Startups and investment
34. In some environments there are strong forces working against the strategic
approach. For example, early-stage startups feel tremendous pressure to get
their early releases out quickly. In these companies, it might seem that even a
10–20% investment isn’t affordable. As a result, many startups take a tactical
approach, spending little effort on design and even less on cleanup when
problems pop up. They rationalize this with the thought that, if they are
successful, they’ll have enough money to hire extra engineers to clean things
up.
If you are in a company leaning in this direction, you should realize that
once a code base turns to spaghetti, it is nearly impossible to fix. You will
probably pay high development costs for the life of the product. Furthermore,
the payoff for good (or bad) design comes pretty quickly, so there’s a good
chance that the tactical approach won’t even speed up your first product
release.
Another thing to consider is that one of the most important factors for
success of a company is the quality of its engineers. The best way to lower
development costs is to hire great engineers: they don’t cost much more than
mediocre engineers but have tremendously higher productivity. However, the
best engineers care deeply about good design. If your code base is a wreck,
word will get out, and this will make it harder for you to recruit. As a result,
you are likely to end up with mediocre engineers. This will increase your
future costs and probably cause the system structure to degrade even more.
Facebook is an example of a startup that encouraged tactical
programming. For many years the company’s motto was “Move fast and
break things.” New engineers fresh out of college were encouraged to dive
immediately into the company’s code base; it was normal for engineers to
push commits into production in their first week on the job. On the positive
side, Facebook developed a reputation as a company that empowered its
employees. Engineers had tremendous latitude, and there were few rules and
restrictions to get in their way.
Facebook has been spectacularly successful as a company, but its code
base suffered because of the company’s tactical approach; much of the code
was unstable and hard to understand, with few comments or tests, and painful
to work with. Over time the company realized that its culture was
unsustainable. Eventually, Facebook changed its motto to “Move fast with
35. solid infrastructure” to encourage its engineers to invest more in good design.
It remains to be seen whether Facebook can successfully clean up the
problems that accumulated over years of tactical programming.
In fairness to Facebook, I should point out that Facebook’s code probably
isn’t much worse than average among startups. Tactical programming is
commonplace among startups; Facebook just happens to be a particularly
visible example.
Fortunately, it is also possible to succeed in Silicon Valley with a
strategic approach. Google and VMware grew up around the same time as
Facebook, but both of these companies embraced a more strategic approach.
Both companies placed a heavy emphasis on high quality code and good
design, and both companies built sophisticated products that solved complex
problems with reliable software systems. The companies’ strong technical
cultures became well known in Silicon Valley. Few other companies could
compete with them for hiring the top technical talent.
These examples show that a company can succeed with either approach.
However, it’s a lot more fun to work in a company that cares about software
design and has a clean code base.
3.5 Conclusion
Good design doesn’t come for free. It has to be something you invest in
continually, so that small problems don’t accumulate into big ones.
Fortunately, good design eventually pays for itself, and sooner than you
might think.
It’s crucial to be consistent in applying the strategic approach and to think
of investment as something to do today, not tomorrow. When you get in a
crunch it will be tempting to put off cleanups until after the crunch is over.
However, this is a slippery slope; after the current crunch there will almost
certainly be another one, and another after that. Once you start delaying
design improvements, it’s easy for the delays to become permanent and for
your culture to slip into the tactical approach. The longer you wait to address
design problems, the bigger they become; the solutions become more
intimidating, which makes it easy to put them off even more. The most
36. effective approach is one where every engineer makes continuous small
investments in good design.
37. Chapter 4
Modules Should Be Deep
One of the most important techniques for managing software complexity is to
design systems so that developers only need to face a small fraction of the
overall complexity at any given time. This approach is called modular design,
and this chapter presents its basic principles.
4.1 Modular design
In modular design, a software system is decomposed into a collection of
modules that are relatively independent. Modules can take many forms, such
as classes, subsystems, or services. In an ideal world, each module would be
completely independent of the others: a developer could work in any of the
modules without knowing anything about any of the other modules. In this
world, the complexity of a system would be the complexity of its worst
module.
Unfortunately, this ideal is not achievable. Modules must work together
by calling each others’s functions or methods. As a result, modules must
know something about each other. There will be dependencies between the
modules: if one module changes, other modules may need to change to
match. For example, the arguments for a method create a dependency
between the method and any code that invokes the method. If the required
arguments change, all invocations of the method must be modified to
conform to the new signature. Dependencies can take many other forms, and
they can be quite subtle. The goal of modular design is to minimize the
dependencies between modules.
In order to manage dependencies, we think of each module in two parts:
an interface and an implementation. The interface consists of everything that
a developer working in a different module must know in order to use the
38. given module. Typically, the interface describes what the module does but
not how it does it. The implementation consists of the code that carries out
the promises made by the interface. A developer working in a particular
module must understand the interface and implementation of that module,
plus the interfaces of any other modules invoked by the given module. A
developer should not need to understand the implementations of modules
other than the one he or she is working in.
Consider a module that implements balanced trees. The module probably
contains sophisticated code for ensuring that the tree remains balanced.
However, this complexity is not visible to users of the module. Users see a
relatively simple interface for invoking operations to insert, remove, and
fetch nodes in the tree. To invoke an insert operation, the caller need only
provide the key and value for the new node; the mechanisms for traversing
the tree and splitting nodes are not visible in the interface.
For the purposes of this book, a module is any unit of code that has an
interface and an implementation. Each class in an object-oriented
programming language is a module. Methods within a class, or functions in a
language that isn’t object-oriented, can also be thought of as modules: each of
these has an interface and an implementation, and modular design techniques
can be applied to them. Higher-level subsystems and services are also
modules; their interfaces may take different forms, such as kernel calls or
HTTP requests. Much of the discussion about modular design in this book
focuses on designing classes, but the techniques and concepts apply to other
kinds of modules as well.
The best modules are those whose interfaces are much simpler than their
implementations. Such modules have two advantages. First, a simple
interface minimizes the complexity that a module imposes on the rest of the
system. Second, if a module is modified in a way that does not change its
interface, then no other module will be affected by the modification. If a
module’s interface is much simpler than its implementation, there will be
many aspects of the module that can be changed without affecting other
modules.
4.2 What’s in an interface?
39. The interface to a module contains two kinds of information: formal and
informal. The formal parts of an interface are specified explicitly in the code,
and some of these can be checked for correctness by the programming
language. For example, the formal interface for a method is its signature,
which includes the names and types of its parameters, the type of its return
value, and information about exceptions thrown by the method. Most
programming languages ensure that each invocation of a method provides the
right number and types of arguments to match its signature. The formal
interface for a class consists of the signatures for all of its public methods,
plus the names and types of any public variables.
Each interface also includes informal elements. These are not specified in
a way that can be understood or enforced by the programming language. The
informal parts of an interface include its high-level behavior, such as the fact
that a function deletes the file named by one of its arguments. If there are
constraints on the usage of a class (perhaps one method must be called before
another), these are also part of the class’s interface. In general, if a developer
needs to know a particular piece of information in order to use a module, then
that information is part of the module’s interface. The informal aspects of an
interface can only be described using comments, and the programming
language cannot ensure that the description is complete or accurate1. For
most interfaces the informal aspects are larger and more complex than the
formal aspects.
One of the benefits of a clearly specified interface is that it indicates
exactly what developers need to know in order to use the associated module.
This helps to eliminate the “unknown unknowns” problem described in
Section 2.2.
4.3 Abstractions
The term abstraction is closely related to the idea of modular design. An
abstraction is a simplified view of an entity, which omits unimportant
details. Abstractions are useful because they make it easier for us to think
about and manipulate complex things.
In modular programming, each module provides an abstraction in form of
its interface. The interface presents a simplified view of the module’s
40. functionality; the details of the implementation are unimportant from the
standpoint of the module’s abstraction, so they are omitted from the interface.
In the definition of abstraction, the word “unimportant” is crucial. The
more unimportant details that are omitted from an abstraction, the better.
However, a detail can only be omitted from an abstraction if it is
unimportant. An abstraction can go wrong in two ways. First, it can include
details that are not really important; when this happens, it makes the
abstraction more complicated than necessary, which increases the cognitive
load on developers using the abstraction. The second error is when an
abstraction omits details that really are important. This results in obscurity:
developers looking only at the abstraction will not have all the information
they need to use the abstraction correctly. An abstraction that omits important
details is a false abstraction: it might appear simple, but in reality it isn’t. The
key to designing abstractions is to understand what is important, and to look
for designs that minimize the amount of information that is important.
As an example, consider a file system. The abstraction provided by a file
system omits many details, such as the mechanism for choosing which blocks
on a storage device to use for the data in a given file. These details are
unimportant to users of the file system (as long as the system provides
adequate performance). However, some of the details of a file system’s
implementation are important to users. Most file systems cache data in main
memory, and they may delay writing new data to the storage device in order
to improve performance. Some applications, such as databases, need to know
exactly when data is written through to storage, so they can ensure that data
will be preserved after system crashes. Thus, the rules for flushing data to
secondary storage must be visible in the file system’s interface.
We depend on abstractions to manage complexity not just in
programming, but pervasively in our everyday lives. A microwave oven
contains complex electronics to convert alternating current into microwave
radiation and distribute that radiation throughout the cooking cavity.
Fortunately, users see a much simpler abstraction, consisting of a few buttons
to control the timing and intensity of the microwaves. Cars provide a simple
abstraction that allows us to drive them without understanding the
mechanisms for electrical motors, battery power management, anti-lock
brakes, cruise control, and so on.
41. 4.4 Deep modules
The best modules are those that provide powerful functionality yet have
simple interfaces. I use the term deep to describe such modules. To visualize
the notion of depth, imagine that each module is represented by a rectangle,
as shown in Figure 4.1. The area of each rectangle is proportional to the
functionality implemented by the module. The top edge of a rectangle
represents the module’s interface; the length of that edge indicates the
complexity of the interface. The best modules are deep: they have a lot of
functionality hidden behind a simple interface. A deep module is a good
abstraction because only a small fraction of its internal complexity is visible
to its users.
Figure 4.1: Deep and shallow modules. The best modules are deep: they allow a lot of functionality to
be accessed through a simple interface. A shallow module is one with a relatively complex interface,
but not much functionality: it doesn’t hide much complexity.
Module depth is a way of thinking about cost versus benefit. The benefit
provided by a module is its functionality. The cost of a module (in terms of
system complexity) is its interface. A module’s interface represents the
complexity that the module imposes on the rest of the system: the smaller and
simpler the interface, the less complexity that it introduces. The best modules
are those with the greatest benefit and the least cost. Interfaces are good, but
more, or larger, interfaces are not necessarily better!
The mechanism for file I/O provided by the Unix operating system and its
descendants, such as Linux, is a beautiful example of a deep interface. There
are only five basic system calls for I/O, with simple signatures:
int open(const char* path, int flags, mode_t permissions);
ssize_t read(int fd, void* buffer, size_t count);
42. ssize_t write(int fd, const void* buffer, size_t count);
off_t lseek(int fd, off_t offset, int referencePosition);
int close(int fd);
The open system call takes a hierarchical file name such as /a/b/c and returns
an integer file descriptor, which is used to reference the open file. The other
arguments for open provide optional information such as whether the file is
being opened for reading or writing, whether a new file should be created if
there is no existing file, and access permissions for the file, if a new file is
created. The read and write system calls transfer information between buffer
areas in the application’s memory and the file; close ends the access to the
file. Most files are accessed sequentially, so that is the default; however,
random access can be achieved by invoking the lseek system call to change
the current access position.
A modern implementation of the Unix I/O interface requires hundreds of
thousands of lines of code, which address complex issues such as:
How are files represented on disk in order to allow efficient access?
How are directories stored, and how are hierarchical path names
processed to find the files they refer to?
How are permissions enforced, so that one user cannot modify or delete
another user’s files?
How are file accesses implemented? For example, how is functionality
divided between interrupt handlers and background code, and how do
these two elements communicate safely?
What scheduling policies are used when there are concurrent accesses to
multiple files?
How can recently accessed file data be cached in memory in order to
reduce the number of disk accesses?
How can a variety of different secondary storage devices, such as disks
and flash drives, be incorporated into a single file system?
All of these issues, and many more, are handled by the Unix file system
implementation; they are invisible to programmers who invoke the system
calls. Implementations of the Unix I/O interface have evolved radically over
the years, but the five basic kernel calls have not changed.
43. Another example of a deep module is the garbage collector in a language
such as Go or Java. This module has no interface at all; it works invisibly
behind the scenes to reclaim unused memory. Adding garbage collection to a
system actually shrinks its overall interface, since it eliminates the interface
for freeing objects. The implementation of a garbage collector is quite
complex, but that complexity is hidden from programmers using the
language.
Deep modules such as Unix I/O and garbage collectors provide powerful
abstractions because they are easy to use, yet they hide significant
implementation complexity.
4.5 Shallow modules
On the other hand, a shallow module is one whose interface is relatively
complex in comparison to the functionality that it provides. For example, a
class that implements linked lists is shallow. It doesn’t take much code to
manipulate a linked list (inserting or deleting an element takes only a few
lines), so the linked list abstraction doesn’t hide very many details. The
complexity of a linked list interface is nearly as great as the complexity of its
implementation. Shallow classes are sometimes unavoidable, but they don’t
provide help much in managing complexity.
Here is an extreme example of a shallow method, taken from a project in
a software design class:
private void addNullValueForAttribute(String attribute) {
data.put(attribute, null);
}
From the standpoint of managing complexity, this method makes things
worse, not better. The method offers no abstraction, since all of its
functionality is visible through its interface. For example, callers probably
need to know that the attribute will be stored in the data variable. It is no
simpler to think about the interface than to think about the full
implementation. If the method is documented properly, the documentation
will be longer than the method’s code. It even takes more keystrokes to
invoke the method than it would take for a caller to manipulate the data
44. variable directly. The method adds complexity (in the form of a new interface
for developers to learn) but provides no compensating benefit.
Red Flag: Shallow Module
A shallow module is one whose interface is complicated relative to the
functionality it provides. Shallow modules don’t help much in the battle
against complexity, because the benefit they provide (not having to learn
about how they work internally) is negated by the cost of learning and
using their interfaces. Small modules tend to be shallow.
4.6 Classitis
Unfortunately, the value of deep classes is not widely appreciated today. The
conventional wisdom in programming is that classes should be small, not
deep. Students are often taught that the most important thing in class design
is to break up larger classes into smaller ones. The same advice is often given
about methods: “Any method longer than N lines should be divided into
multiple methods” (N can be as low as 10). This approach results in large
numbers of shallow classes and methods, which add to overall system
complexity.
The extreme of the “classes should be small” approach is a syndrome I
call classitis, which stems from the mistaken view that “classes are good, so
more classes are better.” In systems suffering from classitis, developers are
encouraged to minimize the amount of functionality in each new class: if you
want more functionality, introduce more classes. Classitis may result in
classes that are individually simple, but it increases the complexity of the
overall system. Small classes don’t contribute much functionality, so there
have to be a lot of them, each with its own interface. These interfaces
accumulate to create tremendous complexity at the system level. Small
classes also result in a verbose programming style, due to the boilerplate
required for each class.
4.7 Examples: Java and Unix I/O
45. One of the most visible examples of classitis today is the Java class library.
The Java language doesn’t require lots of small classes, but a culture of
classitis seems to have taken root in the Java programming community. For
example, to open a file in order to read serialized objects from it, you must
create three different objects:
FileInputStream fileStream =
new FileInputStream(fileName);
BufferedInputStream bufferedStream =
new BufferedInputStream(fileStream);
ObjectInputStream objectStream =
new ObjectInputStream(bufferedStream);
A FileInputStream object provides only rudimentary I/O: it is not capable of
performing buffered I/O, nor can it read or write serialized objects. The
BufferedInputStream object adds buffering to a FileInputStream, and the
ObjectInputStream adds the ability to read and write serialized objects. The
first two objects in the code above, fileStream and bufferedStream, are never
used once the file has been opened; all future operations use objectStream.
It is particularly annoying (and error-prone) that buffering must be
requested explicitly by creating a separate BufferedInputStream object; if a
developer forgets to create this object, there will be no buffering and I/O will
be slow. Perhaps the Java developers would argue that not everyone wants to
use buffering for file I/O, so it shouldn’t be built into the base mechanism.
They might argue that it’s better to keep buffering separate, so people can
choose whether or not to use it. Providing choice is good, but interfaces
should be designed to make the common case as simple as possible (see
the formula on page 6). Almost every user of file I/O will want buffering, so
it should be provided by default. For those few situations where buffering is
not desirable, the library can provide a mechanism to disable it. Any
mechanism for disabling buffering should be cleanly separated in the
interface (for example, by providing a different constructor for
FileInputStream, or through a method that disables or replaces the buffering
mechanism), so that most developers do not even need to be aware of its
existence.
46. In contrast, the designers of the Unix system calls made the common case
simple. For example, they recognized that sequential I/O is most common, so
they made that the default behavior. Random access is still relatively easy to
do, using the lseek system call, but a developer doing only sequential access
need not be aware of that mechanism. If an interface has many features, but
most developers only need to be aware of a few of them, the effective
complexity of that interface is just the complexity of the commonly used
features.
4.8 Conclusion
By separating the interface of a module from its implementation, we can hide
the complexity of the implementation from the rest of the system. Users of a
module need only understand the abstraction provided by its interface. The
most important issue in designing classes and other modules is to make them
deep, so that they have simple interfaces for the common use cases, yet still
provide significant functionality. This maximizes the amount of complexity
that is concealed.
1There exist languages, mostly in the research community, where the overall behavior of a method
or function can be described formally using a specification language. The specification can be checked
automatically to ensure that it matches the implementation. An interesting question is whether such a
formal specification could replace the informal parts of an interface. My current opinion is that an
interface described in English is likely to be more intuitive and understandable for developers than one
written in a formal specification language.
47. Chapter 5
Information Hiding (and Leakage)
Chapter 4 argued that modules should be deep. This chapter, and the next few
that follow, discuss techniques for creating deep modules.
5.1 Information hiding
The most important technique for achieving deep modules is information
hiding. This technique was first described by David Parnas1. The basic idea is
that each module should encapsulate a few pieces of knowledge, which
represent design decisions. The knowledge is embedded in the module’s
implementation but does not appear in its interface, so it is not visible to other
modules.
The information hidden within a module usually consists of details about
how to implement some mechanism. Here are some examples of information
that might be hidden within a module:
How to store information in a B-tree, and how to access it efficiently.
How to identify the physical disk block corresponding to each logical
block within a file.
How to implement the TCP network protocol.
How to schedule threads on a multi-core processor.
How to parse JSON documents.
The hidden information includes data structures and algorithms related to the
mechanism. It can also include lower-level details such as the size of a page,
and it can include higher-level concepts that are more abstract, such as an
assumption that most files are small.
Information hiding reduces complexity in two ways. First, it simplifies
the interface to a module. The interface reflects a simpler, more abstract view
of the module’s functionality and hides the details; this reduces the cognitive
48. load on developers who use the module. For instance, a developer using a B-
tree class need not worry about the ideal fanout for nodes in the tree or how
to keep the tree balanced. Second, information hiding makes it easier to
evolve the system. If a piece of information is hidden, there are no
dependencies on that information outside the module containing the
information, so a design change related to that information will affect only
the one module. For example, if the TCP protocol changes (to introduce a
new mechanism for congestion control, for instance), the protocol’s
implementation will have to be modified, but no changes should be needed in
higher-level code that uses TCP to send and receive data.
When designing a new module, you should think carefully about what
information can be hidden in that module. If you can hide more information,
you should also be able to simplify the module’s interface, and this makes the
module deeper.
Note: hiding variables and methods in a class by declaring them private
isn’t the same thing as information hiding. Private elements can help with
information hiding, since they make it impossible for the items to be accessed
directly from outside the class. However, information about the private items
can still be exposed through public methods such as getter and setter
methods. When this happens the nature and usage of the variables are just as
exposed as if the variables were public.
The best form of information hiding is when information is totally hidden
within a module, so that it is irrelevant and invisible to users of the module.
However, partial information hiding also has value. For example, if a
particular feature or piece of information is only needed by a few of a class’s
users, and it is accessed through separate methods so that it isn’t visible in the
most common use cases, then that information is mostly hidden. Such
information will create fewer dependencies than information that is visible to
every user of the class.
5.2 Information leakage
The opposite of information hiding is information leakage. Information
leakage occurs when a design decision is reflected in multiple modules. This
creates a dependency between the modules: any change to that design
49. decision will require changes to all of the involved modules. If a piece of
information is reflected in the interface for a module, then by definition it has
been leaked; thus, simpler interfaces tend to correlate with better information
hiding. However, information can be leaked even if it doesn’t appear in a
module’s interface. Suppose two classes both have knowledge of a particular
file format (perhaps one class reads files in that format and the other class
writes them). Even if neither class exposes that information in its interface,
they both depend on the file format: if the format changes, both classes will
need to be modified. Back-door leakage like this is more pernicious than
leakage through an interface, because it isn’t obvious.
Information leakage is one of the most important red flags in software
design. One of the best skills you can learn as a software designer is a high
level of sensitivity to information leakage. If you encounter information
leakage between classes, ask yourself “How can I reorganize these classes so
that this particular piece of knowledge only affects a single class?” If the
affected classes are relatively small and closely tied to the leaked
information, it may make sense to merge them into a single class. Another
possible approach is to pull the information out of all of the affected classes
and create a new class that encapsulates just that information. However, this
approach will be effective only if you can find a simple interface that
abstracts away from the details; if the new class exposes most of the
knowledge through its interface, then it won’t provide much value (you’ve
simply replaced back-door leakage with leakage through an interface).
Red Flag: Information Leakage
Information leakage occurs when the same knowledge is used in multiple
places, such as two different classes that both understand the format of a
particular type of file.
5.3 Temporal decomposition
One common cause of information leakage is a design style I call temporal
decomposition. In temporal decomposition, the structure of a system
50. corresponds to the time order in which operations will occur. Consider an
application that reads a file in a particular format, modifies the contents of the
file, and then writes the file out again. With temporal decomposition, this
application might be broken into three classes: one to read the file, another to
perform the modifications, and a third to write out the new version. Both the
file reading and file writing steps have knowledge about the file format,
which results in information leakage. The solution is to combine the core
mechanisms for reading and writing files into a single class. This class will
get used during both the reading and writing phases of the application. It’s
easy to fall into the trap of temporal decomposition, because the order in
which operations must occur is often on your mind when you code. However,
most design decisions manifest themselves at several different times over the
life of the application; as a result, temporal decomposition often results in
information leakage.
Order usually does matter, so it will be reflected somewhere in the
application. However, it shouldn’t be reflected in the module structure unless
that structure is consistent with information hiding (perhaps the different
stages use totally different information). When designing modules, focus on
the knowledge that’s needed to perform each task, not the order in which
tasks occur.
Red Flag: Temporal Decomposition
In temporal decomposition, execution order is reflected in the code
structure: operations that happen at different times are in different methods
or classes. If the same knowledge is used at different points in execution, it
gets encoded in multiple places, resulting in information leakage.
5.4 Example: HTTP server
To illustrate the issues in information hiding, let’s consider the design
decisions made by students implementing the HTTP protocol in a software
design course. It’s useful to see both the things they did well and they areas
where they had problems.
51. HTTP is a mechanism used by Web browsers to communicate with Web
servers. When a user clicks on a link in a Web browser or submits a form, the
browser uses HTTP to send a request over the network to a Web server. Once
the server has processed the request, it sends a response back to the browser;
the response normally contains a new Web page to display. The HTTP
protocol specifies the format of requests and responses, both of which are
represented textually. Figure 5.1 shows a sample HTTP request describing a
form submission. The students in the course were asked to implement one or
more classes to make it easy for Web servers to receive incoming HTTP
requests and send responses.
Figure 5.1: A POST request in the HTTP protocol consists of text sent over a TCP socket. Each
request contains an initial line, a collection of headers terminated by an empty line, and an optional
body. The initial line contains the request type (POST is used for submitting form data), a URL
indicating an operation (/comments/create) and optional parameters (photo_id has the value 246), and
the HTTP protocol version used by the sender. Each header line consists of a name such as Content-
Length followed by its value. For this request, the body contains additional parameters (comment and
priority).
5.5 Example: too many classes
The most common mistake made by students was to divide their code into a
large number of shallow classes, which led to information leakage between
the classes. One team used two different classes for receiving HTTP requests;
the first class read the request from the network connection into a string, and
the second class parsed the string. This is an example of a temporal
decomposition (“first we read the request, then we parse it”). Information
leakage occurred because an HTTP request can’t be read without parsing
much of the message; for example, the Content-Length header specifies the
length of the request body, so the headers must be parsed in order to compute
the total request length. As a result, both classes needed to understand most
52. of the structure of HTTP requests, and parsing code was duplicated in both
classes. This approach also created extra complexity for callers, who had to
invoke two methods in different classes, in a particular order, to receive a
request.
Because the classes shared so much information, it would have been
better to merge them into a single class that handles both request reading and
parsing. This provides better information hiding, since it isolates all
knowledge of the request format in one class, and it also provides a simpler
interface to callers (just one method to invoke).
This example illustrates a general theme in software design: information
hiding can often be improved by making a class slightly larger. One
reason for doing this is to bring together all of the code related to a particular
capability (such as parsing an HTTP request), so that the resulting class
contains everything related to that capability. A second reason for increasing
the size of a class is to raise the level of the interface; for example, rather than
having separate methods for each of three steps of a computation, have a
single method that performs the entire computation. This can result in a
simpler interface. Both of these benefits apply in the example of the previous
paragraph: combining the classes brings together all of the code related to
parsing an HTTP request, and it replaces two externally-visible methods with
one. The combined class is deeper than the original classes.
Of course, it is possible to take the notion of larger classes too far (such
as a single class for the entire application). Chapter 9 will discuss conditions
under which it makes sense to separate code into multiple smaller classes.
5.6 Example: HTTP parameter handling
After an HTTP request has been received by a server, the server needs to
access some of the information from the request. The code that handles the
request in Figure 5.1 might need to know the value of the photo_id
parameter. Parameters can be specified in the first line of the request
(photo_id in Figure 5.1) or, sometimes, in the body (comment and priority in
Figure 5.1). Each parameter has a name and a value. The values of
parameters use a special encoding called URL encoding; for example, in the
value for comment in Figure 5.1, “+” is used to represent a space character,
53. and “%21” is used instead of “!”. In order to process a request, the server will
need the values for some of the parameters, and it will want them in
unencoded form.
Most of the student projects made two good choices with respect to
parameter handling. First, they recognized that server applications don’t care
whether a parameter is specified in the header line or the body of the request,
so they hid this distinction from callers and merged the parameters from both
locations together. Second, they hid knowledge of URL encoding: the HTTP
parser decodes parameter values before returning them to the Web server, so
that the value of the comment parameter in Figure 5.1 will be returned as
“What a cute baby!”, not “What+a+cute+baby%21”). In both of these cases,
information hiding resulted in simpler APIs for the code using the HTTP
module.
However, most of the students used an interface for returning parameters
that was too shallow, and this resulted in lost opportunities for information
hiding. Most projects used an object of type HTTPRequest to hold the parsed
HTTP request, and the HTTPRequest class had a single method like the
following one to return parameters:
public Map<String, String> getParams() {
return this.params;
}
Rather than returning a single parameter, the method returns a reference to
the Map used internally to store all of the parameters. This method is shallow,
and it exposes the internal representation used by the HTTPRequest class to
store parameters. Any change to that representation will result in a change to
the interface, which will require modifications to all callers. When
implementations are modified, the changes often involve changes in the
representation of key data structures (to improve performance, for example).
Thus, it’s important to avoid exposing internal data structures as much as
possible. This approach also makes more work for callers: a caller must first
invoke getParams, then it must call another method to retrieve a specific
parameter from the Map. Finally, callers must realize that they should not
modify the Map returned by getParams, since that will affect the internal state
of the HTTPRequest.
54. Here is a better interface for retrieving parameter values:
public String getParameter(String name) { ... }
public int getIntParameter(String name) { ... }
getParameter returns a parameter value as a string. It provides a slightly
deeper interface than getParams above; more importantly, it hides the internal
representation of parameters. getIntParameter converts the value of a
parameter from its string form in the HTTP request to an integer (e.g., the
photo_id parameter in Figure 5.1). This saves the caller from having to
request string-to-integer conversion separately, and hides that mechanism
from the caller. Additional methods for other data types, such as
getDoubleParameter, could be defined if needed. (All of these methods will
throw exceptions if the desired parameter doesn’t exist, or if it can’t be
converted to the requested type; the exception declarations have been omitted
in the code above).
5.7 Example: defaults in HTTP responses
The HTTP projects also had to provide support for generating HTTP
responses. The most common mistake students made in this area was
inadequate defaults. Each HTTP response must specify an HTTP protocol
version; one team required callers to specify this version explicitly when
creating a response object. However, the response version must correspond to
that in the request object, and the request must already be passed as an
argument when sending the response (it indicates where to send the
response). Thus, it makes more sense for the HTTP classes to provide the
response version automatically. The caller is unlikely to know what version
to specify, and if the caller does specify a value, it probably results in
information leakage between the HTTP library and the caller. HTTP
responses also include a Date header specifying the time when the response
was sent; the HTTP library should provide a sensible default for this as well.
Defaults illustrate the principle that interfaces should be designed to make
the common case as simple as possible. They are also an example of partial
information hiding: in the normal case, the caller need not be aware of the
existence of the defaulted item. In the rare cases where a caller needs to
60. This ebook is for the use of anyone anywhere in the United
States and most other parts of the world at no cost and with
almost no restrictions whatsoever. You may copy it, give it away
or re-use it under the terms of the Project Gutenberg License
included with this ebook or online at www.gutenberg.org. If you
are not located in the United States, you will have to check the
laws of the country where you are located before using this
eBook.
Title: The Legal Position of the Clergy
Author: Philip Vernon Smith
Release date: August 28, 2012 [eBook #40606]
Most recently updated: October 23, 2024
Language: English
Credits: Produced by David Clarke, Ian Swainson and the Online
Distributed Proofreading Team at http://www.pgdp.net
*** START OF THE PROJECT GUTENBERG EBOOK THE LEGAL
POSITION OF THE CLERGY ***
61. Handbooks for the Clergy
EDITED BY
ARTHUR W. ROBINSON, B.D.
VICAR OF ALLHALLOWS BARKING
BY THE TOWER
THE LEGAL POSITION OF
THE CLERGY
62. THE LEGAL POSITION OF
THE CLERGY
BY
P. V. SMITH, LL.D.
CHANCELLOR OF THE DIOCESE OF MANCHESTER
AUTHOR OF "THE LAW OF CHURCHWARDENS AND SIDESMEN
IN THE TWENTIETH CENTURY," ETC.
LONGMANS, GREEN, AND CO.
39 PATERNOSTER ROW, LONDON
NEW YORK AND BOMBAY
1905
64. PREFACE
In the following pages an endeavour has been made to give a
succinct sketch of the legal position of the parish clergy of the
Church of England in respect both of spiritualities and of
temporalities. The book, being intended for their use, does not touch
upon the subject of ordination by which they acquired the status of
deacons or priests. Nor does it deal with the episcopate or the non-
parochial clergy, except so far as these subjects are connected with
the parochial system.
Like all other human arrangements, our English Church law is, of
course, far from being ideally perfect. It may be safely affirmed that
there has never been either a Church or a State in which the law has
actually been what it ideally ought to have been. It is important to
recognise the difference between the two positions; for there has
sometimes been a disposition on the part of individuals to confuse
them, and to treat what they consider to be the ideal law, as if it
were the actual law, and as if, as such, it demanded their loyal
obedience. Such an attitude, whether in ecclesiastical or civil
matters, is anarchical in its tendency; for it sets up private judgment
instead of the constituted authority as the criterion of what ought or
ought not to be done. It can only be justified where the actual law is
absolutely inconsistent with the fundamental principles of morality or
of Christian truth. The object of the present treatise is to state
succinctly what the law is,—not what it ought to be; and no opinion
is expressed or suggestion offered as to points in which amendment
would be proper or expedient.
Within the limited compass of the book it is obviously impossible to
enter into details; and the reader who desires information as to
these will find them in the authorities to which reference is made. It
must also be borne in mind that the general law on the subject of
65. P. V. SMITH.
buildings, property, and pecuniary rights is, in various places,
modified by special local enactments or customs. These can only be
ascertained on the spot, or by consulting the Acts of Parliament in
which they are embodied or recorded.
One other word of caution is desirable. In explaining the legal
position of the parochial clergy, it is, of course, necessary to indicate
the exact limits of their rights. If they venture beyond these limits,
they are manifestly in the wrong. But no community, either
ecclesiastical or civil, could maintain its well-being, or even its
coherence, if every individual were on all occasions to take
advantage of the full tether of his legal rights. It will frequently be
wise and proper for the clergy, in their relations with their
ecclesiastical superiors or with the lay officials and other laity of the
parish, not to adopt the most uncompromising attitude which the
letter of the law permits to them. The dictates of love and of
Christian forbearance, and of consideration for the claims of others,
as well as of expediency, will not warrant the infringement by an
individual of the ordinances of either the Church or the State. But
they will more than justify him in refraining from taking up a position
of defiance which these ordinances may strictly entitle him to
assume.
Easter, 1905.
66. pages xxi-xiv
pages 1-24
CONTENTS
List of Abbreviations
CHAPTER I
General Legal Position
1.Spiritual, ecclesiastical, and civil status of the clergy. 2. Sources of
Church law. 3. Written and unwritten law—Foreign Canon law—Pre-
Reformation Canons—Acts of Parliament—Canons of 1603—Canons
of 1640—Other canons. 4. Decisions of Church courts—Distinction
between judicial and legislative action. 5. Legal status of the ancient
Parish—Rector or Parson—Patronage or Advowson—Vicar—Perpetual
curate. 6. Dissolution of the Monasteries—Impropriate rectories—
New churches and ecclesiastical parishes—Assistant parochial clergy
—Titular vicars—Incumbent—Curate. 7. Minister in charge—Lecturer.
8. Status of clergy ordained elsewhere than in England or Ireland, or
ordained for service in the colonies or foreign countries—Scottish
clergy. 9. Benefices—Beneficed and unbeneficed clergy. 10. Bishops,
their relation to the clergy—Suffragan bishops—Chancellors. 11.
Archdeacons. 12. Rural Deans. 13. Judicial procedure—Church
Discipline Act, 1840—Public Worship Regulation Act, 1874—Clergy
Discipline Act, 1892. 14. Abstinence of Clergy from secular pursuits.
15. Civil exemptions—Municipal and Parliamentary qualifications and
disqualifications. 16. Restrictions as to labour, business, and trade—
Lawful exceptions—Penalties for unlawful trading. 17. Protection in
performance of religious rites—Act against brawling. 18. Indelibility
of Orders—Relinquishment of clerical status
67. CHAPTER II
Beneficed Clergy
1. Admission by bishop on presentation of patron—Lapse to bishop,
archbishop, or Crown. 2. Transfers of advowsons or rights of
presentation—Next presentations—Power of patron to present
himself—Restrictions under Benefices Act, 1898. 3. Qualification for
admission—Grounds for refusal by bishop—Testimony as to fitness.
4. Procedure in case of refusal by bishop. 5. Publication of notice of
intended admission. 6. Mode of admission—Institution—Licence—
Collation—Declarations of assent and against simony—Oaths of
allegiance and canonical obedience—Reading of Thirty-nine Articles.
7. Effect of admission—Induction. 8. Fees on admission. 9. Cure of
Souls—Duties laid down in Ordination Service—Residence—Divine
service—Marriages—Burials—Private ministrations. 10. Exclusive
right of administration—Superior right of bishop—Modern comity as
between town parishes. 11. Private ministrations—Service in
unconsecrated buildings—Meetings for worship. 12. Private chapels
—Chapels of institutions—Unconsecrated proprietary chapels. 13.
Formation of new parishes—Approval or otherwise of incumbent. 14.
Holding of two benefices. 15. Neglect of duty—Commission of
inquiry—Procedure on adverse report of Commission. 16. Residence
on benefice—Forfeitures for non-residence—Bishop's licence of non-
residence—Grounds for licence. 17. Monition, sequestration, and
avoidance of benefice for non-residence. 18. Performance of duties
where incumbent is non-resident. 19. Restrictions on interfering with
duties during period of non-residence. 20. Reckoning of time as to
residence. 21. Vacation of benefice by death, resignation, admission
to other preferment, or deprivation. 22. Resignation; unconditional
except upon an exchange—Engagement to resign illegal except
under Clergy Resignation Bonds Act, 1828—Corrupt resignations and
exchanges—Pensions under Incumbents Resignation Acts. 23.
Vacation of benefice on admission to other preferment. 24.
68. pages 25-54
pages 55-64
Deprivation ipso facto—Declaration of vacancy by bishop on
conviction of incumbent in certain cases—Sentences of deprivation
under Acts of 1840 and 1892
CHAPTER III
Unbeneficed Clergy
1. Classes of unbeneficed clergy—Bishop's licence—Declaration of
assent—Examination and admission by bishop—Discretion of bishop
—Revocation of licence. 2. Curates or ministers in charge—(a) On
vacancy of benefice—(b) On sequestration of benefice for
incumbent's bankruptcy or debt—(c) On incumbent's non-residence
—(d) On incumbent's neglect of duties—(e) On formation of Peel
district. 3. Assistant curates—Stipend—Notice to quit or relinquish
curacy—Discretion of incumbent as to employment—Appointment
where duties are inadequately performed; or where circumstances of
parish require it. 4. Performance of duty by other clergy—Discretion
of incumbent—Licence of bishop—Production of licence and entry of
names of preachers in a book. 5. Lecturers and preachers—
Performance of other ministerial duties
CHAPTER IV
Laity of the Parish
1. Relations between incumbent and lay officials. 2. The vestry—
Constitution, meetings, and voting in ancient parishes, and in new
parishes—Vestries Act, 1818—Present functions—Select vestries. 3.
Churchwardens—Election in ancient and new parishes—Admission.
4. Parson's or vicar's and people's wardens—Duties: (a) Care of
fabric and ornaments of the church and of the churchyard—(b)
Seating of parishioners—(c) Provision of requisites for service—(d)
69. pages 65-79
Maintenance of order in church and churchyard—(e) Collection and
concurrence in disposal of offertory money—(f) Charge of church
and benefice during vacancy, if appointed sequestrators—
Restrictions on powers. 5. Sidesmen. 6. Church trustees. 7. Parish
clerk—Appointment and removal. 8. Sexton. 9. Beadle. 10. Organist
and choristers. 11. Officiating of lay readers and other laymen. 12.
Other lay work—Visiting of poor and sick—Sunday schools—Church
elementary schools. 13. Parochial church councils
CHAPTER V
Divine Service
1. Duty of clergy as to uniformity of service—Divergence by lawful
authority—Liberty under Act of 1872. 2. Morning and Evening Prayer
—Litany—Bishop 0.5em;">may order two full services, and a third
service, with sermon. 3. Notices during Divine service—Notices on
church door—Banns. 4. Offertory—Other collections in a church or
chapel—Duty of incumbent as to money entrusted to him. 5.
Questions as to the legality of various church ornaments, vestments,
and ceremonies—Legal decisions as to (A) Stone Holy Table—Crucifix
—Cross—Candlesticks—Flower-vases—Pictures—Sculptures—
Credence table—Second Holy Table—Chancel gates—Baldacchino—
Voice of parishioners in vestry—(B) Attire of clergy at Holy
Communion—Surplice—Hood—Albe—Vestment or chasuble—Tunicle
—Stole—Chaplain's scarf—Biretta—Black gown—(C) Incense—
Processions with lighted candles—Lighted candles at Holy
Communion—Mixed chalice—Wafers—Agnus Dei and other hymns—
Position of minister—Genuflexions—Elevation—Sign of the Cross—
Ablutions—Reservation. 6. Baptism not to be refused—Time for the
ceremony—Private baptism in urgent cases—Godparents—Reception
in church after private baptism—Conditional baptism—Immersion or
affusion—Notice to bishop in cases of adult baptism—Deacon may
baptize—Lay baptism. 7. Times for and notice of Holy Communion—
70. pages 80-99
Communion not to be unlawfully refused—Who are to be repelled
from it—Procedure in such cases—Jenkins v. Cook—Persons coming
from other parishes—Persons attending dissenting places of worship
—Persons baptized in another communion and not confirmed. 8.
Sermons and homilies—Provisions of rubrics, Canons, and Acts of
Parliament. 9. Catechising. 10. Churching of women
CHAPTER VI
Marriage
1. Duty of minister to solemnise marriage between persons legally
competent—Unlawful solemnisation, when a felony—Marriage, when
void. 2. Original places for banns and marriages—Churches of new
parishes—Licences for banns and marriages in chapels—Parishes
having no regular services in parish church—Where parish church is
being rebuilt or repaired—No reconsecration necessary where church
is rebuilt or enlarged and position of Holy Table altered. 3. Persons
legally competent to intermarry—Religion or absence of religion of
the parties no ground for refusal to solemnise marriage. 4. Minimum
age—Consent of parents or guardians in case of unions—Marriage
without consent, in absence of notice—Marriage below lawful age. 5.
Marriage of lunatic or non compos, void. 6. Absence, unheard of, for
seven years—Relief from punishment for bigamy—Invalidity of
remarriage. 7 Divorce abroad—Divorce in England under Act of 1857
—Remarriage of divorced persons. 8. Marriage of foreigners—
Requirements of laws of foreign States—Precautions to be observed.
9. Prohibited degrees of kindred and affinity. 10. Publication of
banns—Time and form—Seven days' notice—Publication and
marriage without notice and due inquiry—Publication where parties
dwell in different parishes or districts—Where one dwells in Scotland,
or in Ireland—What constitutes dwelling—Correct names to be
published—Status need not be published—Publication to be from
book and signed—Forbidding of banns. 11. Marriage, with consent of
71. pages 100-120
minister, on registrar's certificate—Not permitted on registrar's
licence. 12. Marriage on licence of bishop or Archbishop of
Canterbury—Grant of bishop's licence—Previous affidavit before
surrogate—Duty of minister on production of licence—Names in
licence—Grant of licence a favour and not a right. 13. Marriage,
where and when to be solemnised—Priest or deacon may marry—
Penalty for solemnising marriage at improper place or time. 14.
Reading of service after marriage at a registry office—Second
solemnisation of marriage. 15. Fees for banns, certificate of banns,
and marriage. 16. Marriage register books—Certificate of marriage.
17. Presumption of marriage of persons coming to Holy Communion
—Proof of no marriage—Validity of marriage governed by law of
place of solemnisation—Capacity to contract marriage governed by
law of domicile—-Marriage between British subjects in a foreign
country or on board ship
CHAPTER VII
Burial
1. Right of burial by clergyman of the parish where death occurs—
Bells to be rung—Burial in case of death in another parish—Relief in
case interment is refused—No right to particular hour or spot of
burial—Incumbent or churchwardens cannot sell or grant grave-
spaces in perpetuity or brick graves—Reservation of exclusive right
of burial on grant of addition to churchyard—Faculty for exclusive
grave space in other cases—Burial of non-parishioners not dying
within the parish. 2. Burial of bodies cast up by the sea or tidal or
navigable water. 3. Burial of person dying unbaptized or
excommunicate and of felo de se—Burial of child of dissenter or
person who has received lay baptism—Interment cannot be required
without convenient warning. 4. Bringing of corpse into church and
burial under church. 5. Fees—Prepayment not enforceable—
Customary amount—On burial of non-parishioners—Tables of fees—
72. pages 121-134
pages 135-140
Special fees for brick graves, iron coffins, and other extras—Fees and
rights of burial where new ecclesiastical parish has its own burial
ground. 6. Use of Burial Service in unconsecrated ground—Use of
special form—Permission of burial without Church rites and with or
without some other service on notice under Act of 1880—Day and
time for burial—Fee. 7. Delivery of registrar's certificate of death or
order of coroner at funeral. 8. Fees on interments in cemeteries
under Cemeteries Clauses Act, 1847. 9. Burial Acts—Consecrated
and unconsecrated parts of burial grounds—Chapels—Fees of
incumbents, clerks, and sextons—Sale of rights to vaults and
monuments—Burial Act, 1900—Tables of fees—Restrictions on future
fees to incumbents, churchwardens, and sextons—Commutation of
fees. 10. Cremation—Burial of cremated remains. 11. Faculty for
removal of body from one unconsecrated place of interment to
another—Licence of Home Secretary for removal in other cases
CHAPTER VIII
Private Ministrations
1. Visitation and Communion of the Sick—-Canon 67—Order for the
Visitation—Confession and absolution of the sick—Regulations as to
Communion. 2. Preparation for Confirmation. 3. Spiritual advice and
comfort—Confession—Absolution. 4. Ordinary visitation and
intercourse
CHAPTER IX
Temporalities
1. Possessions and revenues of benefices of ancient parishes and
new ecclesiastical parishes. 2. Incumbent a corporation sole—
73. Restrictions on his acquisition and holding of landed property—
Licence in mortmain—Mortmain and Charitable Uses Acts—School
Sites Acts—Inability to hold as a corporation land upon trusts. 3.
Freehold of church and churchyard of ancient parish in rector—
Chancel repairable by rector—Enforcement of repairs—Possession
and custody of church in incumbent and churchwardens—Right of
incumbent to keys and control of organ and bells—Canon 88—Right
of rector to profits of soil of churchyard—Felling of trees in
churchyard—Freehold of church and churchyard of new parish in
incumbent—Exemption from rates and contributions to making new
streets—Removal of part of church as a dangerous structure. 4.
Rights of bishop and parishioners in church and churchyard—Power
of incumbent as to ordinary tombstones and inscriptions in
churchyard—Glass shades for wreaths—Appeal to consistory and
higher courts—Faculties for monuments in church and other
alterations and additions in church and churchyard—Application by
incumbent and churchwardens after resolution of vestry—Consent of
rector to alteration in chancel—Faculty for vault or space for
exclusive burial—Removal of earth or bones from churchyard, or
other desecration—Faculty for diversion of ancient footpath through
churchyard, and for throwing part of churchyard into highway—
Restoration of wall wilfully thrown down—Easement of light and air
over churchyard—Laying out of closed churchyard as a garden and
removal of gravestones—Restrictions as to building on closed or
disused burial-grounds. 5. Glebe, rectorial and vicarial—Exemption
from tithe—Waste—Cultivation of glebe—Cutting down of trees—
Opening and working of mines and quarries and gravel pits. 6.
Statutory facilities for parsonage houses and other buildings and
repair of chancels—Gilbert Acts—Loans by, and mortgages to Queen
Anne's Bounty—Purchase of land—Building and improving of farm
buildings and labourers' dwellings—Gifts and bequests of parsonage
houses and glebe—Sale and exchange of parsonage houses and
glebe. 7. Letting of parsonage house where incumbent has licence to
reside elsewhere. 8. Farming or letting of glebe—Agricultural,
building, and mining leases. 9. Repair of parsonage house and glebe
buildings—Ecclesiastical Dilapidations Act, 1871. 10. Diocesan
74. surveyors—Proceedings (a) on vacancies in benefices and (b) in
other cases—Exemption from liability for five years after certificate of
surveyor. 11. (a) Inspection and report by surveyor on a vacancy—
Objections to report—Order of bishop—Debt from late incumbent, or
his estate, to new incumbent—Payment of amount recovered to
Queen Anne's Bounty—Loan of amount not recovered—Balance to
be paid by new incumbent—Dilapidation Account—Liability where a
vacancy occurs between inspection of buildings and certificate of
completion of works. 12. (b) Inspection of buildings on complaint of
archdeacon, rural dean, or patron, or on request of incumbent—
Inspection after and during sequestration of benefice—Report—
Objections—Decision of bishop—Loans—Dilapidation Account—
Execution of repairs—-Charge of cost on income in case of benefice
under sequestration—Vacancy before execution of works—Liability of
sequestrator spending excessive amount on repairs. 13. Payment of
money out of dilapidation account on certificate of surveyor—Liability
and duty of incumbent—Rebuilding or remodelling instead of
repairing. 14. Insurance of parsonage house, glebe buildings, and
chancel against fire—Production of receipts for premiums at
visitations—Payment and application of insurance money and
reinstatement of buildings in the event of fire—Sequestration of
benefice to raise any requisite balance. 15. Exemption from Act of
1871 of buildings let on lease under which tenant is liable—
Inspection by surveyor. 16. Faculty or consent of bishop and patron
to alterations in buildings—Liability of incumbent for alterations not
so sanctioned—Power of bishop to authorise removal of unnecessary
buildings—Movable sheds or garden frames. 17. Vacation of benefice
—Cesser of rights of former incumbent—Right of widow to two
months' residence in parsonage house—Inspection of premises
pending settlement of dilapidations—Emblements—Apportionment of
rents, tithe rentcharge, and other income. 18. Tithe commutation
rentcharge under Act of 1836 and amending Acts—Assessment in
lieu of great or rectorial tithes and small or vicarial tithes—
Extraordinary tithe rentcharge in respect of hop and other gardens
and orchards—Act of 1886—Assessment of tithe rentcharge with
regard to prices of wheat, barley, and oats—Variation according to
75. pages 141-168
pages 169-174
septennial average prices. 19. Payment of tithe rentcharge and
recovery by distress on appointment of receiver—Recovery from
railway company. 20. Dues (i.) ordinary and (ii.) special—Variety by
law and custom—Payments on the customary four offering days—
Easter offerings—Rights of vicar of new ecclesiastical parish. 21.
Mortuaries. 22. Dues for special services or concessions. 23. Pew
rents under special or general Acts of Parliament—Under Church
Building and New Parishes Acts—Recovery of pew rents. 24. First
fruits and tenths—Exemption of small benefices—Number of
benefices remaining liable. 25. Income or property tax—On
parsonage house, glebe lands, and tithe rentcharge—On landed
property in occupation of incumbent—On other stipend, fees,
perquisites, and profits—Legal deductions—Test as to whether
receipts are or are not liable to tax—Voluntary contributions to
minister in respect of his office—Grants from Curates' Augmentation
Fund—Grants from Queen Victoria Clergy Fund
Index
76. LIST OF ABBREVIATIONS
A. C.
Law Reports (House of Lords and Privy Council)
1891 onwards.
A. & E. Adolphus & Ellis's Reports (King's Bench)1834-41.
Add. Addam's Reports (Ecclesiastical) 1822-6.
Ambl. Ambler's Reports (Chancery) 1737-83.
App. Ca.
Law Reports (House of Lords and Privy Council)
1875-90.
Atk. Atkyn's Reports (Chancery) 1735-54.
Ayl. Par. Ayliffe's Parergon Juris Canonici Anglicani, 1726.
B. & C.
Barnewall & Cresswell's Reports (King's Bench)
1822-30.
B. & Ad.
Barnewall & Adolphus' Reports (King's Bench) 1830-
34.
B. & Ald.
Barnewall & Alderson's Reports (King's Bench)
1818-22.
B. & Sm. Best & Smith's Reports (Queen's Bench) 1861-70.
Beav. Beavan's Reports (Chancery) 1838-66.
Bl. Comm. Blackstone's Commentaries on the Laws of England.
Burn. Burn's Ecclesiastical Law, 4 vols.
Canon.
One of the Constitutions and Canons Ecclesiastical
agreed upon in the Canterbury convocation begun
in 1603.
C. B. Common Bench Reports, 1845-56.
C. B. N. S. Common Bench Reports, New Series, 1856-65.
C. & K.
Carrington & Kirwan's Reports (Nisi Prius) 1843-
1853.
C. P. D. Law Reports (Common Pleas Division) 1875-80.
Ch. Law Reports, Chancery Division, 1891 onwards.
77. Ch. D. Law Reports, Chancery Division, 1875-90.
Cl. & F. Clark & Finnelly's Reports (House of Lords) 1831-46.
Clarke, Proxis
Francis Clarke's Proxis in Curiis Ecclesiasticis, 1666,
1684.
Co. Inst.
Coke's Institutes of the Laws of England, Second
Part.
Co. Litt.
Coke upon Littleton (with notes by Hargrave and
Butler).
Co. Rep. Coke's Reports, 1598-1616.
Com. Dig. Comyn's Digest.
Cowp. Cowper's Reports (King's Bench) 1774-78.
Cripps.
Cripps's Law relating to the Church and Clergy, 6th
ed., 1886.
Cro. Jac. Croke's Reports (temp. James I.) 1603-1625.
Curt. Curteis's Ecclesiastical Reports, 1834-44.
Degge. Sir Simon Degge's Parson's Counsellor.
Dr. & Sm. Drewry & Smale's Reports (Chancery) 1859-65.
E. & B. Ellis & Blackburn's Reports (Queen's Bench) 1854-8.
Eccl. & Adm. Ecclesiastical & Admiralty Reports (Spinks) 1853-5.
El. & El. Ellis & Ellis' Reports (Queen's Bench) 1858-61.
Ex. Exchequer Reports, 1847-56.
Ex. D. Law Reports (Exchequer Division) 1875-1880.
Geary
Geary's Law of Marriage and Family Relations (A. &
C. Black, 1892).
Gibs. Cod. Gibson's Codex Juris Ecclesiastici Anglicani.
Hag. Cons. Haggard's Consistory Reports, 1729-1821.
Hag. Eccl. Haggard's Ecclesiastical Reports, 1827-1832.
H. & C.
Hurlstone & Coltman's Reports (Exchequer) 1862-
66.
H. L. C. House of Lords Cases, 1847-66.
Hob. Hobart's Reports, 1611-20.
Ir. Ch. Rep.
App.
Irish Chancery Reports (Appendix).
78. J. & H. Johnson & Hemming's Reports (Chancery) 1859-62.
J. P. Justice of the Peace, 1837 onwards.
Johns.
John Johnson's Clergyman's Vade Mecum, 6th ed.,
1731.
Jur. Jurist (Reports) 1837-54.
Jur. N. S. Jurist, New Series (Reports) 1855-66.
K. B. Law Reports (King's Bench) 1901 onwards.
L. J. (Ch., C.P.,
Ex. Q.B.)
Law Journal 1823-31; New Series 1832 onwards
(Chancery, Common Pleas, Exchequer, Queen's
Bench).
L. J. Eccl. Ditto (Ecclesiastical Cases).
L. J. M. C. Ditto (Magistrates' Cases).
L. J. P. M. & A. Ditto (Probate, Matrimonial, and Admiralty Cases).
L. R. A. & E. Law Reports, 1865-75 (Admiralty and Ecclesiastical).
L. R. C. P. Ex.
Q. B.
Ditto (Common Law).
L. R. Ch. Ditto (Chancery Appeals).
L. R. Eq. Ditto (Equity).
L. R. H. L. Ditto (House of Lords).
L. R. H. L. Sc. Ditto (Scotch and Divorce Appeals).
L. R. P. C. Ditto (Privy Council).
L. T. N. S. Law Times (New Series) Reports, 1859 onwards.
M. & S. Maule & Selwyn's Reports (King's Bench) 1813-17.
M. & W. Meeson & Welsby's Reports (Exchequer) 1836-47.
Marsh. Marshall's Reports (Common Pleas) 1813-1816.
Mer. Merivale's Reports (Chancery) 1815-17.
Moo. P. C. Moore's Privy Council Reports, 1836-62.
Moo. P. C. N.
S.
Ditto, New Series, 1862-73.
N. R. New Reports (Equity and Common Law) 1862-65.
Not. of Ca.
Notes of Cases (Ecclesiastical and Maritime) 1841-
50.
P. Law Reports, Probate Division, 1891 onwards.
79. P. D. Law Reports, Probate Division, 1875-90.
Phill. Phillimore's Reports (Ecclesiastical) 1809-1821.
Phill. Eccl. Law
Phillimore's Ecclesiastical Law of the Church of
England, 2 vols., 2nd ed., 1895.
P. Wms. Peere Williams' Reports (Chancery) 1695-1735.
Q. B. Queen's Bench Reports (Adolphus & Ellis) 1841-52.
Q. B. Law Reports (Queen's Bench) 1891-1900.
Q. B. D. Law Reports (Queen's Bench Division) 1875-1890.
Rob. Eccl. Robertson's Reports (Ecclesiastical) 1844-1853.
Sc. L. R. Scottish Law Reporter, 1865 onwards.
Sm. Churchw.
Smith's Law of Churchwardens and Sidesmen in the
Twentieth Century (Wells, Gardner, & Co., 2s.).
Str. Strange's Reports, 1715-47.
Strype's
Annals
John Strype's Annals of the Reformation (ed. 1824)
4 vols.
Sw. & Tr.
Swabey & Tristram's Reports (Probate and Divorce)
1858-65.
Taun. Taunton's Reports (Common Pleas) 1807-1819.
Times Law
Rep.
Times Law Reports, 1884 onwards.
T. R.
Durnford & East's Term Reports (King's Bench)
1785-1800.
Trist. Cons.
Judgm.
Tristram's Consistory Judgments, 1872-90.
Ventr. Ventris' Reports (King's Bench) 1668-91.
Ves. Vesey Junior's Reports (Chancery) 1789-1816.
Wats. Watson's Clergyman's Law, 4th ed., 1747.
Willes Willes Reports (Common Pleas) 1737-58.
Wils. Wilson's Reports (Common Law) 1743-74.
W. R. Weekly Reporter, 1853 onwards.
Yo. & Jer. Younge & Jervis's Reports (Exchequer) 1826-30.
82. 1. In every country where a Christian Church is permitted to exist,
the power and authority of her clergy to exercise their functions will
rest upon a triple basis and be subject to twofold restrictions and
limitations. In the first place, (i.) they derive their spiritual authority
from their ordination, and this authority is independent of the
particular Church to which they belong. But, in the next place, they
are bound on the one hand (ii.) to obey the regulations of the
Church of which they are the ministers, and must also, on the other
hand, (iii.) conform to the laws of the country in which they labour.
For they can only actively exercise their functions by the licence or
permission of the ruling power of that country, and subject to any
conditions which it may choose to impose. These principles apply
equally whether the Church is what we call established or not. The
only difference is that if the Church is established, her own
regulations are part of the law of the land; whereas, if she is not
established, the law of the land sanctions or suffers the existence of
these regulations as a private contract or arrangement between the
ministers and other members of the Church. But even in the case of
an established Church, her ministers will obviously be restricted in
the exercise of their functions by civil regulations which do not form
part of the ecclesiastical law. Thus there may be nothing in the law
of his Church to prevent a clergyman from holding a religious service
or preaching in a crowded thoroughfare. But in England and other
civilised countries any attempt to do so would be checked by the
existing laws against the obstruction of highways. In the following
pages no attempt will be made to point out the non-ecclesiastical
laws and limitations to which a parish priest is subject. For though
they necessarily affect himself and his spiritual work, they do so only
indirectly. They touch him not as a minister or even as a Christian,
but as a citizen; and they touch his spiritual work only in so far as
that work has a material and civil element.
83. 2. Confining then our attention to the ecclesiastical law under which
the parish priest holds his position and acts in this country, we note
in the first place, that the Church being here established, this
ecclesiastical law is equally the law of the Church and the law of the
State. This is true whatever be its origin, and however it came into
force; and it has always had this double aspect, since (with the
exception of the brief interval of the Commonwealth—a period which
is not recognised in our jurisprudence as having had any legal
existence) there never has been a time in our history when the
Church of England has not been the Established Church of the
nation. Portions of our Church system and Church law have had an
exclusively ecclesiastical origin, by canon or otherwise, and have
been adopted or acquiesced in by the State. Further portions have
been created by the joint or concurrent action of the Church and the
State. Other portions again have been due to the sole action of the
civil legislature, which has received the tacit assent of the Church
but has never been confirmed by any formal ecclesiastical
ratification. From whichever of these three sources any particular
point of our Church law may have been derived, its validity and
obligation is the same. It binds the Church and her ministers and
members irrespectively of its origin, and is at present in force unless
it has either been formally repealed or become obsolete and fallen
into desuetude.
84. 3. Again, like our civil law, our ecclesiastical law is in part written
and in part unwritten or customary. Foreign canon or conciliar law or
papal law is only binding in England so far as it has been received by
immemorial custom, and has thus become part of our unwritten law,
or has been incorporated into our written law by the ratification of
an Act of Parliament, or a canon or constitution of our own Church;
and the binding force of the English Pre-Reformation canons,
ordinances, and provincial constitutions stands on the same footing.
For the Commission authorised by the Act for the Submission of the
Clergy of 1533 to examine the English canons and constitutions,
and, with the king's assent, declare which of them should be in force
and which should be abrogated, was never appointed, although the
time for its appointment was extended by Acts of 1535 and 1543,
and the scope of its inquiry was extended by the latter Act so as to
include foreign canons and ordinances.[1] Consequently the only
written Church law is to be found in Acts of Parliament and the
Prayer-Book,[2] and in Post-Reformation canons, which, however,
except so far as they are confirmed by Act of Parliament, or declare
the unwritten law of the Church, are only binding on the clergy.[3] Of
these the chief are those known as the Canons of 1603, which were
agreed upon at the sitting of the Canterbury Convocation begun in
that year, and were separately passed two years afterwards by the
York Convocation. Many portions of them are, however, now
obsolete; and Canon 36 and the last words of Canon 102 have been
superseded by new canons made in 1865-66 and 1888. The Canons
of 1640 were passed after the dissolution of Parliament, which,
according to the custom of the realm, put an end also to the
existence of Convocation, and they have no legal force.[4]
85. 4. Much discussion has arisen upon a fourth source of Church law,
namely, the decisions of our ecclesiastical courts. It is important to
draw a clear distinction between legislative and judicial functions. A
court, whether ecclesiastical or civil, has nothing to do with enacting
laws. Its province is confined to interpreting them, when their
meaning is obscure or disputed. No doubt, in the course of this
interpretation, it will sometimes make law by deciding in a particular
way a point on which the legislature has left the matter in doubt,
and has not itself clearly laid down the law. Many questions affecting
the clergy and the Church have, in fact, been thus determined by
our civil as well as by our ecclesiastical tribunals. But if one of our
civil courts, in interpreting the civil law, delivers a decision which
does not commend itself to the common sense of the nation, it is
recognised that the remedy lies not in altering the constitution of the
court and endeavouring to obtain a fresh legal decision which shall
upset the other, but in obtaining an Act of Parliament expressly over-
ruling the unsatisfactory decision. If this is not done, the law may
have been technically judge-made, but it is acquiesced in and
assented to by Parliament and the nation. The same principle applies
to the decisions of ecclesiastical courts. The natural way of getting
rid of an obnoxious decision is not by fresh adjudication, but by
legislation. Until it has been reversed by one or other of these
means, the decision of a court, which de facto possesses
ecclesiastical jurisdiction, is binding upon the Church as part of her
law for the time being. We have somewhat lost sight of this
principle, owing to the extreme difficulty of obtaining any definition
or alteration of Church law by a legislative process. But the true
remedy lies in a healthy revival of the exercise of ecclesiastical
legislation, and not in an endeavour to make the ecclesiastical
judicature, whether as now existing or after a reform of the courts,
discharge legislative functions which are wholly outside its proper
province.
86. 5. The legal position of the parochial clergy depends for its ultimate
origin upon the legal status of the ancient Parish. The word is the
English form of the Greek παροικία (habitation), and the Latin
parochia, an expression originally synonymous with diocese (Gr.
διοίκησις, i.e. administration; Lat. diœcesis, used of a district or part
of a province in the Roman Empire), and applied to the territory
assigned to the jurisdiction of a bishop, which was served by him
and a college of clergy under him. But under Archbishop Theodore
(668-690) or shortly after his time the process was begun of
encouraging the lords of manors and great landowners to build
churches for themselves and their dependants, and devote the tithes
of their manors or estates to the maintenance of divine worship in
these churches, and the performance of religious duties among the
residents on the estates. This process was gradually extended
throughout the country, and, wherever it was adopted, the tithes
were assigned either to the priest for the time being in charge of the
church, who was in that case called the rector (governor of the
church) or parson (Lat. persona)[5] or to a monastery, the members
of which were then expected to serve the church. The manor or
estate, including any detached and outlying portions, became the
parish of the church, and developed into a territorial unit not only for
ecclesiastical but also for many civil purposes. Where the church was
served by a single rector, the landowner who had endowed it and his
successors after him were given in return the right of nominating to
the bishop a clerk in Holy Orders to become rector of the church, or,
in other words, they acquired the patronage or advowson[6] of the
benefice. The frequent cases of neglect in the service of the parish,
where a monastery was rector, led, in the thirteenth century, to the
requirement that in such cases a succession of individual priests
should be appointed to discharge the duty, with a definite portion of
the endowments of the benefice as their stipend for so doing. As a
rule the great tithes, being those of corn, grain, hay, and wood,
were reserved to the monastery, and were in consequence styled
rectorial tithes, while the officiating priest, who was styled a vicar,
87. was endowed with the remaining or small tithes, which consequently
were called vicarial. But in a few instances the officiating priest,
instead of becoming entitled to the small tithes, only received a fixed
monetary stipend. Where this occurred, he was called a perpetual
curate. It was the rule that rectories, whether in the hands of a
monastery or a succession of individual priests, should be endowed
not only with the tithes of the parish, but also with a house and
lands, which are called glebe; and sometimes these houses and
lands, or a part of the lands, were assigned towards the stipend of
the vicar.
88. 6. Towards the close of Henry VIII.'s reign the monasteries were
dissolved, and their rectories and the rectorial tithes of the parishes
and other endowments attached thereto, and the right of
nominating vicars or perpetual curates to the parishes passed, with
the rest of the monastic property, in some cases into the hands of
the Crown or of private individuals who received grants of them from
the Crown, while in other cases they went to the endowment of
episcopal sees or of colleges, hospitals, or other public institutions.
Whichever happened, the rectory and rectorial tithes became
thenceforth impropriate, and the vicar or perpetual curate was left
with the vicarial tithes and other endowments, or a stipend, as the
case might be, to serve the parish as the beneficed parish priest.
Later on, and particularly during the nineteenth century, the growth
of the population and the rapid increase of our urban centres, owing
to the steady migration from the villages to the towns, has rendered
the building of new churches and the creation of new ecclesiastical
areas a matter of pressing importance; and the same causes have
necessitated the employment in the larger parishes of additional
clergy, whether stipendiary or voluntary. In some cases an old parish
has been divided into distinct and separate parishes, each of which
has received a portion of the old church endowments, and has
become a rectory, vicarage, or perpetual curacy, according to the
status of the old parish;[7] or a vicarage has been converted into a
rectory upon a surrender of the rectorial tithes by the impropriator.
[8] But, as a rule, new ecclesiastical districts or parishes have been
formed and churches built without resorting to the old endowments;
and the Church Building and New Parishes Acts provided that the
ministers put in charge of these new districts or parishes and
churches should be perpetual curates, and should, like the old
rectors, vicars, and perpetual curates, be corporations, with
perpetual succession.[9] But in 1868 it was enacted that the
incumbent of every parish and new ecclesiastical parish, who was
authorised to publish banns, and solemnise marriages, churchings,
and baptisms in his church, and was not a rector, should, for the
89. purpose of designation only, be styled a vicar, and his benefice
should for the same purpose be styled a vicarage.[10] The modern
generic title, which includes every beneficed parish priest, is
incumbent. The proper and ancient term for rectors, vicars, and all
other parochial clergy, whether beneficed or unbeneficed, is curate,
as having the cure of souls within the parish.[11] But in modern
practice this term, when used by itself, is generally applied to the
unbeneficed or assistant curates in a parish.
90. 7. Two other classes of parochial clergy remain to be mentioned.
Where, for any reason, the incumbent is for a prolonged period
disabled from performing the duties of his office, a substitute will be
appointed under the designation of Minister in Charge. Again, in
some parishes, lectureships have been endowed, and are held by a
lecturer, who, in respect of his duties as such, is independent of the
incumbent.
91. Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com