Format source files to align with Liferay's coding standards.
Scanned 8/31/2026
Install to Claude Code
npx -y skills add liferay/liferay-portal --skill format-source --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Format Source?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/liferay-format-source)More formats (shields.io, HTML) on the badges page.
---
description: Format source files to align with Liferay's coding standards.
name: format-source
---
# Format Source
All the code is strictly formatted using the source formatter (Java, JavaScript, JSON, JSP, Markdown, properties, shell, XML, YAML, and others). This is how it works:
Run for a specific module:
```bash
cd <module-root> && <gradlew> formatSource
```
Run across the entire codebase:
```bash
cd <repo-root>/portal-impl && ant format-source-current-branch
```
`ant format-source-current-branch` only inspects committed files, so run it after creating the commit, and amend any formatter changes or fixes into that commit.
In both cases, if there are issues to be fixed, the formatter will list them. Fix them.
In addition to the automatic formatter, there is a set of manual rules that the formatter does not catch. The full workflow is to run the formatter, apply the manual rules, then rerun the formatter to clean up any fallout from the manual edits. When a manual rule conflicts with the automatic formatter, the formatter wins; leave the formatted code as it stands.
Skip generated files. The automatic formatter already does this via `BaseSourceProcessor.hasGeneratedTag`; apply the same rule to manual edits. A file is generated when it contains any of these unquoted markers:
- `@generated` — Service Builder, REST Builder, taglib generator (Java, by far the most common; ~18k files)
- `$ANTLR` — ANTLR-generated lexers and parsers
- `# This is a generated file.` — generated scripts
- `## Autogenerated` — generated Markdown and config
- `// Code generated ... DO NOT EDIT.` — `go generate` output, such as the controller-gen deepcopy and kubebuilder scaffolding under `cloud/`
These files are overwritten on the next build, so manual edits are lost and only pollute the diff.
## Shell Scripts
Shell scripts (`*.sh`) follow a separate style guide maintained in the `liferay-docker` repository, not the manual rules below. Defer their formatting to the `format-bash-source` skill and the `CODE_STYLE.md` it depends on. Resolve both files in this order:
1. **Local Checkout** — when `liferay-docker` sits beside this repository, read `../liferay-docker/.claude/skills/format-bash-source/SKILL.md` and `../liferay-docker/.claude/CODE_STYLE.md`.
1. **Remote Fallback** — when the local checkout is absent, download both files from `raw.githubusercontent.com` and read them from there:
```bash
temp_dir=$(mktemp -d)
curl \
--fail \
--output "${temp_dir}/format-bash-source.md" \
--silent \
--url "https://raw.githubusercontent.com/liferay/liferay-docker/refs/heads/master/.claude/skills/format-bash-source/SKILL.md"
curl \
--fail \
--output "${temp_dir}/CODE_STYLE.md" \
--silent \
--url "https://raw.githubusercontent.com/liferay/liferay-docker/refs/heads/master/.claude/CODE_STYLE.md"
```
For any `*.sh` file in scope, read the resolved `format-bash-source` `SKILL.md` and the `CODE_STYLE.md` it points to, then apply those rules in place of the manual rules in this document.
### Portal-Exclusive Rule: Bash Scripts Under `cloud/` Exit on First Failure
Every `liferay-portal` shell script follows the delegated Bash Code Style. Scripts under `cloud/` must also satisfy the rule below, which is exclusive to `liferay-portal` and has no counterpart in `liferay-docker`'s `CODE_STYLE.md`.
**Why:** Without an explicit fail-fast directive, a failing command silently passes through to the next; the `set -o errexit` / `set -o nounset` / `set -o pipefail` block at the top of the script makes failures, unset variables, and broken pipeline stages surface immediately.
**Examples:**
```diff
#!/usr/bin/env bash
+set -o errexit
+set -o nounset
+set -o pipefail
+
_execute "step-1"
_execute "step-2"
```
## Go Code
Go files (`*.go`) are outside the portal source formatter's set of file types, so the automatic formatter `gofmt` is used instead. The manual rules for Go are not listed below; they live in `.claude/rules/go-style.md`, which is scoped to `cloud/operator/**/*.go`. Read that file and apply it in place of the manual rules in this document.
The workflow mirrors the one above. Run `gofmt` across the Go module — the directory that holds `go.mod` — apply the rules from `.claude/rules/go-style.md`, then rerun `gofmt` to absorb any changes. Both the first pass and the rerun are the same command:
```bash
cd <go-module-root> && gofmt -w .
```
List the files that are not yet formatted without rewriting them:
```bash
cd <go-module-root> && gofmt -l .
```
When a rule and `gofmt` disagree, `gofmt` wins; leave the formatted code as it stands.
Skip generated Go files. Beyond the marker line listed above, a Go file whose name contains `zz_generated` is generated output that the next `go generate` rewrites.
## Rules
### Rule 1: Chained Method Call Ordering
**Why:** Consistent method order in chained calls makes it easier to scan for a specific call and reduces churn when new methods are added to the chain.
**Examples:**
```diff
Foo foo = builder.start(
arg
-).gamma(
- gammaArg
).alpha(
alphaArg
).beta(
betaArg
+).gamma(
+ gammaArg
).build();
```
### Rule 2: Method Parameter Ordering
**Why:** Consistent parameter order makes call sites easier to scan and reduces churn when new parameters are added.
**Examples:**
```diff
private void process(
- String charlie, long alpha, String beta,
+ long alpha, String beta, String charlie,
Object delta) {
```
### Rule 3: Sequential Assertion Ordering
**Why:** Consistent assertion order makes test failures easier to locate and reduces churn when new cases are added.
**Examples:**
```diff
Assert.assertEquals(1L, map.get("apple"));
-Assert.assertEquals(3L, map.get("cherry"));
Assert.assertEquals(2L, map.get("banana"));
+Assert.assertEquals(3L, map.get("cherry"));
```
### Rule 4: Local Variable Declaration Ordering
**Why:** Consistent declaration order makes it easier to find a variable and reduces churn when new locals are added.
**Examples:**
```diff
-Map<X, Y> beta = new HashMap<>();
-
boolean alpha = check();
+Map<X, Y> beta = new HashMap<>();
```
### Rule 5: Variable Name Type Suffix
**Why:** A type suffix makes the variable's type readable at the use site and prevents a generic local from shadowing a same-named string key, field, or call argument in scope.
**Examples:**
Strings and other reference types like `Date`, `JSONObject` get a type suffix.
```diff
-String foo = result.toString();
+String fooString = result.toString();
```
`int`, `long`, `boolean` keep descriptive names without a type suffix.
```diff
-int countInt = items.size();
-long timeLong = System.currentTimeMillis();
-boolean enabledBoolean = config.isEnabled();
+int count = items.size();
+long time = System.currentTimeMillis();
+boolean enabled = config.isEnabled();
```
Lists prefer a plural name; the `List` suffix is acceptable when no natural plural exists.
```diff
-List<Item> itemList = repository.findAll();
+List<Item> items = repository.findAll();
```
Maps prefer a descriptive name; the `Map` suffix is acceptable when no natural descriptor exists.
```diff
-Map<String, Item> itemMap = loadIndex();
+Map<String, Item> itemsByKey = loadIndex();
```
### Rule 6: Acronym Capitalization in Identifiers
**Why:** Treating acronyms as fully uppercase tokens keeps method, field, and variable names visually consistent with the surrounding API and avoids drift between camelCase and CamelCase variants for the same concept.
**Examples:**
```diff
-public String getUrl() {
+public String getURL() {
return _url;
}
```
```diff
-foo.getHtmlContent();
-bar.parseXmlString();
+foo.getHTMLContent();
+bar.parseXMLString();
```
### Rule 7: Quote Literal Tokens in Messages
**Why:** Wrapping literal identifiers, header values, content types, and similar tokens in double quotes inside log and exception messages separates the literal from the surrounding prose, so a reader can tell at a glance which words come from the data and which from the sentence.
**Examples:**
```diff
throw new IllegalArgumentException(
- "Request body has no application/json content");
+ "Request body has no \"application/json\" content");
```
```diff
-_log.warn("Missing header X-Custom-Header for request");
+_log.warn("Missing header \"X-Custom-Header\" for request");
```
Use escaped double quotes, not single quotes, to wrap the token.
```diff
-throw new IllegalArgumentException("Missing 'paths' object");
+throw new IllegalArgumentException("Missing \"paths\" object");
```
### Rule 8: Generic Index Variable Name
**Why:** When a method scope holds a single `int` index returned from `indexOf` or similar, naming it plainly `index` is shorter than a qualified name and matches the dominant convention; reuse the same `index` slot for sequential lookups in the same scope rather than introducing parallel qualified names.
**Examples:**
```diff
-int spaceIndex = endpoint.indexOf(' ');
+int index = endpoint.indexOf(' ');
-String prefix = endpoint.substring(0, spaceIndex);
-String suffix = endpoint.substring(spaceIndex + 1);
+String prefix = endpoint.substring(0, index);
+String suffix = endpoint.substring(index + 1);
```
When the value is reused for a second lookup in the same scope, reassign `index` rather than introducing a new variable.
```diff
-int firstSlashIndex = path.indexOf('/', 1);
-int secondSlashIndex = path.indexOf('/', firstSlashIndex + 1);
+int index = path.indexOf('/', 1);
+index = path.indexOf('/', index + 1);
```
### Rule 9: Map Entry Loop Naming
**Why:** Naming the loop variable `entry` and the extracted parts after the data they hold (typically `key`/`name` and `value`) keeps every map iteration readable in the same shape, regardless of the surrounding domain.
**Examples:**
```diff
-for (Map.Entry<String, Object> argumentEntry : arguments.entrySet()) {
- String paramName = argumentEntry.getKey();
- Object paramValue = argumentEntry.getValue();
+for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+ String name = entry.getKey();
+ Object value = entry.getValue();
```
### Rule 10: Test Method Predicate Phrasing
**Why:** Phrasing the predicate clause of a test method as `<property>Is<state>` rather than `<subject>Has<state><property>` makes a sorted method list group together by the property under test, and reads as a complete subject-verb-complement sentence.
**Examples:**
```diff
-public void testGetFooWhenBarHasNullBaz() throws Exception {
+public void testGetFooWhenBarBazIsNull() throws Exception {
```
```diff
-public void testGetFooWhenBarHasValidBaz() throws Exception {
+public void testGetFooWhenBarBazIsValid() throws Exception {
```
### Rule 11: Drop Redundant Nonnull Assertion Before Specific Assertions
**Why:** A subsequent assertion that calls a method on the same reference would already throw a `NullPointerException` if the value were null, so the explicit nonnull check adds noise without adding coverage.
**Examples:**
```diff
Foo foo = service.findFoo();
-Assert.assertNotNull(foo);
Assert.assertEquals("expected", foo.getName());
Assert.assertEquals(1L, foo.getId());
```
### Rule 12: Inline Single-Use Local Variables
**Why:** A local that is computed once and immediately handed to a single call site adds a name without adding meaning, so passing the expression directly removes a hop the reader otherwise has to follow.
**Examples:**
```diff
-Foo foo = makeFoo(arg);
-
-bar.consume(foo);
+bar.consume(makeFoo(arg));
```
```diff
-FooSchema fooSchema = computeSchema(args, root);
-
return Bar.builder(
).name(
"x"
).inputSchema(
- fooSchema
+ computeSchema(args, root)
).build();
```
Anonymous classes follow the same rule.
```diff
-FooDelegate fooDelegate = new FooDelegate() {};
-
-method.invoke(fooDelegate);
+method.invoke(new FooDelegate() {});
```
### Rule 13: Drop Narrative Assertion Messages
**Why:** A verbose explanatory message on `Assert.assertTrue` or `Assert.assertFalse` mostly restates what the predicate already shows; removing it lets the failing line and stack frame carry the diagnostic, and shortens the test.
**Examples:**
```diff
-Assert.assertTrue(
- StringBundler.concat(
- "Lookup must use the entity's ", id,
- ". Actual filter was: ", filterString),
- filterString.contains("(id=" + id + ")"));
+Assert.assertTrue(filterString.contains("(id=" + id + ")"));
```
### Rule 14: Declare Locals Next to First Use
**Why:** Declaring a local right before the statement that consumes it keeps related lines together and removes the need to scan back to a top-of-method block to recall what each value means. The same logic applies inside a `try` block: hoisting a local out of the `try` only makes sense when the `catch` or `finally` needs it; otherwise the wider scope adds visual noise and a reader has to confirm the local is not reused later.
**Examples:**
```diff
-long alpha = randomLong();
-String beta = "https://example.com";
-String gamma = randomString();
-
Foo foo = Mockito.mock(Foo.class);
+long alpha = randomLong();
+
Mockito.when(
foo.getAlpha()
).thenReturn(
alpha
);
+String beta = "https://example.com";
+
Mockito.when(
foo.getBeta()
).thenReturn(
beta
);
```
A local used only inside a `try` belongs inside the `try`:
```diff
-Foo foo = makeFoo();
-
-try {
- foo.consume();
-}
-catch (Exception exception) {
- _log.error("Failed", exception);
-}
+try {
+ Foo foo = makeFoo();
+
+ foo.consume();
+}
+catch (Exception exception) {
+ _log.error("Failed", exception);
+}
```
### Rule 15: Avoid Unboxing in Assertion Comparisons
**Why:** Calling `.longValue()`, `.intValue()`, or similar on the actual value forces a chain on the line being asserted; matching the boxed type on the expected side keeps the comparison readable on a single call.
**Examples:**
```diff
-Assert.assertEquals(
- 0L,
- threadLocal.getValue(
- ).longValue());
+Assert.assertEquals(Long.valueOf(0), threadLocal.getValue());
```
### Rule 16: Keep Default Override Adjacent to Declaration
**Why:** When a local is declared and then immediately patched if its initial value is null or otherwise unsuitable, keeping the `if` directly after the declaration treats the pair as one logical "compute alpha" step and avoids splitting it across an unrelated declaration block.
**Examples:**
```diff
String alpha = source.getAlpha();
+
+if (alpha == null) {
+ alpha = fallback.getAlpha();
+}
+
String beta = null;
String gamma = null;
Date delta = source.getDelta();
-
-if (alpha == null) {
- alpha = fallback.getAlpha();
-}
```
### Rule 17: Sort Sequential Setter Calls on Same Object
**Why:** When the same object is configured by a contiguous block of setter calls, ordering the calls alphabetically by method name (and then by argument) makes the configuration easier to scan and matches the convention used for assertions and declarations.
**Examples:**
```diff
Foo foo = new Foo();
-foo.setGamma(gamma);
foo.setAlpha(alpha);
foo.setBeta(beta);
+foo.setGamma(gamma);
```
**Exception:** When the receiver is a Service Builder entity (anything backed by a `*ModelImpl` — `FragmentEntryVersion`, `User`, `Group`, etc.), the automatic formatter's `JavaServiceObjectCheck` rewrites the setter block into model-field declaration order, not alphabetical order. Leave entity setter blocks as the formatter produces them; alphabetizing by hand will be reverted on the next `formatSource` run.
### Rule 18: Use Complete Sentences in User-Facing Messages
**Why:** Status, error, and notification strings that omit the linking verb read as fragments and translate poorly; restoring the auxiliary (`is`, `are`, `was`, `were`) turns the message into a complete sentence and matches the dominant phrasing already used across language files, log statements, and shell echoes. For failure messages, prefer the `Unable to <verb>` form over `Cannot <verb>`, `Failed to <verb>`, or `Error <verb>ing`.
**Examples:**
The rule applies to language property values.
```diff
-foo-not-allowed=Foo not allowed.
+foo-is-not-allowed=Foo is not allowed.
```
It applies to shell script messages.
```diff
-_log "Resource ${name} created successfully."
+_log "Resource ${name} was created successfully."
```
It applies to workflow and other YAML scripted output.
```diff
-echo "No entries found for ${id}."
+echo "No entries were found for ${id}."
```
It applies to Java exception and log messages.
```diff
-throw new IllegalStateException("Foo not found for id " + id);
+throw new IllegalStateException("Foo was not found for id " + id);
```
```diff
-_log.warn("Cannot delete foo " + id);
+_log.warn("Unable to delete foo " + id);
```
### Rule 19: Use "Delete" for Helpers That Delete Entities
**Why:** Liferay's persistence APIs spell entity destruction as `delete*` (`deleteUser`, `deleteEntry`); naming a private helper `_delete*` when its body calls a `delete*` service keeps the helper's verb aligned with the operation it performs.
**Examples:**
```diff
-private void _removeStaleFoos(Map<Long, List<String>> deletedIdsMap)
+private void _deleteStaleFoos(Map<Long, List<String>> deletedIdsMap)
throws Exception {
...
_fooLocalService.deleteFoo(foo);
}
```
Update the call sites at the same time.
```diff
-_removeStaleFoos(deletedIdsMap);
+_deleteStaleFoos(deletedIdsMap);
```
### Rule 20: Drop Unnecessary `L` Suffix on Long Literals
**Why:** When the receiving slot is already typed `long`, the `L` suffix on an integer literal adds visual noise without changing the value, since the integer is widened automatically.
**Examples:**
```diff
-public static final long TIMEOUT = 300000L;
+public static final long TIMEOUT = 300000;
```
### Rule 21: Avoid `iterator().next()` for First-Element Access
**Why:** A multimethod chain to reach the first element hides the intent behind two calls; pick the most direct accessor the type already offers so the call site reads as a single lookup.
**Examples:**
```diff
-Foo foo = page.getItems().iterator().next();
+Foo foo = page.getItems().get(0);
```
### Rule 22: Prefer `while` Over `do-while`
**Why:** A `while` loop checks its guard before the body, matching the dominant convention in the codebase; `do-while` belongs only to cases where the body genuinely must run before the first check.
**Examples:**
```diff
-do {
- advance();
-}
-while (!done());
+while (!done()) {
+ advance();
+}
```
### Rule 23: Blank Lines Delimit Logical Groups
**Why:** Blank lines mark the boundaries of a group; the statements inside a group read as one logical step. Within a group, ordering should be deterministic (alphabetical, argument order, call order); when the statements cannot be ordered, split them into separate groups with a blank line so the reader knows the order is intentional rather than arbitrary. Pairs that already read as one step (parallel setup, parallel assertions, paired declarations) should sit on adjacent lines without a blank line between them. Conversely, when one logical setup block finishes (configuring a context object, mocking a service, building a fixture), a single blank line marks the boundary so the next block reads as a new paragraph.
**Examples:**
Paired declarations:
```diff
Foo first = create("first");
-
Foo second = create("second");
```
Paired assertions on parallel results:
```diff
Assert.assertEquals("alpha", alpha.getName());
-
Assert.assertEquals("beta", beta.getName());
```
A blank line after a finished setup block separates it from the next:
```diff
themeDisplay.setSiteGroupId(siteGroupId);
themeDisplay.setUser(user);
+
ThemeRequest themeRequest = new ThemeRequest();
themeRequest.setLocale(locale);
```
### Rule 24: Single Space After a Period in Prose
**Why:** Two spaces after a period is a legacy typewriter convention; modern Liferay prose in comments, JSPs, language strings, and Markdown uses one.
**Examples:**
```diff
-// Compute the score. Cache it for next time.
+// Compute the score. Cache it for next time.
```
### Rule 25: Method-Name Plurality Matches Return-Type Plurality
**Why:** A method that returns a collection should signal that in its name, so a reader can predict the return type without checking the signature; a singular-sounding name on a `List` return forces a second look.
**Examples:**
```diff
-public List<Foo> getFooOverview() {
+public List<Foo> getFoos() {
return _fooLocalService.findAll();
}
```
### Rule 26: Mirror Methods Share a Naming Suffix
**Why:** When two methods are paired (data-fetch with count, get with getCount, by-key with by-key-count), they should differ only by the operation noun; a mismatched suffix hides the pairing from `git grep` and from the reader.
**Examples:**
```diff
public List<Foo> getFoosByGroupIds(long[] groupIds);
-public int getFoosCount(long[] groupIds);
+public int getFoosCountByGroupIds(long[] groupIds);
```
### Rule 27: "Cleanup" Is a Noun, "Clean Up" Is a Verb
**Why:** Treating `cleanup` and `clean up` as interchangeable produces noise in symbols and prose; the noun form names a thing (a method, a phase, a section header), the verb form describes an action.
**Examples:**
The verb form belongs in imperative comments and method names.
```diff
-// Cleanup the cache after the test runs
+// Clean up the cache after the test runs
```
The noun form belongs in identifiers and section headers.
```diff
-public void runCleanUp() {
+public void runCleanup() {
```
### Rule 28: Order Declarations to Match Their Downstream Usage
**Why:** When a block of declarations feeds straight into a downstream call sequence, ordering them to match that sequence lets the eye match left-to-right and reduces the chance of swapping two same-typed values at the call site; alphabetical breaks ties.
**Examples:**
When a block of locals feeds straight into a multiarg call, declare them in the call's argument order.
```diff
-String beta = computeBeta();
-String alpha = computeAlpha();
-String gamma = computeGamma();
+String alpha = computeAlpha();
+String beta = computeBeta();
+String gamma = computeGamma();
invoke(alpha, beta, gamma);
```
The same applies to Mockito mock declarations: order them in the sequence the system under test exercises them, with alphabetical as the tie-breaker. When the system under test calls `_serviceA` first and `_serviceB` second:
```diff
-Mockito.when(_serviceB.findFoo(id)).thenReturn(foo);
Mockito.when(_serviceA.exists(id)).thenReturn(true);
+Mockito.when(_serviceB.findFoo(id)).thenReturn(foo);
```
### Rule 29: Descriptive Lambda Parameter Names
**Why:** A bare `k`, `v`, or `e` lambda parameter forces the reader to scroll up to the enclosing call to know what it represents; a domain name reads on its own line.
**Examples:**
```diff
-fooMap.computeIfAbsent(name, k -> new HashSet<>());
+fooMap.computeIfAbsent(name, fooName -> new HashSet<>());
```
### Rule 30: Use Guard Clauses Over Nested Positive Conditions
**Why:** Inverting the condition and exiting early flattens the indentation of the bulk of the method, so the reader follows one straight column instead of an arrow-shaped nest.
**Examples:**
```diff
for (Foo foo : foos) {
- if ((foo != null) && foo.isEnabled()) {
- // thirty lines of work
- }
+ if ((foo == null) || !foo.isEnabled()) {
+ continue;
+ }
+
+ // thirty lines of work
}
```
### Rule 31: Prefer `@Before` and `@After` Over `@BeforeClass` and `@AfterClass`
**Why:** Instance-level setup gives each test a fresh state; class-level setup creates hidden coupling between tests that share the static fixture, and the failure mode is silent when one test mutates it.
**Examples:**
```diff
-@BeforeClass
-public static void setUpClass() throws Exception {
+@Before
+public void setUp() throws Exception {
_fixture = createFixture();
}
```
**Exception:** When the fixture is expensive to build (e.g. creating a new company), `@BeforeClass` can be the right call so the suite does not pay the cost per test.
### Rule 32: Group Members by Category, Sort Within the Group
**Why:** Interleaving categories scatters related members across the class; one blank-line-separated block per category, alphabetical within, keeps each group scannable and makes additions obvious in a diff. The same principle handles must-be-first or must-be-last entries (initialization, defaults, "all"): separate them from the sorted block with a blank line so the reader knows the leading or trailing position is intentional and the rest of the order has no further meaning.
**Examples:**
Group constants by category:
```diff
private static final String _ALPHA_X = "ax";
-private static final String _GAMMA_X = "gx";
private static final String _ALPHA_Y = "ay";
+
+private static final String _GAMMA_X = "gx";
private static final String _GAMMA_Y = "gy";
```
Separate must-be-first or must-be-last items from the sorted block:
```diff
public enum FooStep {
INIT,
+
ALPHA,
BETA,
GAMMA;
}
```
### Rule 33: Variable Name Matches the Expression Assigned to It
**Why:** When a local's name disagrees with the right-hand side, the reader has to verify which name is the truthful one at every use; pick the name from the expression so the two stay in sync.
**Examples:**
```diff
-long[] currentAndAncestorGroupIds = getReferencedGroupIds();
+long[] referencedGroupIds = getReferencedGroupIds();
```
### Rule 34: Add `@Override` on Every Overriding Method
**Why:** `@Override` makes the override explicit, lets the compiler catch signature drift in the supertype, and matches every other override in the codebase.
**Examples:**
```diff
+@Override
public void doSomething() {
super.doSomething();
}
```
### Rule 35: No ASCII-Art Separators in CSS Comments
**Why:** ASCII-art rules duplicate what indentation and blank lines already convey; matching the surrounding terse comment style keeps the file scannable and consistent.
**Examples:**
```diff
-/* ---------- Hide the column when narrow ---------- */
+/* Hide the column when narrow */
.foo .col {
display: none;
}
```
### Rule 36: Combine Consecutive `StringBundler.append` of Literal Strings
**Why:** Two literal-only `append` calls collapse to one without changing behavior, and the merged form lets the reader see the full literal in a single line.
**Examples:**
```diff
-sb.append("<?xml version=\"1.0\"?>");
-sb.append("<foo><bar>");
+sb.append("<?xml version=\"1.0\"?><foo><bar>");
```
### Rule 37: Drop the Fully-Qualified Class Name When the Class Is Imported
**Why:** Once a class is in the import block, the fully-qualified form at the use site adds noise and forces a line wrap; the simple name is what every other reference in the file already uses.
**Examples:**
```diff
import com.example.foo.FooResource;
// ...
-com.example.foo.FooResource fooResource = factory.create();
+FooResource fooResource = factory.create();
```
### Rule 38: Class-Level Constants Live at the Top of the Class, Sorted
**Why:** Constants scattered between methods force the reader to scan the whole class to confirm what is and is not a constant; a single sorted block at the top, after fields, is the canonical place to look.
**Examples:**
```diff
public class Foo {
+ private static final String _ALPHA = "alpha";
+
+ private static final String _BAR = "bar";
+
public void doFirst() {
- }
-
- private static final String _BAR = "bar";
-
- public void doSecond() {
}
- private static final String _ALPHA = "alpha";
+ public void doSecond() {
+ }
}
```
### Rule 39: Methods Used Only Inside the Class Must Be `private`
**Why:** Default or `public` visibility on a class-internal method overstates the contract; a reader cannot tell from the signature alone whether external callers exist, and tooling cannot prune the method when its callers go away.
**Examples:**
```diff
-void _doInternal() {
+private void _doInternal() {
// ...
}
```
### Rule 40: Method Names Start With a Verb
**Why:** A method represents an action, so its name should begin with one (`get`, `set`, `is`, `make`, `attach`, `verify`, …); a noun-only name reads as a field, not a call.
**Examples:**
```diff
-private boolean _osgiAware() {
+private boolean _isOsgiAware() {
return _bundleContext != null;
}
```
### Rule 41: Constant Names Lead With Their Group Prefix
**Why:** When constant names begin with their category (`<PREFIX>_<KIND>_<VALUE>`), an alphabetical sort places every member of the group together; leading with the value scatters the group across the file.
**Examples:**
```diff
-private static final String _DXP_ONLY_BUNDLE_NAME = "...";
-private static final String _ENTERPRISE_APP_BUNDLE_NAME = "...";
+private static final String _BUNDLE_NAME_DXP_ONLY = "...";
+private static final String _BUNDLE_NAME_ENTERPRISE_APP = "...";
```
### Rule 42: Blank Line Between Dependent Resources in `try`-With-Resources
**Why:** When a multiresource `try` mixes independent resources with one that consumes them, a blank line between the independent group and the consumer makes the dependency visible at the resource declaration level instead of forcing the reader to trace it through the body.
**Examples:**
```diff
try (
PreparedStatement preparedStatement1 = connection.prepareStatement(selectSQL);
PreparedStatement preparedStatement2 = connection.prepareStatement(updateSQL);
+
ResultSet resultSet = preparedStatement1.executeQuery()) {
```
### Rule 43: Do Not Wrap and Rethrow a Checked Exception
**Why:** Wrapping a caught exception in a generic runtime exception (or a framework-specific equivalent) hides both the original type and the original stack frame; the first choice is to let the original propagate by declaring it on the method.
**Examples:**
```diff
-try {
- parser.read(input);
-}
-catch (IOException ioException) {
- throw new PortalException(ioException);
-}
+parser.read(input);
```
**Exception:** When the method signature cannot be changed (an interface override, a callback whose contract forbids the checked type), wrapping is the necessary escape hatch. Use a known utility (`ReflectionUtil.throwException`, `_log.error` plus a domain-specific runtime type) and keep the original as the cause so the stack frame survives.
### Rule 44: Drop Defensive `Math.ceil` on Whole-Unit Division
**Why:** When converting a whole-unit value (milliseconds to seconds, bytes to kilobytes) for an input whose realistic values are already multiples of the divisor, `Math.ceil` adds a double promotion and a primitive cast that all collapse for any actual input; integer division does the same job.
**Examples:**
```diff
-long seconds = (long)Math.ceil(milliseconds / 1000.0);
+long seconds = milliseconds / 1000;
```
### Rule 45: Burrito — Declarations Before Configuration, Outer Before Inner
**Why:** Grouping all declarations together and all configuration together — with the outermost/output object first — makes the purpose of a block visible upfront and eliminates "spaghetti" code where create-and-configure steps are interleaved as you descend the dependency chain.
**Examples:**
**Output/accumulator declared first.** When a block builds a collection and returns or passes it on, declare the output variable at the top — before the input and source variables — even though it is populated later in the loop. As Brian Chan put it: "the clue is that you are returning X, so we want to wrap the vars around this."
```diff
+List<OutputType> results = new ArrayList<>();
+
InputType input = fetchInput(arg);
List<SourceType> sources = service.getSources(input.getId());
-List<OutputType> results = new ArrayList<>();
-
for (SourceType source : sources) {
results.add(transform(source));
}
return results;
```
The same applies to `Map`, `Set`, and `JSONObject` accumulators — whatever is being built and returned goes to the top.
**Outer objects declared first, then configured inner-to-outer.** When setting up a containment hierarchy (A wraps B wraps C), declare all objects upfront in outer-to-inner order, then configure them from innermost to outermost. Do not interleave declaration and configuration as you traverse the chain.
```diff
+ContainerA containerA = new ContainerA();
+ContainerB containerB = new ContainerB();
+
ContainerC containerC = new ContainerC();
containerC.setContent(content);
-ContainerB containerB = new ContainerB();
-
containerB.setContainerC(containerC);
-ContainerA containerA = new ContainerA();
-
containerA.setContainerB(containerB);
```
In Mockito-based tests the same rule applies: declare all mocks first in outer-to-inner order (the mock that wraps or receives others comes first), then write the `Mockito.when()` stubs from innermost to outermost.
```diff
+OuterMock outerMock = Mockito.mock(OuterMock.class);
+
InnerMock innerMock = Mockito.mock(InnerMock.class);
Mockito.when(
innerMock.getValue()
).thenReturn(
value
);
-OuterMock outerMock = Mockito.mock(OuterMock.class);
-
Mockito.when(
outerMock.getInner()
).thenReturn(
innerMock
);
```
This is the complement of Rule 14: intermediate input variables move down (next to first use), while output and wrapping variables move up (declared before the code that feeds them).
### Rule 46: Parameter-Aligned Variable Naming
**Why:** When a local variable carries a value directly into a method call, naming it after the method's parameter makes the call site self-documenting and eliminates the translation overhead for the reader who must otherwise reconcile a synonym with the method signature.
**Examples:**
When a local is passed as a specific named parameter, adopt the parameter's name rather than an alternative description of the same value.
```diff
-boolean httpsEnabled = _isHttpsEnabled();
+boolean secure = _isSecure();
String baseURL = _portal.getPortalURL(
company.getVirtualHostname(),
- _portal.getPortalServerPort(httpsEnabled), httpsEnabled);
+ _portal.getPortalServerPort(secure), secure);
```
The same applies when renaming a method or its parameter to match the vocabulary of the API it delegates to.
```diff
private Map<Locale, String> _getLocalizedMap(
- String value, Map<String, String> i18nMap) {
+ String defaultValue, Map<String, String> i18nMap) {
Map<Locale, String> localizedMap = LocalizedMapUtil.getLocalizedMap(
- contextAcceptLanguage.getPreferredLocale(), value, i18nMap);
+ contextAcceptLanguage.getPreferredLocale(), defaultValue, i18nMap);
```
**`Page<T>` variables use the plural form of the method that returned them.** If the method is `getItemsPage(...)`, name the variable `itemsPage`, not `itemPage`.
```diff
-Page<OrderItem> orderItemPage =
+Page<OrderItem> orderItemsPage =
service.getOrderIdOrderItemsPage(orderId, pagination);
-for (OrderItem orderItem : orderItemPage.getItems()) {
+for (OrderItem orderItem : orderItemsPage.getItems()) {
```
When you rename a local, propagate the new name to every call site, every parameter that passes it on, and every private helper that receives it.
### Rule 47: Chicago Title Case for Titles in Language Properties
**Why:** Titles in `Language.properties` — labels, headings, button text, dropdown options, filter values — follow the Chicago Manual of Style: capitalize the first word, the last word, and every major word (nouns, verbs, adjectives, adverbs, pronouns), and keep articles, coordinating conjunctions, and prepositions lowercase. Sentences and inline phrases stay in sentence case; full sentences fall under Rule 18.
**Examples:**
```diff
-some-key=Alpha of the bravo
+some-key=Alpha of the Bravo
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!