method-review
Skill44 starsChanged 4 months agoMITView on GitHub
Review code for method-level clarity by applying decomposition, conditional structure, boolean simplification, and unnecessary-machinery principles. Use when the user asks to simplify methods, clean up conditionals, flatten logic, reduce complexity, or improve how individual methods are expressed.
In this repository7 other files it gives its agents.
- commit-messagesSkill
- defragSkill
- diff-explainerSkill
- hierarchical-documentationSkill
- pentestSkill
- retroSkill
- structural-reviewSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 4 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 71
Separate caching from calculation: When a method memoizes, split the caching concern (||=) from the work it caches.
- Distinctive: line 77
Push conditionals up the decision tree: When independent conditions are scattered throughout a method, they create a combinatorial …
- Distinctive: line 79
Instead, branch early on the real decision and be honest about the fact that there are multiple distinct paths.
- Very specific: line 106
When you spot an if/else that returns true/false, check whether it's just identity, negation, &&, or || in disguise.
- Very specific: line 130
Don't build collections iteratively: When code initializes an empty collection and appends to it in a loop, it's usually reimplementing …
- Very specific: line 148
Push block logic to the objects being iterated: When a map, select, or each block reaches into an object's internals, that logic usually …
- Distinctive: line 154
Avoid special cases through better abstractions: Every conditional is a special case readers must parse.
- Distinctive: line 173
If the user asks "why" about a recommendation, check references.md for related blog posts to point them toward.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Method Review
Review whether each method is expressed as clearly as it could be. Walk changed or flagged methods and apply the principles below as lenses — not as a checklist to run exhaustively, but as tools to reach for when something reads harder than it should.
Process
- Identify new or modified methods in scope.
- For each method, check whether any of the principles below apply.
- For each finding: state what's hard to read, which principle it violates, and a concrete suggestion.
Principles
Decomposition
Single level of abstraction. A method should read at one level. When it mixes high-level intent with low-level mechanics, extract the low-level pieces into private methods so the public method reads as what happens and the private methods handle how.
# before
def process_order(order)
total = order.items.sum { |i| i.price * i.quantity }
total *= 0.9 if order.coupon_applied?
charge_card(order.card_token, total)
OrderMailer.confirmation(order).deliver_later
end
# after
def process_order(order)
total = calculate_total(order)
charge_card(order.card_token, total)
send_confirmation(order)
endSeparate branching from doing. Code that branches should only call out to other methods — it doesn't get to contain implementation details. This makes each branch's behavior independently readable, testable, and reusable.
# before
def save(for_real:)
if for_real
File.open("#{@title}.txt", "w") { |f| f.puts @title; f.puts @body }
else
$stdout.puts "PREVIEW"
$stdout.puts @title
end
end
# after
def save(for_real:)
if for_real
save_to_file
else
output_preview
end
endSeparate caching from calculation. When a method memoizes, split the
caching concern (||=) from the work it caches. This keeps each piece readable
and makes it easy to bypass the cache when needed.
Conditional structure
Push conditionals up the decision tree. When independent conditions are scattered throughout a method, they create a combinatorial explosion of paths. Instead, branch early on the real decision and be honest about the fact that there are multiple distinct paths. Flat conditionals at the top of a method are easier to read, reason about, and debug than deeply nested ones.
# Processing all steps of a multi-step form on one endpoint: independent
# conditionals on parameters vs step-based branching
#
# before: 16 possible paths, most "should never happen"
def process(params)
fetch_alma_mater if params[:school].present?
confirm_email if params[:email].present?
verify_number if params[:phone].present? && @user.active?
reset_timer if params[:school].present? || params[:email].present?
end
# after: 3 explicit paths
case step
when :bio then process_bio
when :address then process_address
when :socials then process_socials
endBoolean simplification
Conditionals that return booleans are often reimplementing basic operators.
When you spot an if/else that returns true/false, check whether it's
just identity, negation, &&, or || in disguise.
# before: reimplements negation
def reader?
if admin?
false
else
true
end
end
# after
def reader?
!admin?
endFor complex boolean methods with multiple variables, a truth table can help reveal which operator the early-return chain is reimplementing.
Unnecessary machinery
Don't build collections iteratively. When code initializes an empty
collection and appends to it in a loop, it's usually reimplementing map,
select, flat_map, or reduce.
# before
def signer_key_ids
result = []
signers.each { |s| result << s.key_id }
result
end
# after
def signer_key_ids
signers.map(&:key_id)
endPush block logic to the objects being iterated. When a map, select, or
each block reaches into an object's internals, that logic usually belongs on
the object as a method. This fixes feature envy and builds richer domain
objects. The pattern applies broadly to any complex block in Ruby, not just
map.
Avoid special cases through better abstractions. Every conditional is a special case readers must parse. Sometimes a better abstraction eliminates it entirely — null objects instead of nil checks, empty collections instead of presence guards, polymorphism instead of type branching.
Scope
- Takes the overall approach as settled. Does not question the decomposition into classes/services or the choice of data structures — those are macro-structural concerns.
- Restructures code (extracts methods, flattens conditionals) but gives extracted methods working names rather than polished ones — naming is a separate concern.
- Focuses on judgment calls about code structure. Mechanical Ruby/Rails idioms belong in rubocop. Framework-level judgment (trust ActiveRecord, reach for scopes) is a separate concern.
Further reading
If the user asks "why" about a recommendation, check references.md for related blog posts to point them toward.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

