class-surface
a method added to a class for logic that never touches the class's state
Agent checkadvisory by defaultbasecode
The argument
Keep the Class Surface Small
Prefer extracting logic into functions over adding instance methods: before graduation, non-exported helpers in the class file; after, files under the folder's common/utils/. The class surface stays limited to behavior that genuinely needs its state; logic is covered through the class's public API.
The proof
failsrc/http/HttpClient.ts
interface ConstructorParams {
baseUrl: string;
}
// `buildQuery` touches no state — it is on the surface only because it was
// written where the class was, and every consumer now sees it as API.
export class HttpClient {
private readonly baseUrl: string;
constructor({ baseUrl }: ConstructorParams) {
this.baseUrl = baseUrl;
}
get({ path, query }: { path: string; query: Record<string, string> }): string {
return `${this.baseUrl}${path}?${this.buildQuery({ query })}`;
}
buildQuery({ query }: { query: Record<string, string> }): string {
return Object.entries(query)
.map(([key, value]) => `${key}=${value}`)
.join('&');
}
}
passsrc/http/HttpClient.ts
interface ConstructorParams {
baseUrl: string;
}
// The stateless half is a co-located helper, so the class surface is only what
// genuinely needs the injected base url.
const buildQuery = ({ query }: { query: Record<string, string> }) =>
Object.entries(query)
.map(([key, value]) => `${key}=${value}`)
.join('&');
export class HttpClient {
private readonly baseUrl: string;
constructor({ baseUrl }: ConstructorParams) {
this.baseUrl = baseUrl;
}
get({ path, query }: { path: string; query: Record<string, string> }): string {
return `${this.baseUrl}${path}?${buildQuery({ query })}`;
}
}
Turn it down
Both lines go in your lightsout.config.json.
"standards-checks": { "class-surface": "advisory" }"standards-checks": { "class-surface": "off" }