Building Maintainable Software-java篇之Separate Concerns in Modules

  In a system that is both complex and tightly coupled, accidents are inevitable.
—Charles Perrow’s Normal Accidents
theory in one sentence





Guideline: • Avoid large modules in order to achieve loose coupling between them.
• Do this by assigning responsibilities to separate modules and hiding implementation details behind interfaces
• This improves maintainability because changes in a loosely coupled codebase are much easier to oversee and execute than changes in a tightly coupled codebase.




Remember that the concept of a module translates to a class in object-oriented languages such as Java.


Motivation

The biggest advantage of keeping classes small is that it provides a direct path toward loose coupling between classes. Loose coupling means that your class-level design will be much more flexible to facilitate future changes. By “flexibility” we mean that you can make changes while limiting unexpected effects of those changes. Thus, loose coupling allows developers to work on isolated parts of the codebase without creating change ripples that affect the rest of the codebase. A third advantage, which cannot be underestimated, is that the codebase as a whole will be much more open to less experienced developers.
 

Small, Loosely Coupled Modules Allow Developers to Work on Isolated Parts of the Codebase

When a class is tightly coupled with other classes, changes to the implementation of the class tend to create ripple effects through the codebase. For example, changing the interface of a public method leads to code changes everywhere the method is called. Besides the increased development effort, this also increases the risk that class modifications lead to bugs or inconsistencies in remote parts of the codebase.

Small, Loosely Coupled Modules Ease Navigation Through the Codebase

Not only does a good separation of concerns keep the codebase flexible to facilitate future changes, it also improves the analyzability of the codebase since classes encapsulate data and implement logic to perform a single task. Just as it is easier to name methods that only do one thing, classes also become easier to name and understand when they have one responsibility. Making sure classes have only one responsibility is also known as the single responsibility principle.

Small, Loosely Coupled Modules Prevent No-Go Areas for New Developers

Classes that violate the single responsibility principle become tightly coupled and accumulate a lot of code over time. As with the UserService example in the introduction of this chapter, these classes become intimidating to less experienced developers, and
even experienced developers are hesitant to make changes to their implementation. A codebase that has a large number of classes that lack a good separation of concerns is very difficult to adapt to new requirements.


How to Apply the Guideline In general, this guideline prescribes keeping your classes small (by addressing only one concern) and limiting the number of places where a class is called by code outside the class itself. Following are three development best practices that help to prevent tight coupling between classes in a codebase.

Split Classes to Separate Concerns

Designing classes that collectively implement functionality of a software system is the most essential step in modeling and designing object-oriented systems. In typical software projects we see that classes start out as logical entities that implement a single functionality but over time gain more responsibilities. To prevent classes from getting a large class smell, it is crucial that developers take action if a class has more than one responsibility by splitting up the class.

Hide Specialized Implementations Behind Interfaces

We can also achieve loose coupling by hiding specific and detailed implementations behind a high-level interface.

Replace Custom Code with Third-Party Libraries/Frameworks

A third situation that typically leads to tight module coupling are classes that provide generic or utility functionality. Classic examples are classes called StringUtils and FileUtils. Since these classes provide generic functionality, they are obviously called
from many places in the codebase. In many cases this is an occurrence of tight coupling that is hard to avoid. A best practice, though, is to keep the class sizes limited and to periodically review (open source) libraries and frameworks to check if they
can replace the custom implementation. Apache Commons and Google Guava are widespread libraries with frequently used utility functionality. In some cases, utility code can be replaced with new Java language features or a company-wide shared
library.




读书笔记:

Building Maintainable Software: Ten Guidelines for Future-Proof Code
by Joost Visser
Copyright © 2016 Software Improvement Group, B.V. All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are
also available for most titles (http://safaribooksonline.com). For more information, contact our corporate/
institutional sales department: 800-998-9938 or corporate@oreilly.com.
Acquisitions Editor: Rachel Roumeliotis
Editor: Nan Barber
Production Editor: Matthew Hacker
Copyeditor: Rachel Monaghan
Proofreader: Marta Justak
Indexer: WordCo Indexing Services, Inc.
Interior Designer: David Futato
Cover Designer: Randy Comer
Illustrator: Rebecca Demarest
February 2016: First Edition
Revision History for the First Edition
2016-01-25: First Release
See  http://shop.oreilly.com/product/0636920049159.do