lightsoutAlpha

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" }